diff --git a/.github/ci-setup-action/action.yml b/.github/ci-setup-action/action.yml index 93ad03f5941..8550966fe12 100644 --- a/.github/ci-setup-action/action.yml +++ b/.github/ci-setup-action/action.yml @@ -19,18 +19,11 @@ runs: echo HOME=$RUN_HOME >> $GITHUB_ENV mkdir -p $RUN_HOME - - name: Cache Submodules - id: cache-submodules - uses: actions/cache@v4 - with: - path: .git/modules - key: submodules-${{ hashFiles('.gitmodules') }}-spot-ebs - - name: Checkout Submodules shell: bash run: | git config --global --add safe.directory '*' - git submodule sync --recursive && git submodule update --init --recursive + git submodule update --init --recursive # TODO reconsider how jq gets into image - name: Setup jq diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fccc277a7de..493eb9adfd0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -700,10 +700,9 @@ jobs: values: 16-validators runner_type: 16core-tester-x86 timeout: 60 - # TODO(#9736) - # - test: transfer.test.ts - # values: 48-validators - # runner_type: 32core-tester-x86 + - test: transfer.test.ts + values: 48-validators + runner_type: 32core-tester-x86 - test: reorg.test.ts values: 16-validators runner_type: 16core-tester-x86-high-memory diff --git a/.github/workflows/publish-aztec-packages.yml b/.github/workflows/publish-aztec-packages.yml index 7369207ab0d..ad2d5b355d3 100644 --- a/.github/workflows/publish-aztec-packages.yml +++ b/.github/workflows/publish-aztec-packages.yml @@ -322,7 +322,11 @@ jobs: working-directory: ./aztec-up/terraform run: | terraform init - TAG=${{ env.DEPLOY_TAG }} + if [ "${{ github.ref_name }}" == "master" ]; then + TAG=master + else + TAG=${{ env.DEPLOY_TAG }} + fi export TF_VAR_VERSION=${TAG#aztec-packages-v} terraform apply -auto-approve diff --git a/avm-transpiler/Cargo.lock b/avm-transpiler/Cargo.lock index 0e6d94a39aa..47110353d7a 100644 --- a/avm-transpiler/Cargo.lock +++ b/avm-transpiler/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "acir" -version = "0.53.0" +version = "0.54.0" dependencies = [ "acir_field", "base64 0.21.7", @@ -18,7 +18,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.53.0" +version = "0.54.0" dependencies = [ "ark-bn254", "ark-ff", @@ -30,7 +30,7 @@ dependencies = [ [[package]] name = "acvm" -version = "0.53.0" +version = "0.54.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -44,7 +44,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "0.53.0" +version = "0.54.0" dependencies = [ "acir", "blake2", @@ -370,7 +370,7 @@ dependencies = [ [[package]] name = "brillig" -version = "0.53.0" +version = "0.54.0" dependencies = [ "acir_field", "serde", @@ -378,7 +378,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "0.53.0" +version = "0.54.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -675,7 +675,7 @@ dependencies = [ [[package]] name = "fm" -version = "0.37.0" +version = "0.38.0" dependencies = [ "codespan-reporting", "iter-extended", @@ -830,7 +830,7 @@ checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" [[package]] name = "iter-extended" -version = "0.37.0" +version = "0.38.0" [[package]] name = "itertools" @@ -935,7 +935,7 @@ dependencies = [ [[package]] name = "noirc_errors" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "base64 0.21.7", @@ -952,7 +952,7 @@ dependencies = [ [[package]] name = "noirc_printable_type" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "iter-extended", diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index b02a917d874..bf98c239648 100644 --- a/avm-transpiler/src/transpile.rs +++ b/avm-transpiler/src/transpile.rs @@ -306,16 +306,12 @@ pub fn brillig_to_avm(brillig_bytecode: &[BrilligOpcode]) -> (Vec< } BrilligOpcode::Return {} => avm_instrs .push(AvmInstruction { opcode: AvmOpcode::INTERNALRETURN, ..Default::default() }), - BrilligOpcode::Stop { return_data_offset, return_data_size } => { - avm_instrs.push(AvmInstruction { - opcode: AvmOpcode::RETURN, - indirect: Some(AddressingModeBuilder::default().build()), - operands: vec![ - AvmOperand::U16 { value: *return_data_offset as u16 }, - AvmOperand::U16 { value: *return_data_size as u16 }, - ], - ..Default::default() - }); + BrilligOpcode::Stop { return_data } => { + generate_return_instruction( + &mut avm_instrs, + &return_data.pointer, + &return_data.size, + ); } BrilligOpcode::Trap { revert_data } => { generate_revert_instruction( @@ -960,6 +956,28 @@ fn generate_revert_instruction( }); } +/// Generates an AVM RETURN instruction. +fn generate_return_instruction( + avm_instrs: &mut Vec, + return_data_pointer: &MemoryAddress, + return_data_size_offset: &MemoryAddress, +) { + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::RETURN, + indirect: Some( + AddressingModeBuilder::default() + .indirect_operand(return_data_pointer) + .direct_operand(return_data_size_offset) + .build(), + ), + operands: vec![ + AvmOperand::U16 { value: return_data_pointer.to_usize() as u16 }, + AvmOperand::U16 { value: return_data_size_offset.to_usize() as u16 }, + ], + ..Default::default() + }); +} + /// Generates an AVM MOV instruction. fn generate_mov_instruction( indirect: Option, @@ -1323,25 +1341,16 @@ fn handle_return( destinations: &Vec, inputs: &Vec, ) { - assert!(inputs.len() == 1); + assert!(inputs.len() == 2); assert!(destinations.len() == 0); - let (return_data_offset, return_data_size) = match inputs[0] { - ValueOrArray::HeapArray(HeapArray { pointer, size }) => (pointer, size as u32), - _ => panic!("Return instruction's args input should be a HeapArray"), + // First arg is the size, which is ignored because it's redundant. + let (return_data_offset, return_data_size) = match inputs[1] { + ValueOrArray::HeapVector(HeapVector { pointer, size }) => (pointer, size), + _ => panic!("Revert instruction's args input should be a HeapVector"), }; - avm_instrs.push(AvmInstruction { - opcode: AvmOpcode::RETURN, - indirect: Some( - AddressingModeBuilder::default().indirect_operand(&return_data_offset).build(), - ), - operands: vec![ - AvmOperand::U16 { value: return_data_offset.to_usize() as u16 }, - AvmOperand::U16 { value: return_data_size as u16 }, - ], - ..Default::default() - }); + generate_return_instruction(avm_instrs, &return_data_offset, &return_data_size); } // #[oracle(avmOpcodeRevert)] diff --git a/aztec-nargo/compile_then_postprocess.sh b/aztec-nargo/compile_then_postprocess.sh index c859377609d..03deed4d4cf 100755 --- a/aztec-nargo/compile_then_postprocess.sh +++ b/aztec-nargo/compile_then_postprocess.sh @@ -19,7 +19,7 @@ fi shift # remove the compile arg so we can inject --show-artifact-paths # Forward all arguments to nargo, tee output to console -artifacts_to_process=$($NARGO compile --show-artifact-paths $@ | tee /dev/tty | grep -oP 'Saved contract artifact to: \K.*') +artifacts_to_process=$($NARGO compile --inliner-aggressiveness 0 --show-artifact-paths $@ | tee /dev/tty | grep -oP 'Saved contract artifact to: \K.*') # NOTE: the output that is teed to /dev/tty will normally not be redirectable by the caller. # If the script is run via docker, however, the user will see this output on stdout and will be able to redirect. diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index 24942502962..4572f4629de 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = 1a334c80aa8d74abe81a216d7995b21dabef4dd3 - parent = 23c122d36091b3b756084584ecba59b800196d58 + commit = e13d72485ea6fc45715ce424b2e1a88f7d21376e + parent = 5997c823077d686107408caa8b4d148e115b62ac method = merge cmdver = 0.4.6 diff --git a/barretenberg/cpp/CMakeLists.txt b/barretenberg/cpp/CMakeLists.txt index ebbe45edd4d..302e997f434 100644 --- a/barretenberg/cpp/CMakeLists.txt +++ b/barretenberg/cpp/CMakeLists.txt @@ -31,7 +31,7 @@ option(DISABLE_AZTEC_VM "Don't build Aztec VM (acceptable if iterating on core p option(MULTITHREADING "Enable multi-threading" ON) option(OMP_MULTITHREADING "Enable OMP multi-threading" OFF) option(FUZZING "Build ONLY fuzzing harnesses" OFF) -option(ENABLE_PAR_ALGOS "Enable parallel algorithms" ON) +option(ENABLE_PAR_ALGOS "Enable parallel algorithms" OFF) option(COVERAGE "Enable collecting coverage from tests" OFF) option(ENABLE_ASAN "Address sanitizer for debugging tricky memory corruption" OFF) option(ENABLE_HEAVY_TESTS "Enable heavy tests when collecting coverage" OFF) diff --git a/barretenberg/cpp/pil/avm/alu.pil b/barretenberg/cpp/pil/avm/alu.pil index 4462161e917..7014885fbd5 100644 --- a/barretenberg/cpp/pil/avm/alu.pil +++ b/barretenberg/cpp/pil/avm/alu.pil @@ -84,17 +84,21 @@ namespace alu(256); pol commit cmp_gadget_input_b; pol commit cmp_gadget_result; pol commit cmp_gadget_gt; + pol commit cmp_gadget_non_ff_gt; // We use the comparison gadget to test GT for the following operations - cmp_gadget_gt = op_lt + op_lte + op_div + op_shr + op_shl; + pol CMP_GADGET_GT = op_lt + op_lte + op_div + op_shr + op_shl; + cmp_gadget_gt = CMP_GADGET_GT * ff_tag; + cmp_gadget_non_ff_gt = CMP_GADGET_GT * (1 - ff_tag); + // The cmp gadget is on when we are either testing GT or EQ - cmp_gadget_sel - (cmp_gadget_gt + op_eq) = 0; + cmp_gadget_sel - (cmp_gadget_gt + op_eq + cmp_gadget_non_ff_gt) = 0; // Permutation to the Comparison Gadget #[PERM_CMP_ALU] - cmp.sel_cmp {cmp.clk, cmp.input_a, cmp.input_b, cmp.result, cmp.op_eq, cmp.op_gt} + cmp.sel_cmp {cmp.clk, cmp.input_a, cmp.input_b, cmp.result, cmp.op_eq, cmp.op_gt, cmp.op_non_ff_gt} is - cmp_gadget_sel {clk, cmp_gadget_input_a, cmp_gadget_input_b, cmp_gadget_result, op_eq, cmp_gadget_gt }; + cmp_gadget_sel {clk, cmp_gadget_input_a, cmp_gadget_input_b, cmp_gadget_result, op_eq, cmp_gadget_gt, cmp_gadget_non_ff_gt }; // =============== HELPER POLYNOMIAL RELATIONS ================================================= @@ -143,6 +147,7 @@ namespace alu(256); // This holds the product over the integers // (u1 multiplication only cares about a_lo and b_lo) + // TODO(9937): The following is not well constrained as this expression overflows the field. pol PRODUCT = a_lo * b_lo + (1 - u1_tag) * (LIMB_BITS_POW * partial_prod_lo + MAX_BITS_POW * (partial_prod_hi + a_hi * b_hi)); // =============== ADDITION/SUBTRACTION Operation Constraints ================================================= diff --git a/barretenberg/cpp/pil/avm/gadgets/cmp.pil b/barretenberg/cpp/pil/avm/gadgets/cmp.pil index 2664880a55c..bca80423689 100644 --- a/barretenberg/cpp/pil/avm/gadgets/cmp.pil +++ b/barretenberg/cpp/pil/avm/gadgets/cmp.pil @@ -16,6 +16,25 @@ namespace cmp(256); pol commit input_b; pol commit result; + // ========= NON FF GT Short-circuit computation =============================== + // If this is a non-ff check, we can short circuit (a > b) by checking + // 0 < a - b - 1 < 2**128 --> i.e. we just check we dont underlow which for "small" sized 128-bit number is just a + // single 128 bit range check + // This will be constrained by the calling function - maybe through instruction decomposition + pol commit op_non_ff_gt; + // Value of a - b + pol commit diff; + + pol A_GT_B = input_a - input_b - 1; + pol B_GTE_A = input_b - input_a; + op_non_ff_gt * (diff - (A_GT_B * result) - (B_GTE_A * (1 - result))) = 0; + + #[PERM_RNG_NON_FF_CMP] + range_check.cmp_non_ff_rng_chk {range_check.clk, range_check.value} + is + op_non_ff_gt {range_chk_clk, diff}; + + // ========= FF GT computation =============================== // We range check two columns per row of the cmp gadget, the lo and hi bit ranges resp. #[PERM_RNG_CMP_LO] range_check.cmp_lo_bits_rng_chk {range_check.clk, range_check.value} @@ -32,7 +51,7 @@ namespace cmp(256); pol commit op_eq; pol commit op_gt; - sel_cmp = op_eq + op_gt; + sel_cmp = op_eq + op_gt + op_non_ff_gt; // There are some standardised constraints on this gadget // The result is always a boolean diff --git a/barretenberg/cpp/pil/avm/gadgets/range_check.pil b/barretenberg/cpp/pil/avm/gadgets/range_check.pil index 872c12f0b8c..d3d11168212 100644 --- a/barretenberg/cpp/pil/avm/gadgets/range_check.pil +++ b/barretenberg/cpp/pil/avm/gadgets/range_check.pil @@ -201,6 +201,9 @@ namespace range_check(256); // We range check 128 bits in the cmp trace cmp_lo_bits_rng_chk * (rng_chk_bits - 128) = 0; cmp_hi_bits_rng_chk * (rng_chk_bits - 128) = 0; + // For non FF + pol commit cmp_non_ff_rng_chk; + cmp_non_ff_rng_chk * (rng_chk_bits - 128) = 0; // ==== ALU TRACE RANGE CHECKS ==== pol commit alu_rng_chk; diff --git a/barretenberg/cpp/pil/avm/gas.pil b/barretenberg/cpp/pil/avm/gas.pil index 8894346f10c..32b1a858c86 100644 --- a/barretenberg/cpp/pil/avm/gas.pil +++ b/barretenberg/cpp/pil/avm/gas.pil @@ -94,13 +94,20 @@ namespace main(256); // ========= Initialize Range Check Gadget =============================== // We range check that the absolute value of the differences between each row of l2 and da gas are 32 bits. - #[PERM_RNG_GAS_L2] - range_check.gas_l2_rng_chk {range_check.clk, range_check.value} - is - is_gas_accounted {main.clk, main.abs_l2_rem_gas }; + pol commit l2_gas_u16_r0; + pol commit l2_gas_u16_r1; + main.abs_l2_rem_gas = l2_gas_u16_r0 + l2_gas_u16_r1 * 2**16; - #[PERM_RNG_GAS_DA] - range_check.gas_da_rng_chk {range_check.clk, range_check.value} - is - is_gas_accounted {main.clk, main.abs_da_rem_gas }; + #[LOOKUP_L2_GAS_RNG_CHK_0] + is_gas_accounted { l2_gas_u16_r0 } in main.sel_rng_16 { main.clk }; + #[LOOKUP_L2_GAS_RNG_CHK_1] + is_gas_accounted { l2_gas_u16_r1 } in main.sel_rng_16 { main.clk }; + pol commit da_gas_u16_r0; + pol commit da_gas_u16_r1; + main.abs_da_rem_gas = da_gas_u16_r0 + da_gas_u16_r1 * 2**16; + + #[LOOKUP_DA_GAS_RNG_CHK_0] + is_gas_accounted { da_gas_u16_r0 } in main.sel_rng_16 { main.clk }; + #[LOOKUP_DA_GAS_RNG_CHK_1] + is_gas_accounted { da_gas_u16_r1 } in main.sel_rng_16 { main.clk }; diff --git a/barretenberg/cpp/pil/avm/kernel.pil b/barretenberg/cpp/pil/avm/kernel.pil index 3b6594c297b..03da4e3d1f7 100644 --- a/barretenberg/cpp/pil/avm/kernel.pil +++ b/barretenberg/cpp/pil/avm/kernel.pil @@ -183,7 +183,7 @@ namespace main(256); + sel_op_emit_nullifier + sel_op_l1_to_l2_msg_exists + sel_op_emit_unencrypted_log + sel_op_emit_l2_to_l1_msg + sel_op_sload + sel_op_sstore; #[KERNEL_OUTPUT_ACTIVE_CHECK] - KERNEL_OUTPUT_SELECTORS * (1 - sel_q_kernel_output_lookup) = 0; + KERNEL_OUTPUT_SELECTORS * (1 - sel_q_kernel_output_lookup) * (1 - op_err) = 0; // TODO(#8287): Reintroduce constraints #[KERNEL_OUTPUT_LOOKUP] diff --git a/barretenberg/cpp/pil/avm/main.pil b/barretenberg/cpp/pil/avm/main.pil index 5242f3db0da..7317de68c91 100644 --- a/barretenberg/cpp/pil/avm/main.pil +++ b/barretenberg/cpp/pil/avm/main.pil @@ -85,6 +85,9 @@ namespace main(256); // TODO: Opcode value (byte) will be constrained by the bytecode validation circuit pol commit opcode_val; + //===== MISC ====================================================== + pol commit sel_op_debug_log; + //===== Gadget Selectors ====================================================== pol commit sel_op_radix_be; pol commit sel_op_sha256; @@ -246,6 +249,8 @@ namespace main(256); sel_op_sload * (1 - sel_op_sload) = 0; sel_op_sstore * (1 - sel_op_sstore) = 0; + sel_op_debug_log * (1 - sel_op_debug_log) = 0; + sel_op_radix_be * (1 - sel_op_radix_be) = 0; sel_op_sha256 * (1 - sel_op_sha256) = 0; sel_op_poseidon2 * (1 - sel_op_poseidon2) = 0; @@ -351,13 +356,16 @@ namespace main(256); #[SUBOP_FDIV_W_IN_TAG_FF] sel_op_fdiv * (w_in_tag - constants.MEM_TAG_FF) = 0; - // op_err cannot be maliciously activated for a non-relevant + // TODO: op_err cannot be maliciously activated for a non-relevant // operation selector, i.e., op_err == 1 ==> sel_op_fdiv || sel_op_XXX || ... // op_err * (sel_op_fdiv + sel_op_XXX + ... - 1) == 0 // Note that the above is even a stronger constraint, as it shows // that exactly one sel_op_XXX must be true. - #[SUBOP_ERROR_RELEVANT_OP] - op_err * ((sel_op_fdiv + sel_op_div + sel_op_get_contract_instance) - 1) = 0; + // #[SUBOP_ERROR_RELEVANT_OP] + // op_err * (1 - tag_err) * ((sel_op_fdiv + sel_op_div + sel_op_get_contract_instance) - 1) = 0; + + #[TAG_ERR_IMPLIES_OP_ERR] + tag_err * (1 - op_err) = 0; // TODO: constraint that we stop execution at the first error (tag_err or op_err) // An error can only happen at the last sub-operation row. @@ -426,7 +434,7 @@ namespace main(256); + sel_op_ecadd + sel_op_msm; pol SEL_ALL_MEMORY = sel_op_mov + sel_op_set; pol OPCODE_SELECTORS = sel_op_fdiv + sel_op_calldata_copy + sel_op_get_contract_instance - + sel_op_returndata_size + sel_op_returndata_copy + + sel_op_returndata_size + sel_op_returndata_copy + sel_op_debug_log + SEL_ALL_ALU + SEL_ALL_BINARY + SEL_ALL_MEMORY + SEL_ALL_GADGET + KERNEL_INPUT_SELECTORS + KERNEL_OUTPUT_SELECTORS + SEL_ALL_LEFTGAS + SEL_ALL_CTRL_FLOW; @@ -486,9 +494,9 @@ namespace main(256); #[MOV_MAIN_SAME_TAG] sel_op_mov * (r_in_tag - w_in_tag) = 0; - // Predicate to activate the copy of intermediate registers to ALU table. If tag_err == 1, - // the operation is not copied to the ALU table. - sel_alu = SEL_ALL_ALU * (1 - tag_err) * (1 - op_err); + // Predicate to activate the copy of intermediate registers to ALU table. If op_err == 1, + // the operation is not copied to the ALU table. Note that it encompasses tag_err == 1. + sel_alu = SEL_ALL_ALU * (1 - op_err); // Dispatch the correct in_tag for alu SEL_ALU_R_TAG * (alu_in_tag - r_in_tag) = 0; @@ -506,8 +514,8 @@ namespace main(256); //===== Memory Slice Constraints ============================================ pol commit sel_slice_gadget; // Selector to activate a slice gadget operation in the gadget (#[PERM_MAIN_SLICE]). - // Activate only if tag_err is disabled or retsize (ib) is non-zero - ib * (1 - tag_err) * (sel_op_calldata_copy + sel_op_external_return - sel_slice_gadget)= 0; + // Activate only if op_err is disabled or retsize (ib) is non-zero + ib * (1 - op_err) * (sel_op_calldata_copy + sel_op_external_return - sel_slice_gadget)= 0; //====== Inter-table Constraints ============================================ @@ -537,7 +545,7 @@ namespace main(256); // sel_Bin is not explicitly constrained to be boolean, however this is enforced through // the operation decomposition step during bytecode unpacking. #[BIN_SEL_2] - sel_bin = sel_op_and + sel_op_or + sel_op_xor; + sel_bin = (sel_op_and + sel_op_or + sel_op_xor) * (1 - op_err); #[PERM_MAIN_BIN] sel_bin {clk, ia, ib, ic, bin_op_id, r_in_tag} diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 66a4a831a6f..8daccc33257 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -359,7 +359,7 @@ void client_ivc_prove_output_all_msgpack(const std::string& bytecodePath, // TODO(https://github.com/AztecProtocol/barretenberg/issues/1101): remove use of auto_verify_mode ClientIVC ivc; ivc.auto_verify_mode = true; - ivc.trace_structure = TraceStructure::E2E_FULL_TEST; + ivc.trace_settings.structure = TraceStructure::E2E_FULL_TEST; // Accumulate the entire program stack into the IVC // TODO(https://github.com/AztecProtocol/barretenberg/issues/1116): remove manual setting of is_kernel once databus @@ -448,7 +448,7 @@ bool foldAndVerifyProgram(const std::string& bytecodePath, const std::string& wi ClientIVC ivc; ivc.auto_verify_mode = true; - ivc.trace_structure = TraceStructure::SMALL_TEST; + ivc.trace_settings.structure = TraceStructure::SMALL_TEST; auto program_stack = acir_format::get_acir_program_stack( bytecodePath, witnessPath, false); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): this @@ -501,7 +501,7 @@ void client_ivc_prove_output_all(const std::string& bytecodePath, // TODO(https://github.com/AztecProtocol/barretenberg/issues/1101): remove use of auto_verify_mode ClientIVC ivc; ivc.auto_verify_mode = true; - ivc.trace_structure = TraceStructure::E2E_FULL_TEST; + ivc.trace_settings.structure = TraceStructure::E2E_FULL_TEST; auto program_stack = acir_format::get_acir_program_stack( bytecodePath, witnessPath, false); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): this diff --git a/barretenberg/cpp/src/barretenberg/bb/readme.md b/barretenberg/cpp/src/barretenberg/bb/readme.md index 721e54b7695..9483200b214 100644 --- a/barretenberg/cpp/src/barretenberg/bb/readme.md +++ b/barretenberg/cpp/src/barretenberg/bb/readme.md @@ -21,6 +21,10 @@ TODO: https://github.com/AztecProtocol/aztec-packages/issues/7511 For quick reference: +- Noir v0.38.0 <> BB v0.61.0 +- Noir v0.37.0 <> BB v0.61.0 +- Noir v0.36.0 <> BB v0.58.0 +- Noir v0.35.0 <> BB v0.56.0 - Noir v0.34.0 <> BB v0.55.0 - Noir v0.33.0 <> BB v0.47.1 - Noir v0.32.0 <> BB v0.46.1 diff --git a/barretenberg/cpp/src/barretenberg/benchmark/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/benchmark/CMakeLists.txt index e76758ca571..31db5c02858 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/benchmark/CMakeLists.txt @@ -17,3 +17,4 @@ add_subdirectory(append_only_tree_bench) add_subdirectory(ultra_bench) add_subdirectory(stdlib_hash) add_subdirectory(circuit_construction_bench) +add_subdirectory(mega_memory_bench) diff --git a/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp index 12cc8718749..f85bc066ce6 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp @@ -34,7 +34,7 @@ class ClientIVCBench : public benchmark::Fixture { BENCHMARK_DEFINE_F(ClientIVCBench, Full)(benchmark::State& state) { ClientIVC ivc; - ivc.trace_structure = TraceStructure::CLIENT_IVC_BENCH; + ivc.trace_settings.structure = TraceStructure::CLIENT_IVC_BENCH; auto total_num_circuits = 2 * static_cast(state.range(0)); // 2x accounts for kernel circuits auto mocked_vkeys = mock_verification_keys(total_num_circuits); diff --git a/barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/eccvm.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/eccvm.bench.cpp index f796d893068..af7ca5ea43d 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/eccvm.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/eccvm.bench.cpp @@ -61,7 +61,7 @@ void eccvm_prove(State& state) noexcept Builder builder = generate_trace(target_num_gates); ECCVMProver prover(builder); for (auto _ : state) { - auto proof = prover.construct_proof(); + ECCVMProof proof = prover.construct_proof(); }; } diff --git a/barretenberg/cpp/src/barretenberg/benchmark/mega_memory_bench/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/benchmark/mega_memory_bench/CMakeLists.txt new file mode 100644 index 00000000000..f35647268d7 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/benchmark/mega_memory_bench/CMakeLists.txt @@ -0,0 +1,5 @@ +barretenberg_module( + mega_memory_bench + ultra_honk + stdlib_primitives +) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/benchmark/mega_memory_bench/mega_memory.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/mega_memory_bench/mega_memory.bench.cpp new file mode 100644 index 00000000000..29d58f16606 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/benchmark/mega_memory_bench/mega_memory.bench.cpp @@ -0,0 +1,344 @@ +#include "barretenberg/stdlib/primitives/field/field.hpp" +#include "barretenberg/stdlib/primitives/plookup/plookup.hpp" +#include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" +#include "barretenberg/ultra_honk/decider_proving_key.hpp" + +#include + +using namespace benchmark; +using namespace bb; +using namespace bb::plookup; + +namespace { +auto& engine = numeric::get_debug_randomness(); +} + +using DeciderProvingKey = DeciderProvingKey_; +using Builder = MegaCircuitBuilder; +using field_ct = stdlib::field_t; +using witness_ct = stdlib::witness_t; +using plookup_read = stdlib::plookup_read; + +static constexpr size_t NUM_SHORT = 10; + +void fill_ecc_op_block(Builder& builder) +{ + const auto point = g1::affine_element::random_element(); + const auto scalar = fr::random_element(); + const size_t num_to_add((builder.blocks.ecc_op.get_fixed_size() - NUM_SHORT) >> 1); // each accum call adds two rows + for (size_t idx = 0; idx < num_to_add; idx++) { + builder.queue_ecc_mul_accum(point, scalar); + } +} + +void fill_pub_inputs_block(Builder& builder) +{ + for (size_t idx = 0; idx < builder.blocks.pub_inputs.get_fixed_size() - NUM_SHORT; idx++) { + builder.add_public_variable(fr::random_element()); + } +} + +void fill_databus_blocks(Builder& builder) +{ + static constexpr size_t NUM_BUS_IDS(3); + const size_t num_gates_per_bus_id((builder.blocks.busread.get_fixed_size() - NUM_SHORT) / NUM_BUS_IDS); + for (size_t idx = 1; idx < num_gates_per_bus_id + 1; idx++) { // start at 1 to avoid / by zero below + const uint32_t idx_1_1 = builder.add_variable(fr::random_element()); + const uint32_t idx_1_2 = builder.add_variable(static_cast(fr::random_element()) % idx); + builder.add_public_calldata(idx_1_1); + builder.read_calldata(idx_1_2); + const uint32_t idx_2_1 = builder.add_variable(fr::random_element()); + const uint32_t idx_2_2 = builder.add_variable(static_cast(fr::random_element()) % idx); + builder.add_public_secondary_calldata(idx_2_1); + builder.read_secondary_calldata(idx_2_2); + const uint32_t idx_3_1 = builder.add_variable(fr::random_element()); + const uint32_t idx_3_2 = builder.add_variable(static_cast(fr::random_element()) % idx); + builder.add_public_return_data(idx_3_1); + builder.read_return_data(idx_3_2); + } +} + +void fill_delta_range_block(Builder& builder) +{ + // At the moment the trace has space for 90k delta range gates but I don't think it's possible to use them all + // because there is not enough capacity in the arithmetic block! + + const uint32_t idx_1 = builder.add_variable(1 << 0); + builder.create_range_constraint(idx_1, 1, "whoops"); + const uint32_t idx_2 = builder.add_variable(1 << 1); + builder.create_range_constraint(idx_2, 2, "whoops"); + const uint32_t idx_3 = builder.add_variable(1 << 2); + builder.create_range_constraint(idx_3, 3, "whoops"); + const uint32_t idx_4 = builder.add_variable(1 << 3); + builder.create_range_constraint(idx_4, 4, "whoops"); + const uint32_t idx_5 = builder.add_variable(1 << 4); + builder.create_range_constraint(idx_5, 5, "whoops"); + const uint32_t idx_6 = builder.add_variable(1 << 5); + builder.create_range_constraint(idx_6, 6, "whoops"); + const uint32_t idx_7 = builder.add_variable(1 << 6); + builder.create_range_constraint(idx_7, 7, "whoops"); + const uint32_t idx_8 = builder.add_variable(1 << 7); + builder.create_range_constraint(idx_8, 8, "whoops"); + const uint32_t idx_9 = builder.add_variable(1 << 8); + builder.create_range_constraint(idx_9, 9, "whoops"); + const uint32_t idx_10 = builder.add_variable(1 << 9); + builder.create_range_constraint(idx_10, 10, "whoops"); + const uint32_t idx_11 = builder.add_variable(1 << 10); + builder.create_range_constraint(idx_11, 11, "whoops"); + const uint32_t idx_12 = builder.add_variable(1 << 11); + builder.create_range_constraint(idx_12, 12, "whoops"); + const uint32_t idx_13 = builder.add_variable(1 << 12); + builder.create_range_constraint(idx_13, 13, "whoops"); + const uint32_t idx_14 = builder.add_variable(1 << 13); + builder.create_range_constraint(idx_14, 14, "whoops"); + // the above range constraints as 2759 gates + static constexpr size_t NUM_GATES_ADDED_FOR_ALL_DEFAULT_RANGES = 2759; + + size_t num_range_constraints = 14; + + auto& range_block = builder.blocks.delta_range; + auto& arith_block = builder.blocks.arithmetic; + + const auto range_block_has_space = [&range_block, &num_range_constraints]() { + return num_range_constraints < + 4 * (range_block.get_fixed_size() - NUM_GATES_ADDED_FOR_ALL_DEFAULT_RANGES - NUM_SHORT); + }; + + const auto arith_block_has_space = [&arith_block]() { + return arith_block.size() < arith_block.get_fixed_size() - 100; + }; + + while (range_block_has_space() && arith_block_has_space()) { + const uint32_t w_idx = builder.add_variable(1023); + builder.create_range_constraint(w_idx, 10, "failed to create range constraint"); + num_range_constraints++; + } +} + +void fill_arithmetic_block(Builder& builder) +{ + const uint32_t idx_1 = builder.add_variable(fr::random_element()); + const uint32_t idx_2 = builder.add_variable(fr::random_element()); + const uint32_t idx_3 = builder.add_variable(fr::random_element()); + const uint32_t idx_4 = builder.add_variable(fr::random_element()); + while (builder.blocks.arithmetic.size() < builder.blocks.arithmetic.get_fixed_size() - 10 * NUM_SHORT) { + builder.create_big_add_gate({ idx_1, idx_2, idx_3, idx_4, 1, 1, 1, 1, 1 }); + } +} + +void fill_elliptic_block(Builder& builder) +{ + const uint32_t x1_idx = builder.add_variable(fr::random_element()); + const uint32_t y1_idx = builder.add_variable(fr::random_element()); + const uint32_t x2_idx = builder.add_variable(fr::random_element()); + const uint32_t y2_idx = builder.add_variable(fr::random_element()); + const uint32_t x3_idx = builder.add_variable(fr::random_element()); + const uint32_t y3_idx = builder.add_variable(fr::random_element()); + while (builder.blocks.elliptic.size() < builder.blocks.elliptic.get_fixed_size() - 10 * NUM_SHORT) { + builder.create_ecc_add_gate({ x1_idx, y1_idx, x2_idx, y2_idx, x3_idx, y3_idx, 1 }); + } +} + +void fill_aux_block(Builder& builder) +{ + auto& block = builder.blocks.aux; + + const uint32_t idx_1 = builder.add_variable(fr::random_element()); + const uint32_t idx_2 = builder.add_variable(fr::random_element()); + const uint32_t idx_3 = builder.add_variable(fr::random_element()); + const uint32_t idx_4 = builder.add_variable(fr::random_element()); + while (block.size() < block.get_fixed_size() - 10 * NUM_SHORT) { + builder.apply_aux_selectors(Builder::AUX_SELECTORS::ROM_READ); + block.populate_wires(idx_1, idx_2, idx_3, idx_4); + builder.apply_aux_selectors(Builder::AUX_SELECTORS::LIMB_ACCUMULATE_1); + block.populate_wires(idx_1, idx_2, idx_3, idx_4); + builder.apply_aux_selectors(Builder::AUX_SELECTORS::LIMB_ACCUMULATE_2); + block.populate_wires(idx_1, idx_2, idx_3, idx_4); + builder.apply_aux_selectors(Builder::AUX_SELECTORS::NON_NATIVE_FIELD_1); + block.populate_wires(idx_1, idx_2, idx_3, idx_4); + builder.apply_aux_selectors(Builder::AUX_SELECTORS::NON_NATIVE_FIELD_2); + block.populate_wires(idx_1, idx_2, idx_3, idx_4); + builder.apply_aux_selectors(Builder::AUX_SELECTORS::NON_NATIVE_FIELD_3); + block.populate_wires(idx_1, idx_2, idx_3, idx_4); + builder.apply_aux_selectors(Builder::AUX_SELECTORS::RAM_CONSISTENCY_CHECK); + block.populate_wires(idx_1, idx_2, idx_3, idx_4); + builder.apply_aux_selectors(Builder::AUX_SELECTORS::ROM_CONSISTENCY_CHECK); + block.populate_wires(idx_1, idx_2, idx_3, idx_4); + builder.apply_aux_selectors(Builder::AUX_SELECTORS::RAM_TIMESTAMP_CHECK); + block.populate_wires(idx_1, idx_2, idx_3, idx_4); + builder.apply_aux_selectors(Builder::AUX_SELECTORS::ROM_READ); + block.populate_wires(idx_1, idx_2, idx_3, idx_4); + builder.apply_aux_selectors(Builder::AUX_SELECTORS::RAM_READ); + block.populate_wires(idx_1, idx_2, idx_3, idx_4); + builder.apply_aux_selectors(Builder::AUX_SELECTORS::RAM_WRITE); + block.populate_wires(idx_1, idx_2, idx_3, idx_4); + } +} + +void fill_poseidon2_internal_block(Builder& builder) +{ + auto& block = builder.blocks.poseidon2_internal; + const uint32_t idx_1 = builder.add_variable(fr::random_element()); + const uint32_t idx_2 = builder.add_variable(fr::random_element()); + const uint32_t idx_3 = builder.add_variable(fr::random_element()); + const uint32_t idx_4 = builder.add_variable(fr::random_element()); + + while (block.size() < block.get_fixed_size() - NUM_SHORT) { + builder.create_poseidon2_internal_gate({ idx_1, idx_2, idx_3, idx_4, 1 }); + } +} + +void fill_poseidon2_external_block(Builder& builder) +{ + auto& block = builder.blocks.poseidon2_external; + const uint32_t idx_1 = builder.add_variable(fr::random_element()); + const uint32_t idx_2 = builder.add_variable(fr::random_element()); + const uint32_t idx_3 = builder.add_variable(fr::random_element()); + const uint32_t idx_4 = builder.add_variable(fr::random_element()); + + while (block.size() < block.get_fixed_size() - NUM_SHORT) { + builder.create_poseidon2_external_gate({ idx_1, idx_2, idx_3, idx_4, 1 }); + } +} + +void fill_lookup_block(Builder& builder) +{ + auto& block = builder.blocks.lookup; + + // static constexpr size_t NUM_LOOKUP_TYPES_USED(15); + + while (block.size() < (block.get_fixed_size() - 20 * NUM_SHORT)) { + // SHA + uint256_t left_value = (engine.get_random_uint256() & 0xffffffffULL); + uint256_t right_value = (engine.get_random_uint256() & 0xffffffffULL); + field_ct left = witness_ct(&builder, bb::fr(left_value)); + field_ct right = witness_ct(&builder, bb::fr(right_value)); + plookup_read::get_lookup_accumulators(MultiTableId::SHA256_CH_INPUT, left, right, true); + plookup_read::get_lookup_accumulators(MultiTableId::SHA256_CH_OUTPUT, left, right, true); + plookup_read::get_lookup_accumulators(MultiTableId::SHA256_MAJ_INPUT, left, right, true); + plookup_read::get_lookup_accumulators(MultiTableId::SHA256_MAJ_OUTPUT, left, right, true); + plookup_read::get_lookup_accumulators(MultiTableId::SHA256_WITNESS_INPUT, left, right, true); + plookup_read::get_lookup_accumulators(MultiTableId::SHA256_WITNESS_OUTPUT, left, right, true); + + // AES tables not actually used anywhere... + + // fixed base + auto pedersen_input_value = fr::random_element(); + const auto input_hi = + uint256_t(pedersen_input_value) + .slice(plookup::fixed_base::table::BITS_PER_LO_SCALAR, + plookup::fixed_base::table::BITS_PER_LO_SCALAR + plookup::fixed_base::table::BITS_PER_HI_SCALAR); + const auto input_lo = + uint256_t(pedersen_input_value).slice(0, bb::plookup::fixed_base::table::BITS_PER_LO_SCALAR); + plookup::get_lookup_accumulators(bb::plookup::MultiTableId::FIXED_BASE_LEFT_HI, input_hi); + plookup::get_lookup_accumulators(bb::plookup::MultiTableId::FIXED_BASE_LEFT_LO, input_lo); + plookup::get_lookup_accumulators(bb::plookup::MultiTableId::FIXED_BASE_RIGHT_HI, input_hi); + plookup::get_lookup_accumulators(bb::plookup::MultiTableId::FIXED_BASE_RIGHT_LO, input_lo); + + // bit ops + plookup_read::get_lookup_accumulators(MultiTableId::UINT32_XOR, left, right, true); + plookup_read::get_lookup_accumulators(MultiTableId::UINT32_AND, left, right, true); + + // bn254 generator slices + auto byte = field_ct::from_witness(&builder, engine.get_random_uint256() & 0xffULL); + plookup_read::get_lookup_accumulators(MultiTableId::BN254_XLO, byte, 0, false); + plookup_read::get_lookup_accumulators(MultiTableId::BN254_XHI, byte, 0, false); + plookup_read::get_lookup_accumulators(MultiTableId::BN254_YLO, byte, 0, false); + plookup_read::get_lookup_accumulators(MultiTableId::BN254_YHI, byte, 0, false); + plookup_read::get_lookup_accumulators(MultiTableId::BN254_XYPRIME, byte, 0, false); + plookup_read::get_lookup_accumulators(MultiTableId::BN254_XLO_ENDO, byte, 0, false); + plookup_read::get_lookup_accumulators(MultiTableId::BN254_XHI_ENDO, byte, 0, false); + plookup_read::get_lookup_accumulators(MultiTableId::BN254_XYPRIME_ENDO, byte, 0, false); + + // secp256k1 generator slices + plookup_read::get_lookup_accumulators(MultiTableId::SECP256K1_XLO, byte, 0, false); + plookup_read::get_lookup_accumulators(MultiTableId::SECP256K1_XHI, byte, 0, false); + plookup_read::get_lookup_accumulators(MultiTableId::SECP256K1_YLO, byte, 0, false); + plookup_read::get_lookup_accumulators(MultiTableId::SECP256K1_YHI, byte, 0, false); + plookup_read::get_lookup_accumulators(MultiTableId::SECP256K1_XYPRIME, byte, 0, false); + plookup_read::get_lookup_accumulators(MultiTableId::SECP256K1_XLO_ENDO, byte, 0, false); + plookup_read::get_lookup_accumulators(MultiTableId::SECP256K1_XHI_ENDO, byte, 0, false); + plookup_read::get_lookup_accumulators(MultiTableId::SECP256K1_XYPRIME_ENDO, byte, 0, false); + + // blake xor + plookup_read::get_lookup_accumulators(MultiTableId::BLAKE_XOR, left, right, true); + plookup_read::get_lookup_accumulators(MultiTableId::BLAKE_XOR_ROTATE_16, left, right, true); + plookup_read::get_lookup_accumulators(MultiTableId::BLAKE_XOR_ROTATE_8, left, right, true); + plookup_read::get_lookup_accumulators(MultiTableId::BLAKE_XOR_ROTATE_7, left, right, true); + + // keccak tests trigger + // SharedShiftedVirtualZeroesArray ... Assertion `(index >= start_ && index < end_)' failed. + // plookup_read::get_lookup_accumulators(MultiTableId::KECCAK_THETA_OUTPUT, left, right, true); + // plookup_read::get_lookup_accumulators(MultiTableId::KECCAK_CHI_OUTPUT, left, right, true); + // plookup_read::get_lookup_accumulators(MultiTableId::KECCAK_FORMAT_INPUT, left, right, true); + // plookup_read::get_lookup_accumulators(MultiTableId::KECCAK_FORMAT_OUTPUT, left, right, true); + // plookup_read::get_lookup_accumulators(MultiTableId::KECCAK_NORMALIZE_AND_ROTATE, left, right, true); + } +} + +void fill_trace(State& state, TraceSettings settings) +{ + Builder builder; + builder.blocks.set_fixed_block_sizes(settings); + + fill_ecc_op_block(builder); + fill_pub_inputs_block(builder); + fill_databus_blocks(builder); + fill_delta_range_block(builder); + fill_arithmetic_block(builder); // must come after fill_delta_range_block + fill_elliptic_block(builder); + fill_aux_block(builder); + fill_poseidon2_external_block(builder); + fill_poseidon2_internal_block(builder); + fill_lookup_block(builder); + + { + // finalize doesn't populate public inputs block, so copy to verify that the block is being filled well. + // otherwise the pk construction will overflow the block + // alternative: add to finalize or add a flag to check whether PIs have already been populated + auto builder_copy = builder; + builder_copy.finalize_circuit(/* ensure_nonzero */ false); + DeciderProvingKey::Trace::populate_public_inputs_block(builder_copy); + + for (const auto [label, block] : zip_view(builder_copy.blocks.get_labels(), builder_copy.blocks.get())) { + bool overfilled = block.size() >= block.get_fixed_size(); + if (overfilled) { + vinfo(label, " overfilled"); + } + ASSERT(!overfilled); + vinfo(label, ": ", block.size(), " / ", block.get_fixed_size()); + } + } + + builder.finalize_circuit(/* ensure_nonzero */ true); + uint64_t builder_estimate = builder.estimate_memory(); + for (auto _ : state) { + DeciderProvingKey proving_key(builder, settings); + uint64_t memory_estimate = proving_key.proving_key.estimate_memory(); + state.counters["poly_mem_est"] = static_cast(memory_estimate); + state.counters["builder_mem_est"] = static_cast(builder_estimate); + benchmark::DoNotOptimize(proving_key); + } +} + +void fill_trace_client_ivc_bench(State& state) +{ + fill_trace(state, { TraceStructure::CLIENT_IVC_BENCH, /*overflow_capacity=*/0 }); +} + +void fill_trace_e2e_full_test(State& state) +{ + fill_trace(state, { TraceStructure::E2E_FULL_TEST, /*overflow_capacity=*/0 }); +} + +static void pk_mem(State& state, void (*test_circuit_function)(State&)) noexcept +{ + test_circuit_function(state); +} + +BENCHMARK_CAPTURE(pk_mem, E2E_FULL_TEST, &fill_trace_e2e_full_test)->Unit(kMillisecond)->Iterations(1); + +BENCHMARK_CAPTURE(pk_mem, CLIENT_IVC_BENCH, &fill_trace_client_ivc_bench)->Unit(kMillisecond)->Iterations(1); + +BENCHMARK_MAIN(); \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index d4d3f3dad45..9119e17f6ea 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -173,11 +173,11 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr proving_key; if (!initialized) { - proving_key = std::make_shared(circuit, trace_structure); - trace_usage_tracker = ExecutionTraceUsageTracker(trace_structure); + proving_key = std::make_shared(circuit, trace_settings); + trace_usage_tracker = ExecutionTraceUsageTracker(trace_settings); } else { proving_key = std::make_shared( - circuit, trace_structure, fold_output.accumulator->proving_key.commitment_key); + circuit, trace_settings, fold_output.accumulator->proving_key.commitment_key); } vinfo("getting honk vk... precomputed?: ", precomputed_vk); @@ -382,10 +382,10 @@ std::vector> ClientIVC::precompute_f } // Reset the scheme so it can be reused for actual accumulation, maintaining the trace structure setting as is - TraceStructure structure = trace_structure; + TraceSettings settings = trace_settings; bool auto_verify = auto_verify_mode; *this = ClientIVC(); - this->trace_structure = structure; + this->trace_settings = settings; this->auto_verify_mode = auto_verify; return vkeys; diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp index 3c48e73de49..273d4e5fc1d 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp @@ -115,8 +115,8 @@ class ClientIVC { // Management of linking databus commitments between circuits in the IVC DataBusDepot bus_depot; - // A flag indicating whether or not to construct a structured trace in the DeciderProvingKey - TraceStructure trace_structure = TraceStructure::NONE; + // Settings related to the use of fixed block sizes for each gate in the execution trace + TraceSettings trace_settings; // TODO(https://github.com/AztecProtocol/barretenberg/issues/1101): eventually do away with this. // Setting auto_verify_mode = true will cause kernel completion logic to be added to kernels automatically diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp index c7e85ed675f..f61a6d786b3 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp @@ -76,11 +76,11 @@ class ClientIVCTests : public ::testing::Test { } auto precompute_verification_keys(const size_t num_circuits, - TraceStructure trace_structure, + TraceSettings trace_settings, size_t log2_num_gates = 16) { ClientIVC ivc; // temporary IVC instance needed to produce the complete kernel circuits - ivc.trace_structure = trace_structure; + ivc.trace_settings = trace_settings; std::vector> vkeys; @@ -163,7 +163,7 @@ TEST_F(ClientIVCTests, BadProofFailure) // Confirm that the IVC verifies if nothing is tampered with { ClientIVC ivc; - ivc.trace_structure = TraceStructure::SMALL_TEST; + ivc.trace_settings.structure = TraceStructure::SMALL_TEST; MockCircuitProducer circuit_producer; @@ -179,7 +179,7 @@ TEST_F(ClientIVCTests, BadProofFailure) // The IVC throws an exception if the FIRST fold proof is tampered with { ClientIVC ivc; - ivc.trace_structure = TraceStructure::SMALL_TEST; + ivc.trace_settings.structure = TraceStructure::SMALL_TEST; MockCircuitProducer circuit_producer; @@ -204,7 +204,7 @@ TEST_F(ClientIVCTests, BadProofFailure) // The IVC fails if the SECOND fold proof is tampered with { ClientIVC ivc; - ivc.trace_structure = TraceStructure::SMALL_TEST; + ivc.trace_settings.structure = TraceStructure::SMALL_TEST; MockCircuitProducer circuit_producer; @@ -229,7 +229,7 @@ TEST_F(ClientIVCTests, BadProofFailure) // The IVC fails if the 3rd/FINAL fold proof is tampered with { ClientIVC ivc; - ivc.trace_structure = TraceStructure::SMALL_TEST; + ivc.trace_settings.structure = TraceStructure::SMALL_TEST; MockCircuitProducer circuit_producer; @@ -278,7 +278,7 @@ TEST_F(ClientIVCTests, BasicLarge) TEST_F(ClientIVCTests, BasicStructured) { ClientIVC ivc; - ivc.trace_structure = TraceStructure::SMALL_TEST; + ivc.trace_settings.structure = TraceStructure::SMALL_TEST; MockCircuitProducer circuit_producer; @@ -307,7 +307,7 @@ TEST_F(ClientIVCTests, PrecomputedVerificationKeys) MockCircuitProducer circuit_producer; - auto precomputed_vks = circuit_producer.precompute_verification_keys(NUM_CIRCUITS, TraceStructure::NONE); + auto precomputed_vks = circuit_producer.precompute_verification_keys(NUM_CIRCUITS, TraceSettings{}); // Construct and accumulate set of circuits using the precomputed vkeys for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { @@ -325,7 +325,7 @@ TEST_F(ClientIVCTests, PrecomputedVerificationKeys) TEST_F(ClientIVCTests, StructuredPrecomputedVKs) { ClientIVC ivc; - ivc.trace_structure = TraceStructure::SMALL_TEST; + ivc.trace_settings.structure = TraceStructure::SMALL_TEST; size_t NUM_CIRCUITS = 4; size_t log2_num_gates = 5; // number of gates in baseline mocked circuit @@ -333,7 +333,7 @@ TEST_F(ClientIVCTests, StructuredPrecomputedVKs) MockCircuitProducer circuit_producer; auto precomputed_vks = - circuit_producer.precompute_verification_keys(NUM_CIRCUITS, ivc.trace_structure, log2_num_gates); + circuit_producer.precompute_verification_keys(NUM_CIRCUITS, ivc.trace_settings, log2_num_gates); // Construct and accumulate set of circuits using the precomputed vkeys for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { @@ -357,10 +357,10 @@ TEST(ClientIVCBenchValidation, Full6) bb::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); ClientIVC ivc; - ivc.trace_structure = TraceStructure::CLIENT_IVC_BENCH; + ivc.trace_settings.structure = TraceStructure::CLIENT_IVC_BENCH; size_t total_num_circuits{ 12 }; PrivateFunctionExecutionMockCircuitProducer circuit_producer; - auto precomputed_vkeys = circuit_producer.precompute_verification_keys(total_num_circuits, ivc.trace_structure); + auto precomputed_vkeys = circuit_producer.precompute_verification_keys(total_num_circuits, ivc.trace_settings); perform_ivc_accumulation_rounds(total_num_circuits, ivc, precomputed_vkeys); auto proof = ivc.prove(); bool verified = verify_ivc(proof, ivc); @@ -377,7 +377,7 @@ TEST(ClientIVCBenchValidation, Full6MockedVKs) bb::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); ClientIVC ivc; - ivc.trace_structure = TraceStructure::CLIENT_IVC_BENCH; + ivc.trace_settings.structure = TraceStructure::CLIENT_IVC_BENCH; size_t total_num_circuits{ 12 }; PrivateFunctionExecutionMockCircuitProducer circuit_producer; auto mocked_vkeys = mock_verification_keys(total_num_circuits); @@ -386,4 +386,33 @@ TEST(ClientIVCBenchValidation, Full6MockedVKs) verify_ivc(proof, ivc); }; ASSERT_NO_FATAL_FAILURE(run_test()); -} \ No newline at end of file +} + +/** + * @brief Test use of structured trace overflow block mechanism + * @details Accumulate 4 circuits which have progressively more arithmetic gates. The final two overflow the prescribed + * arithmetic block size and make use of the overflow block which has sufficient capacity. + * + */ +TEST_F(ClientIVCTests, StructuredTraceOverflow) +{ + ClientIVC ivc; + + // Define trace settings with sufficient overflow capacity to accommodate each of the circuits to be accumulated + uint32_t overflow_capacity = 1 << 17; + ivc.trace_settings = { TraceStructure::SMALL_TEST, overflow_capacity }; + + MockCircuitProducer circuit_producer; + + size_t NUM_CIRCUITS = 4; + + // Construct and accumulate some circuits of varying size + size_t log2_num_gates = 14; + for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { + auto circuit = circuit_producer.create_next_circuit(ivc, log2_num_gates); + ivc.accumulate(circuit); + log2_num_gates += 1; + } + + EXPECT_TRUE(ivc.prove_and_verify()); +}; \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_auto_verify.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_auto_verify.test.cpp index dc76f673d21..5064d316794 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_auto_verify.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_auto_verify.test.cpp @@ -132,7 +132,7 @@ TEST_F(ClientIVCAutoVerifyTests, BasicStructured) { ClientIVC ivc; ivc.auto_verify_mode = true; - ivc.trace_structure = TraceStructure::SMALL_TEST; + ivc.trace_settings.structure = TraceStructure::SMALL_TEST; // Construct some circuits of varying size Builder circuit_0 = create_mock_circuit(ivc, /*is_kernel=*/false, /*log2_num_gates=*/5); @@ -185,7 +185,7 @@ TEST_F(ClientIVCAutoVerifyTests, StructuredPrecomputedVKs) { ClientIVC ivc; ivc.auto_verify_mode = true; - ivc.trace_structure = TraceStructure::SMALL_TEST; + ivc.trace_settings.structure = TraceStructure::SMALL_TEST; // Construct a set of arbitrary circuits size_t NUM_CIRCUITS = 4; diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_integration.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_integration.test.cpp index 5b08a08c810..9fed2ce5ca5 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc_integration.test.cpp @@ -37,7 +37,7 @@ class ClientIVCIntegrationTests : public ::testing::Test { TEST_F(ClientIVCIntegrationTests, BenchmarkCaseSimple) { ClientIVC ivc; - ivc.trace_structure = TraceStructure::CLIENT_IVC_BENCH; + ivc.trace_settings.structure = TraceStructure::CLIENT_IVC_BENCH; MockCircuitProducer circuit_producer; @@ -61,7 +61,7 @@ TEST_F(ClientIVCIntegrationTests, BenchmarkCaseSimple) TEST_F(ClientIVCIntegrationTests, ConsecutiveKernels) { ClientIVC ivc; - ivc.trace_structure = TraceStructure::CLIENT_IVC_BENCH; + ivc.trace_settings.structure = TraceStructure::CLIENT_IVC_BENCH; MockCircuitProducer circuit_producer; @@ -89,7 +89,7 @@ TEST_F(ClientIVCIntegrationTests, ConsecutiveKernels) TEST_F(ClientIVCIntegrationTests, BenchmarkCasePrecomputedVKs) { ClientIVC ivc; - ivc.trace_structure = TraceStructure::CLIENT_IVC_BENCH; + ivc.trace_settings.structure = TraceStructure::CLIENT_IVC_BENCH; size_t NUM_CIRCUITS = 6; @@ -97,7 +97,7 @@ TEST_F(ClientIVCIntegrationTests, BenchmarkCasePrecomputedVKs) std::vector> precomputed_vks; { MockCircuitProducer circuit_producer; - precomputed_vks = circuit_producer.precompute_verification_keys(NUM_CIRCUITS, ivc.trace_structure); + precomputed_vks = circuit_producer.precompute_verification_keys(NUM_CIRCUITS, ivc.trace_settings); } MockCircuitProducer circuit_producer; @@ -123,7 +123,7 @@ TEST_F(ClientIVCIntegrationTests, BenchmarkCasePrecomputedVKs) TEST_F(ClientIVCIntegrationTests, DatabusFailure) { ClientIVC ivc; - ivc.trace_structure = TraceStructure::CLIENT_IVC_BENCH; + ivc.trace_settings.structure = TraceStructure::CLIENT_IVC_BENCH; MockCircuitProducer circuit_producer; diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp index 7e2332f5309..eae4966e32a 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/mock_circuit_producer.hpp @@ -135,10 +135,10 @@ class PrivateFunctionExecutionMockCircuitProducer { * @param trace_structure Trace structuring must be known in advance because it effects the VKs * @return set of num_circuits-many verification keys */ - auto precompute_verification_keys(const size_t num_circuits, TraceStructure trace_structure) + auto precompute_verification_keys(const size_t num_circuits, TraceSettings trace_settings) { ClientIVC ivc; // temporary IVC instance needed to produce the complete kernel circuits - ivc.trace_structure = trace_structure; + ivc.trace_settings = trace_settings; std::vector> vkeys; diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/mock_kernel_pinning.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/mock_kernel_pinning.test.cpp index 2dc33189cbc..c89c773e814 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/mock_kernel_pinning.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/mock_kernel_pinning.test.cpp @@ -24,7 +24,7 @@ class MockKernelTest : public ::testing::Test { TEST_F(MockKernelTest, PinFoldingKernelSizes) { ClientIVC ivc; - ivc.trace_structure = TraceStructure::CLIENT_IVC_BENCH; + ivc.trace_settings.structure = TraceStructure::CLIENT_IVC_BENCH; MockCircuitProducer circuit_producer; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp index bdedf7f2c19..6440c016a62 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp @@ -269,15 +269,15 @@ template class CommitmentKey { // Percentage of constant coefficients below which we resort to the conventional commit method constexpr size_t CONSTANT_THRESHOLD = 50; - // Compute the active range complement over which the polynomial is assumed to be constant within each range + // Compute the active range complement over which the polynomial is assumed to be constant within each range. + // Note: the range from the end of the last active range to the end of the polynomial is excluded from the + // complement since the polynomial is assumed to be zero there. std::vector> active_ranges_complement; for (size_t i = 0; i < active_ranges.size() - 1; ++i) { const size_t start = active_ranges[i].second; const size_t end = active_ranges[i + 1].first; active_ranges_complement.emplace_back(start, end); } - // Final complement range goes from end of last active range to the end of the polynomial - active_ranges_complement.emplace_back(active_ranges.back().second, polynomial.end_index()); // Compute the total number of scalars in the constant regions size_t total_num_complement_scalars = 0; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp index 4ba2091dccf..3a0afa05a06 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp @@ -142,6 +142,7 @@ template class IPA { size_t poly_length = polynomial.size(); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1150): Hash more things here. // Step 1. // Send polynomial degree + 1 = d to the verifier transcript->send_to_verifier("IPA:poly_degree_plus_1", static_cast(poly_length)); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp index 95d3ac76d03..3e40157661a 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp @@ -330,3 +330,85 @@ TEST_F(IPATest, ShpleminiIPAWithShift) EXPECT_EQ(result, true); } +/** + * @brief Test the behaviour of the method ShpleminiVerifier::remove_shifted_commitments + * + */ +TEST_F(IPATest, ShpleminiIPAShiftsRemoval) +{ + using IPA = IPA; + using ShplonkProver = ShplonkProver_; + using ShpleminiVerifier = ShpleminiVerifier_; + using GeminiProver = GeminiProver_; + + const size_t n = 8; + const size_t log_n = 3; + + // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random + // point. + auto mle_opening_point = this->random_evaluation_point(log_n); // sometimes denoted 'u' + auto poly1 = Polynomial::random(n); + auto poly2 = Polynomial::random(n, /*shiftable*/ 1); + auto poly3 = Polynomial::random(n, /*shiftable*/ 1); + auto poly4 = Polynomial::random(n); + + Commitment commitment1 = this->commit(poly1); + Commitment commitment2 = this->commit(poly2); + Commitment commitment3 = this->commit(poly3); + Commitment commitment4 = this->commit(poly4); + + std::vector unshifted_commitments = { commitment1, commitment2, commitment3, commitment4 }; + std::vector shifted_commitments = { commitment2, commitment3 }; + auto eval1 = poly1.evaluate_mle(mle_opening_point); + auto eval2 = poly2.evaluate_mle(mle_opening_point); + auto eval3 = poly3.evaluate_mle(mle_opening_point); + auto eval4 = poly4.evaluate_mle(mle_opening_point); + + auto eval2_shift = poly2.evaluate_mle(mle_opening_point, true); + auto eval3_shift = poly3.evaluate_mle(mle_opening_point, true); + + auto prover_transcript = NativeTranscript::prover_init_empty(); + + // Run the full prover PCS protocol: + + // Compute: + // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1 + // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1 + auto prover_opening_claims = GeminiProver::prove(n, + RefArray{ poly1, poly2, poly3, poly4 }, + RefArray{ poly2, poly3 }, + mle_opening_point, + this->ck(), + prover_transcript); + + const auto opening_claim = ShplonkProver::prove(this->ck(), prover_opening_claims, prover_transcript); + IPA::compute_opening_proof(this->ck(), opening_claim, prover_transcript); + + // the index of the first commitment to a polynomial to be shifted in the union of unshifted_commitments and + // shifted_commitments. in our case, it is poly2 + const size_t to_be_shifted_commitments_start = 1; + // the index of the first commitment to a shifted polynomial in the union of unshifted_commitments and + // shifted_commitments. in our case, it is the second occurence of poly2 + const size_t shifted_commitments_start = 4; + // number of shifted polynomials + const size_t num_shifted_commitments = 2; + const RepeatedCommitmentsData repeated_commitments = + RepeatedCommitmentsData(to_be_shifted_commitments_start, shifted_commitments_start, num_shifted_commitments); + // since commitments to poly2, poly3 and their shifts are the same group elements, we simply combine the scalar + // multipliers of commitment2 and commitment3 in one place and remove the entries of the commitments and scalars + // vectors corresponding to the "shifted" commitment + auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); + + auto batch_opening_claim = ShpleminiVerifier::compute_batch_opening_claim(n, + RefVector(unshifted_commitments), + RefVector(shifted_commitments), + RefArray{ eval1, eval2, eval3, eval4 }, + RefArray{ eval2_shift, eval3_shift }, + mle_opening_point, + this->vk()->get_g1_identity(), + verifier_transcript, + repeated_commitments); + + auto result = IPA::reduce_verify_batch_opening_claim(batch_opening_claim, this->vk(), verifier_transcript); + EXPECT_EQ(result, true); +} diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index 38d685c3a4a..a50c0a8919a 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -318,6 +318,7 @@ TYPED_TEST(KZGTest, ShpleminiKzgWithShiftAndConcatenation) mle_opening_point, this->vk()->get_g1_identity(), verifier_transcript, + {}, /* libra commitments = */ {}, /* libra evaluations = */ {}, to_vector_of_ref_vectors(concatenation_groups_commitments), @@ -327,5 +328,99 @@ TYPED_TEST(KZGTest, ShpleminiKzgWithShiftAndConcatenation) EXPECT_EQ(this->vk()->pairing_check(pairing_points[0], pairing_points[1]), true); } +TYPED_TEST(KZGTest, ShpleminiKzgShiftsRemoval) +{ + using ShplonkProver = ShplonkProver_; + using GeminiProver = GeminiProver_; + using ShpleminiVerifier = ShpleminiVerifier_; + using KZG = KZG; + using Fr = typename TypeParam::ScalarField; + using Commitment = typename TypeParam::AffineElement; + using Polynomial = typename bb::Polynomial; + + const size_t n = 16; + const size_t log_n = 4; + // Generate multilinear polynomials, their commitments (genuine and mocked) and evaluations (genuine) at a random + // point. + auto mle_opening_point = this->random_evaluation_point(log_n); // sometimes denoted 'u' + auto poly1 = Polynomial::random(n); + auto poly2 = Polynomial::random(n, 1); + auto poly3 = Polynomial::random(n, 1); + auto poly4 = Polynomial::random(n); + + Commitment commitment1 = this->commit(poly1); + Commitment commitment2 = this->commit(poly2); + Commitment commitment3 = this->commit(poly3); + Commitment commitment4 = this->commit(poly4); + std::vector unshifted_commitments = { commitment1, commitment2, commitment3, commitment4 }; + std::vector shifted_commitments = { commitment2, commitment3 }; + auto eval1 = poly1.evaluate_mle(mle_opening_point); + auto eval2 = poly2.evaluate_mle(mle_opening_point); + auto eval3 = poly3.evaluate_mle(mle_opening_point); + auto eval4 = poly4.evaluate_mle(mle_opening_point); + auto eval2_shift = poly2.evaluate_mle(mle_opening_point, true); + auto eval3_shift = poly3.evaluate_mle(mle_opening_point, true); + + // Collect multilinear evaluations for input to prover + // std::vector multilinear_evaluations = { eval1, eval2, eval3, eval4, eval2_shift, eval3_shift }; + + auto prover_transcript = NativeTranscript::prover_init_empty(); + + // Run the full prover PCS protocol: + + // Compute: + // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1 + // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1 + auto prover_opening_claims = GeminiProver::prove(n, + RefArray{ poly1, poly2, poly3, poly4 }, + RefArray{ poly2, poly3 }, + mle_opening_point, + this->ck(), + prover_transcript); + + // Shplonk prover output: + // - opening pair: (z_challenge, 0) + // - witness: polynomial Q - Q_z + const auto opening_claim = ShplonkProver::prove(this->ck(), prover_opening_claims, prover_transcript); + + // KZG prover: + // - Adds commitment [W] to transcript + KZG::compute_opening_proof(this->ck(), opening_claim, prover_transcript); + + // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation) + + auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); + // the index of the first commitment to a polynomial to be shifted in the union of unshifted_commitments and + // shifted_commitments. in our case, it is poly2 + const size_t to_be_shifted_commitments_start = 1; + // the index of the first commitment to a shifted polynomial in the union of unshifted_commitments and + // shifted_commitments. in our case, it is the second occurence of poly2 + const size_t shifted_commitments_start = 4; + // number of shifted polynomials + const size_t num_shifted_commitments = 2; + // since commitments to poly2, poly3 and their shifts are the same group elements, we simply combine the scalar + // multipliers of commitment2 and commitment3 in one place and remove the entries of the commitments and scalars + // vectors corresponding to the "shifted" commitment + const RepeatedCommitmentsData repeated_commitments = + RepeatedCommitmentsData(to_be_shifted_commitments_start, shifted_commitments_start, num_shifted_commitments); + + // Gemini verifier output: + // - claim: d+1 commitments to Fold_{r}^(0), Fold_{-r}^(0), Fold^(l), d+1 evaluations a_0_pos, a_l, l = 0:d-1 + const auto batch_opening_claim = + ShpleminiVerifier::compute_batch_opening_claim(n, + RefVector(unshifted_commitments), + RefVector(shifted_commitments), + RefArray{ eval1, eval2, eval3, eval4 }, + RefArray{ eval2_shift, eval3_shift }, + mle_opening_point, + this->vk()->get_g1_identity(), + verifier_transcript, + repeated_commitments); + + const auto pairing_points = KZG::reduce_verify_batch_opening_claim(batch_opening_claim, verifier_transcript); + + // Final pairing check: e([Q] - [Q_z] + z[W], [1]_2) = e([W], [x]_2) + EXPECT_EQ(this->vk()->pairing_check(pairing_points[0], pairing_points[1]), true); +} } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 2045714d9c2..83ced38c1f4 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -4,6 +4,7 @@ #include "barretenberg/commitment_schemes/gemini/gemini_impl.hpp" #include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" #include "barretenberg/commitment_schemes/verification_key.hpp" +#include "barretenberg/flavor/repeated_commitments_data.hpp" #include "barretenberg/transcript/transcript.hpp" namespace bb { @@ -132,6 +133,7 @@ template class ShpleminiVerifier_ { const std::vector& multivariate_challenge, const Commitment& g1_identity, const std::shared_ptr& transcript, + const RepeatedCommitmentsData& repeated_commitments = {}, RefSpan libra_univariate_commitments = {}, const std::vector& libra_univariate_evaluations = {}, const std::vector>& concatenation_group_commitments = {}, @@ -288,6 +290,8 @@ template class ShpleminiVerifier_ { commitments.emplace_back(g1_identity); scalars.emplace_back(constant_term_accumulator); + remove_repeated_commitments(commitments, scalars, repeated_commitments, has_zk); + // For ZK flavors, the sumcheck output contains the evaluations of Libra univariates that submitted to the // ShpleminiVerifier, otherwise this argument is set to be empty if (has_zk) { @@ -493,13 +497,93 @@ template class ShpleminiVerifier_ { } } + /** + * @brief Combines scalars of repeating commitments to reduce the number of scalar multiplications performed by the + * verifier. + * + * @details The Shplemini verifier gets the access to multiple groups of commitments, some of which are duplicated + * because they correspond to polynomials whose shifts also evaluated or used in concatenation groups in + * Translator. This method combines the scalars associated with these repeating commitments, reducing the total + * number of scalar multiplications required during the verification. + * + * More specifically, the Shplemini verifier receives two or three groups of commitments: get_unshifted() and + * get_to_be_shifted() in the case of Ultra, Mega, and ECCVM Flavors; and get_unshifted_without_concatenated(), + * get_to_be_shifted(), and get_groups_to_be_concatenated() in the case of the TranslatorFlavor. The commitments are + * then placed in this specific order in a BatchOpeningClaim object containing a vector of commitments and a vector + * of scalars. The ranges with repeated commitments belong to the Flavors. This method iterates over these ranges + * and sums the scalar multipliers corresponding to the same group element. After combining the scalars, we erase + * corresponding entries in both vectors. + * + */ + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1151) Avoid erasing vector elements. + static void remove_repeated_commitments(std::vector& commitments, + std::vector& scalars, + const RepeatedCommitmentsData& repeated_commitments, + bool has_zk) + { + // We started populating commitments and scalars by adding Shplonk:Q commitmment and the corresponding scalar + // factor 1. In the case of ZK, we also added Gemini:masking_poly_comm before populating the vector with + // commitments to prover polynomials + const size_t offset = has_zk ? 2 : 1; + + // Extract the indices from the container, which is normally created in a given Flavor + const size_t& first_range_to_be_shifted_start = repeated_commitments.first_range_to_be_shifted_start + offset; + const size_t& first_range_shifted_start = repeated_commitments.first_range_shifted_start + offset; + const size_t& first_range_size = repeated_commitments.first_range_size; + + const size_t& second_range_to_be_shifted_start = repeated_commitments.second_range_to_be_shifted_start + offset; + const size_t& second_range_shifted_start = repeated_commitments.second_range_shifted_start + offset; + const size_t& second_range_size = repeated_commitments.second_range_size; + + // Iterate over the first range of to-be-shifted scalars and their shifted counterparts + for (size_t i = 0; i < first_range_size; i++) { + size_t idx_to_be_shifted = i + first_range_to_be_shifted_start; + size_t idx_shifted = i + first_range_shifted_start; + scalars[idx_to_be_shifted] = scalars[idx_to_be_shifted] + scalars[idx_shifted]; + } + + // Iterate over the second range of to-be-shifted precomputed scalars and their shifted counterparts (if + // provided) + for (size_t i = 0; i < second_range_size; i++) { + size_t idx_to_be_shifted = i + second_range_to_be_shifted_start; + size_t idx_shifted = i + second_range_shifted_start; + scalars[idx_to_be_shifted] = scalars[idx_to_be_shifted] + scalars[idx_shifted]; + } + + if (second_range_shifted_start > first_range_shifted_start) { + // Erase the shifted scalars and commitments from the second range (if provided) + for (size_t i = 0; i < second_range_size; ++i) { + scalars.erase(scalars.begin() + static_cast(second_range_shifted_start)); + commitments.erase(commitments.begin() + static_cast(second_range_shifted_start)); + } + + // Erase the shifted scalars and commitments from the first range + for (size_t i = 0; i < first_range_size; ++i) { + scalars.erase(scalars.begin() + static_cast(first_range_shifted_start)); + commitments.erase(commitments.begin() + static_cast(first_range_shifted_start)); + } + } else { + // Erase the shifted scalars and commitments from the first range + for (size_t i = 0; i < first_range_size; ++i) { + scalars.erase(scalars.begin() + static_cast(first_range_shifted_start)); + commitments.erase(commitments.begin() + static_cast(first_range_shifted_start)); + } + // Erase the shifted scalars and commitments from the second range (if provided) + for (size_t i = 0; i < second_range_size; ++i) { + scalars.erase(scalars.begin() + static_cast(second_range_shifted_start)); + commitments.erase(commitments.begin() + static_cast(second_range_shifted_start)); + } + } + } + /** * @brief Add the opening data corresponding to Libra masking univariates to the batched opening claim * * @details After verifying ZK Sumcheck, the verifier has to validate the claims about the evaluations of Libra - * univariates used to mask Sumcheck round univariates. To minimize the overhead of such openings, we continue the - * Shplonk batching started in Gemini, i.e. we add new claims multiplied by a suitable power of the Shplonk batching - * challenge and re-use the evaluation challenge sampled to prove the evaluations of Gemini polynomials. + * univariates used to mask Sumcheck round univariates. To minimize the overhead of such openings, we continue + * the Shplonk batching started in Gemini, i.e. we add new claims multiplied by a suitable power of the Shplonk + * batching challenge and re-use the evaluation challenge sampled to prove the evaluations of Gemini + * polynomials. * * @param commitments * @param scalars @@ -541,8 +625,8 @@ template class ShpleminiVerifier_ { if constexpr (!Curve::is_stdlib_type) { Fr::batch_invert(denominators); } - // add Libra commitments to the vector of commitments; compute corresponding scalars and the correction to the - // constant term + // add Libra commitments to the vector of commitments; compute corresponding scalars and the correction to + // the constant term for (const auto [libra_univariate_commitment, denominator, libra_univariate_evaluation] : zip_view(libra_univariate_commitments, denominators, libra_univariate_evaluations)) { commitments.push_back(std::move(libra_univariate_commitment)); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp index 3fab01e75c5..e3537c00a75 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.test.cpp @@ -324,6 +324,7 @@ TYPED_TEST(ShpleminiTest, ShpleminiWithMaskingLibraUnivariates) mle_opening_point, this->vk()->get_g1_identity(), verifier_transcript, + {}, RefVector(libra_commitments), libra_evaluations); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/sparse_commitment.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/sparse_commitment.test.cpp index 7e5eb12f6f6..4ec17f8807a 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/sparse_commitment.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/sparse_commitment.test.cpp @@ -54,20 +54,19 @@ template class CommitmentKeyTest : public ::testing::Test { polynomial.at(idx) = Fr::random_element(); } start_idx += fixed_size; - if (non_zero_complement) { // fill complement with random constant value + } + + // If non_zero_complement, populate the space between active regions with a random constant value + if (non_zero_complement) { + for (size_t i = 0; i < active_range_endpoints.size() - 1; ++i) { + const size_t start = active_range_endpoints[i].second; + const size_t end = active_range_endpoints[i + 1].first; Fr const_val = Fr::random_element(); - for (size_t idx = end_idx; idx < start_idx; ++idx) { + for (size_t idx = start; idx < end; ++idx) { polynomial.at(idx) = const_val; } } } - // fill complement region between end of last fixed block and end of polynomial - if (non_zero_complement) { - Fr const_val = polynomial[active_range_endpoints.back().second]; - for (size_t i = active_range_endpoints.back().second; i < polynomial.end_index(); ++i) { - polynomial.at(i) = const_val; - } - } return { polynomial, active_range_endpoints }; } diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp index 02e2de4e920..b94b0c95085 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/shplemini.test.cpp @@ -130,14 +130,14 @@ TEST(ShpleminiRecursionTest, ProveAndVerifySingle) return zero; }); - auto opening_claim = ShpleminiVerifier::compute_batch_opening_claim(Fr::from_witness(&builder, N), - RefVector(stdlib_f_commitments), - RefVector(stdlib_g_commitments), - RefVector(stdlib_v_evaluations), - RefVector(stdlib_w_evaluations), - u_challenge_in_circuit, - Commitment::one(&builder), - stdlib_verifier_transcript); + const auto opening_claim = ShpleminiVerifier::compute_batch_opening_claim(Fr::from_witness(&builder, N), + RefVector(stdlib_f_commitments), + RefVector(stdlib_g_commitments), + RefVector(stdlib_v_evaluations), + RefVector(stdlib_w_evaluations), + u_challenge_in_circuit, + Commitment::one(&builder), + stdlib_verifier_transcript); auto pairing_points = KZG::reduce_verify_batch_opening_claim(opening_claim, stdlib_verifier_transcript); EXPECT_TRUE(CircuitChecker::check(builder)); diff --git a/barretenberg/cpp/src/barretenberg/common/zip_view.hpp b/barretenberg/cpp/src/barretenberg/common/zip_view.hpp index 588e0703cd8..802227ad741 100644 --- a/barretenberg/cpp/src/barretenberg/common/zip_view.hpp +++ b/barretenberg/cpp/src/barretenberg/common/zip_view.hpp @@ -76,6 +76,7 @@ static_assert(__cplusplus >= 201703L, " must be c++17 or greater"); // could be rewritten in c++11, but the features you must use will be buggy // in an older compiler anyways. #include "barretenberg/common/assert.hpp" +#include #include #include #include diff --git a/barretenberg/cpp/src/barretenberg/crypto/merkle_tree/node_store/cached_content_addressed_tree_store.hpp b/barretenberg/cpp/src/barretenberg/crypto/merkle_tree/node_store/cached_content_addressed_tree_store.hpp index 9b113365e1a..f91fd9bf775 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/merkle_tree/node_store/cached_content_addressed_tree_store.hpp +++ b/barretenberg/cpp/src/barretenberg/crypto/merkle_tree/node_store/cached_content_addressed_tree_store.hpp @@ -19,6 +19,7 @@ #include #include #include +#include template <> struct std::hash { std::size_t operator()(const uint256_t& k) const { return k.data[0]; } @@ -729,36 +730,48 @@ void ContentAddressedCachedTreeStore::persist_node(const std::opt uint32_t level, WriteTransaction& tx) { - // If the optional hash does not have a value then it means it's the zero tree value at this level - // If it has a value but that value is not in our stores then it means it is referencing a node - // created in a previous block, so that will need to have it's reference count increased - if (!optional_hash.has_value()) { - return; - } - fr hash = optional_hash.value(); + struct StackObject { + std::optional opHash; + uint32_t lvl; + }; + std::vector stack; + stack.push_back({ .opHash = optional_hash, .lvl = level }); + + while (!stack.empty()) { + StackObject so = stack.back(); + stack.pop_back(); + + // If the optional hash does not have a value then it means it's the zero tree value at this level + // If it has a value but that value is not in our stores then it means it is referencing a node + // created in a previous block, so that will need to have it's reference count increased + if (!so.opHash.has_value()) { + continue; + } + fr hash = so.opHash.value(); - if (level == depth_) { - // this is a leaf - persist_leaf_pre_image(hash, tx); - } + if (so.lvl == depth_) { + // this is a leaf + persist_leaf_pre_image(hash, tx); + } - // std::cout << "Persisting node hash " << hash << " at level " << level << std::endl; + // std::cout << "Persisting node hash " << hash << " at level " << so.lvl << std::endl; + auto nodePayloadIter = nodes_.find(hash); + if (nodePayloadIter == nodes_.end()) { + // need to increase the stored node's reference count here + dataStore_->increment_node_reference_count(hash, tx); + continue; + } - auto nodePayloadIter = nodes_.find(hash); - if (nodePayloadIter == nodes_.end()) { - // need to increase the stored node's reference count here - dataStore_->increment_node_reference_count(hash, tx); - return; - } - NodePayload nodeData = nodePayloadIter->second; - dataStore_->set_or_increment_node_reference_count(hash, nodeData, tx); - if (nodeData.ref != 1) { - // If the node now has a ref count greater then 1, we don't continue. - // It means that the entire sub-tree underneath already exists - return; + NodePayload nodeData = nodePayloadIter->second; + dataStore_->set_or_increment_node_reference_count(hash, nodeData, tx); + if (nodeData.ref != 1) { + // If the node now has a ref count greater then 1, we don't continue. + // It means that the entire sub-tree underneath already exists + continue; + } + stack.push_back({ .opHash = nodePayloadIter->second.left, .lvl = so.lvl + 1 }); + stack.push_back({ .opHash = nodePayloadIter->second.right, .lvl = so.lvl + 1 }); } - persist_node(nodePayloadIter->second.left, level + 1, tx); - persist_node(nodePayloadIter->second.right, level + 1, tx); } template @@ -1048,29 +1061,38 @@ void ContentAddressedCachedTreeStore::remove_node(const std::opti std::optional maxIndex, WriteTransaction& tx) { - if (!optional_hash.has_value()) { - return; - } - fr hash = optional_hash.value(); - - // we need to retrieve the node and decrement it's reference count - // std::cout << "Decrementing ref count for node " << hash << ", level " << level << std::endl; - NodePayload nodeData; - dataStore_->decrement_node_reference_count(hash, nodeData, tx); - - if (nodeData.ref != 0) { - // node was not deleted, we don't continue the search - return; - } - - // the node was deleted, if it was a leaf then we need to remove the pre-image - if (level == depth_) { - remove_leaf(hash, maxIndex, tx); + struct StackObject { + std::optional opHash; + uint32_t lvl; + }; + std::vector stack; + stack.push_back({ .opHash = optional_hash, .lvl = level }); + + while (!stack.empty()) { + StackObject so = stack.back(); + stack.pop_back(); + + if (!so.opHash.has_value()) { + continue; + } + fr hash = so.opHash.value(); + // we need to retrieve the node and decrement it's reference count + // std::cout << "Decrementing ref count for node " << hash << ", level " << so.lvl << std::endl; + NodePayload nodeData; + dataStore_->decrement_node_reference_count(hash, nodeData, tx); + + if (nodeData.ref != 0) { + // node was not deleted, we don't continue the search + continue; + } + // the node was deleted, if it was a leaf then we need to remove the pre-image + if (so.lvl == depth_) { + remove_leaf(hash, maxIndex, tx); + } + // push the child nodes to the stack + stack.push_back({ .opHash = std::optional(nodeData.left), .lvl = so.lvl + 1 }); + stack.push_back({ .opHash = std::optional(nodeData.right), .lvl = so.lvl + 1 }); } - - // now recursively remove the next level - remove_node(std::optional(nodeData.left), level + 1, maxIndex, tx); - remove_node(std::optional(nodeData.right), level + 1, maxIndex, tx); } template void ContentAddressedCachedTreeStore::initialise() diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index bd36912f2f1..d0eb9d767d6 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -1,6 +1,7 @@ #include "acir_format.hpp" #include "barretenberg/common/log.hpp" #include "barretenberg/common/throw_or_abort.hpp" +#include "barretenberg/dsl/acir_format/ivc_recursion_constraint.hpp" #include "barretenberg/stdlib/plonk_recursion/aggregation_state/aggregation_state.hpp" #include "barretenberg/stdlib/primitives/field/field_conversion.hpp" #include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" @@ -490,6 +491,17 @@ MegaCircuitBuilder create_kernel_circuit(AcirFormat& constraint_system, ASSERT(false); } + // If no witness is provided, populate the VK and public inputs in the recursion constraint with dummy values so + // that the present kernel circuit is constructed correctly. (Used for constructing VKs without witnesses). + if (witness.empty()) { + // Create stdlib representations of each {proof, vkey} pair to be recursively verified + for (auto [constraint, queue_entry] : + zip_view(constraint_system.ivc_recursion_constraints, ivc.verification_queue)) { + + populate_dummy_vk_in_constraint(circuit, queue_entry.honk_verification_key, constraint.key); + } + } + // Construct a stdlib verification key for each constraint based on the verification key witness indices therein std::vector> stdlib_verification_keys; stdlib_verification_keys.reserve(constraint_system.ivc_recursion_constraints.size()); @@ -497,7 +509,6 @@ MegaCircuitBuilder create_kernel_circuit(AcirFormat& constraint_system, stdlib_verification_keys.push_back(std::make_shared( StdlibVerificationKey::from_witness_indices(circuit, constraint.key))); } - // Create stdlib representations of each {proof, vkey} pair to be recursively verified ivc.instantiate_stdlib_verification_queue(circuit, stdlib_verification_keys); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index 3719a9ec15c..14ab23240c8 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -402,7 +402,7 @@ TEST_P(AcirIntegrationFoldingTest, DISABLED_FoldAndVerifyProgramStack) ClientIVC ivc; ivc.auto_verify_mode = true; - ivc.trace_structure = TraceStructure::SMALL_TEST; + ivc.trace_settings.structure = TraceStructure::SMALL_TEST; while (!program_stack.empty()) { auto program = program_stack.back(); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp index bb49d13b0e4..9a68ba90dee 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp @@ -54,7 +54,8 @@ class AcirAvmRecursionConstraint : public ::testing::Test { trace_builder.op_add(0, 1, 2, 3); trace_builder.op_sub(0, 3, 2, 3); trace_builder.op_mul(0, 1, 1, 3); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Passing true enables a longer trace with lookups avm_trace::inject_end_gas_values(public_inputs, trace); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp new file mode 100644 index 00000000000..4100773a486 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp @@ -0,0 +1,165 @@ +#include "ivc_recursion_constraint.hpp" +#include "barretenberg/flavor/flavor.hpp" +#include "barretenberg/plonk_honk_shared/types/aggregation_object_type.hpp" +#include "barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.hpp" +#include "barretenberg/stdlib/plonk_recursion/aggregation_state/aggregation_state.hpp" +#include "barretenberg/stdlib/primitives/bigfield/constants.hpp" +#include "barretenberg/stdlib/primitives/curves/bn254.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp" +#include "proof_surgeon.hpp" +#include "recursion_constraint.hpp" + +namespace acir_format { + +using namespace bb; +using field_ct = stdlib::field_t; + +ClientIVC create_mock_ivc_from_constraints(const std::vector& constraints) +{ + ClientIVC ivc; + ivc.trace_settings.structure = TraceStructure::SMALL_TEST; + + for (const auto& constraint : constraints) { + if (static_cast(PROOF_TYPE::OINK) == constraint.proof_type) { + mock_ivc_oink_accumulation(ivc, constraint.public_inputs.size()); + } else if (static_cast(PROOF_TYPE::PG) == constraint.proof_type) { + // perform equivalent mocking for PG accumulation + } + } + + return ivc; +} + +/** + * @brief Populate an IVC instance with data that mimics the state after accumulating the first app (which runs the oink + * prover) + *@details Mock state consists a mock verification queue entry of type OINK (proof, VK) and a mocked merge proof + * + * @param ivc + * @param num_public_inputs_app num pub inputs in accumulated app, excluding fixed components, e.g. pairing points + */ +void mock_ivc_oink_accumulation(ClientIVC& ivc, size_t num_public_inputs_app) +{ + ClientIVC::VerifierInputs oink_entry = + acir_format::create_dummy_vkey_and_proof_oink(ivc.trace_settings, num_public_inputs_app); + ivc.verification_queue.emplace_back(oink_entry); + ivc.merge_verification_queue.emplace_back(acir_format::create_dummy_merge_proof()); + ivc.initialized = true; +} + +/** + * @brief Create a mock oink proof and VK that have the correct structure but are not necessarily valid + * + */ +ClientIVC::VerifierInputs create_dummy_vkey_and_proof_oink(const TraceSettings& trace_settings, + const size_t num_public_inputs = 0) +{ + using Flavor = MegaFlavor; + using VerificationKey = ClientIVC::VerificationKey; + using FF = bb::fr; + + MegaArith::TraceBlocks blocks; + blocks.set_fixed_block_sizes(trace_settings); + blocks.compute_offsets(/*is_structured=*/true); + size_t structured_dyadic_size = blocks.get_structured_dyadic_size(); + size_t pub_inputs_offset = blocks.pub_inputs.trace_offset; + + ClientIVC::VerifierInputs verifier_inputs; + verifier_inputs.type = ClientIVC::QUEUE_TYPE::OINK; + + FF mock_val(5); + + auto mock_commitment = curve::BN254::AffineElement::one() * mock_val; + std::vector mock_commitment_frs = field_conversion::convert_to_bn254_frs(mock_commitment); + + // Set proof preamble (metadata plus public inputs) + size_t total_num_public_inputs = num_public_inputs + bb::PAIRING_POINT_ACCUMULATOR_SIZE; + verifier_inputs.proof.emplace_back(structured_dyadic_size); + verifier_inputs.proof.emplace_back(total_num_public_inputs); + verifier_inputs.proof.emplace_back(pub_inputs_offset); + for (size_t i = 0; i < total_num_public_inputs; ++i) { + verifier_inputs.proof.emplace_back(0); + } + + // Witness polynomial commitments + for (size_t i = 0; i < Flavor::NUM_WITNESS_ENTITIES; ++i) { + for (const FF& val : mock_commitment_frs) { + verifier_inputs.proof.emplace_back(val); + } + } + + // Set relevant VK metadata and commitments + verifier_inputs.honk_verification_key = std::make_shared(); + verifier_inputs.honk_verification_key->circuit_size = structured_dyadic_size; + verifier_inputs.honk_verification_key->num_public_inputs = total_num_public_inputs; + verifier_inputs.honk_verification_key->pub_inputs_offset = blocks.pub_inputs.trace_offset; // must be set correctly + verifier_inputs.honk_verification_key->contains_pairing_point_accumulator = true; + for (auto& commitment : verifier_inputs.honk_verification_key->get_all()) { + commitment = mock_commitment; + } + + return verifier_inputs; +} + +/** + * @brief Create a mock merge proof which has the correct structure but is not necessarily valid + * + * @return ClientIVC::MergeProof + */ +ClientIVC::MergeProof create_dummy_merge_proof() +{ + using FF = bb::fr; + + std::vector proof; + + FF mock_val(5); + auto mock_commitment = curve::BN254::AffineElement::one() * mock_val; + std::vector mock_commitment_frs = field_conversion::convert_to_bn254_frs(mock_commitment); + + // There are 12 entities in the merge protocol (4 columns x 3 components; aggregate transcript, previous aggregate + // transcript, current transcript contribution) + const size_t NUM_TRANSCRIPT_ENTITIES = 12; + + // Transcript poly commitments + for (size_t i = 0; i < NUM_TRANSCRIPT_ENTITIES; ++i) { + for (const FF& val : mock_commitment_frs) { + proof.emplace_back(val); + } + } + // Transcript poly evaluations + for (size_t i = 0; i < NUM_TRANSCRIPT_ENTITIES; ++i) { + proof.emplace_back(mock_val); + } + // Batched KZG quotient commitment + for (const FF& val : mock_commitment_frs) { + proof.emplace_back(val); + } + + return proof; +} + +/** + * @brief Populate VK witness fields from a recursion constraint from a provided VerificationKey + * + * @param builder + * @param mock_verification_key + * @param key_witness_indices + */ +void populate_dummy_vk_in_constraint(MegaCircuitBuilder& builder, + const std::shared_ptr& mock_verification_key, + std::vector& key_witness_indices) +{ + using Flavor = MegaFlavor; + using FF = Flavor::FF; + + // Convert the VerificationKey to fields + std::vector mock_vk_fields = mock_verification_key->to_field_elements(); + ASSERT(mock_vk_fields.size() == key_witness_indices.size()); + + // Add the fields to the witness and set the key witness indices accordingly + for (auto [witness_idx, value] : zip_view(key_witness_indices, mock_vk_fields)) { + witness_idx = builder.add_variable(value); + } +} + +} // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.hpp new file mode 100644 index 00000000000..5ab74ca80e6 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.hpp @@ -0,0 +1,27 @@ +#pragma once +#include "barretenberg/client_ivc/client_ivc.hpp" +#include "barretenberg/dsl/acir_format/recursion_constraint.hpp" +#include "barretenberg/stdlib/primitives/bigfield/bigfield.hpp" +#include + +namespace acir_format { + +using namespace bb; + +// TODO(https://github.com/AztecProtocol/barretenberg/issues/1148): logic in this file is incomplete. See issue for +// details. + +ClientIVC create_mock_ivc_from_constraints(const std::vector& constraints); + +void mock_ivc_oink_accumulation(ClientIVC& ivc, size_t num_public_inputs_app = 0); + +ClientIVC::VerifierInputs create_dummy_vkey_and_proof_oink(const TraceSettings& trace_settings, + const size_t num_public_inputs); + +ClientIVC::MergeProof create_dummy_merge_proof(); + +void populate_dummy_vk_in_constraint(MegaCircuitBuilder& builder, + const std::shared_ptr& mock_verification_key, + std::vector& key_witness_indices); + +} // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp index 11339b3de7b..50da7e166b5 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp @@ -1,3 +1,4 @@ +#include "barretenberg/dsl/acir_format/ivc_recursion_constraint.hpp" #include "acir_format.hpp" #include "acir_format_mocks.hpp" #include "barretenberg/client_ivc/client_ivc.hpp" @@ -75,39 +76,11 @@ class IvcRecursionConstraintTest : public ::testing::Test { }; } - /** - * @brief Create an arithmetic constraint fixing the first public input witness to it's present value - * @details Meant to mimic the "business logic" of the aztec kernel. Used to facilitate failure testing since this - * will lead to failure of the kernel circuit to verify if a different proof witness is used in the business logic - * VS the recursive verification logic. - * - * @param public_inputs Witness indices of public inputs of some proof to be constrained - * @param witness - * @return ArithmeticConstraint - */ - static ArithmeticConstraint create_public_input_value_constraint(const std::vector& public_inputs, - const SlabVector& witness) - { - const uint32_t pub_input_idx = public_inputs[0]; - const FF pub_input_val = witness[pub_input_idx]; - return { - .a = pub_input_idx, - .b = 0, - .c = 0, - .q_m = 0, - .q_l = -1, - .q_r = 0, - .q_o = 0, - .q_c = pub_input_val, - }; - } - /** * @brief Generate an acir program {constraints, witness} for a mock kernel * @details The IVC contains and internal verification queue that contains proofs to be recursively verified. * Construct an AcirProgram with a RecursionConstraint for each entry in the ivc verification queue. (In practice - * these constraints would come directly from calls to verify_proof in noir). Also add mock "business logic" which - * simply enforces some constraint on the public inputs of the proof. + * these constraints would come directly from calls to verify_proof in noir). * @note This method needs the number of public inputs in each proof-to-be-verified so they can be extracted and * provided separately as is required in the acir constraint system. * @@ -130,14 +103,9 @@ class IvcRecursionConstraintTest : public ::testing::Test { verification_queue[idx], program.witness, inner_circuit_num_pub_inputs[idx])); } - // Add some mock kernel "business logic" which simply fixes one of the public inputs to a particular value - ArithmeticConstraint pub_input_constraint = - create_public_input_value_constraint(ivc_recursion_constraints[0].public_inputs, program.witness); - // Construct a constraint system containing the business logic and ivc recursion constraints program.constraints.varnum = static_cast(program.witness.size()); program.constraints.num_acir_opcodes = static_cast(ivc_recursion_constraints.size()); - program.constraints.poly_triple_constraints = { pub_input_constraint }; program.constraints.ivc_recursion_constraints = ivc_recursion_constraints; program.constraints.original_opcode_indices = create_empty_original_opcode_indices(); mock_opcode_indices(program.constraints); @@ -160,7 +128,7 @@ class IvcRecursionConstraintTest : public ::testing::Test { TEST_F(IvcRecursionConstraintTest, AccumulateTwo) { ClientIVC ivc; - ivc.trace_structure = TraceStructure::SMALL_TEST; + ivc.trace_settings.structure = TraceStructure::SMALL_TEST; // construct a mock app_circuit Builder app_circuit = construct_mock_app_circuit(ivc); @@ -185,7 +153,7 @@ TEST_F(IvcRecursionConstraintTest, AccumulateTwo) TEST_F(IvcRecursionConstraintTest, AccumulateFour) { ClientIVC ivc; - ivc.trace_structure = TraceStructure::SMALL_TEST; + ivc.trace_settings.structure = TraceStructure::SMALL_TEST; // construct a mock app_circuit Builder app_circuit_0 = construct_mock_app_circuit(ivc); @@ -214,64 +182,110 @@ TEST_F(IvcRecursionConstraintTest, AccumulateFour) EXPECT_TRUE(ivc.prove_and_verify()); } -/** - * @brief Demonstrate failure of the IVC if the proof witness differs between those encoded in the constraint system - * (i.e. those used in the noir program) and those used in constructing the recursive verifiers internally - * @brief The idea is to construct two valid but unique verification queue entries of the form {proof, vkey}. One is - * used to construct the acir constraint system and the other is used to construct the recursive verification logic - * internally in the IVC. Since the proof/vkey witnesses in the constraint system are asserted equal to those used to - * construct the recursive verifiers, the use of different verification queue witnesses should result in failure as long - * as they were used in some nontrivial way in the main logic of the kernel. (Specifically, failure results from a - * failure of the "business logic" of the kernel which constrains one of the public inputs to a particular value). - */ -TEST_F(IvcRecursionConstraintTest, AccumulateTwoFailure) +// Test generation of "init" kernel VK via dummy IVC data +TEST_F(IvcRecursionConstraintTest, GenerateVK) { - // Accumulate a single app in order to construct a valid verification queue entry {proof, vkey} to be used later on. - // Demonstrate that it is indeed valid by completing the IVC with a kernel (which recursively verifies the entry) - // then proving and verifying the full IVC. - VerifierInputs alternative_verification_queue_entry; + const TraceSettings trace_settings{ TraceStructure::SMALL_TEST }; + + // First, construct the kernel VK by running the full IVC (accumulate one app and one kernel) + std::shared_ptr expected_kernel_vk; + size_t num_app_public_inputs = 0; { ClientIVC ivc; - ivc.trace_structure = TraceStructure::SMALL_TEST; + ivc.trace_settings = trace_settings; - // construct and accumulate a mock app circuit with a single unique public input + // Construct and accumulate mock app_circuit Builder app_circuit = construct_mock_app_circuit(ivc); ivc.accumulate(app_circuit); + num_app_public_inputs = app_circuit.public_inputs.size(); + + // Construct and accumulate kernel consisting only of the kernel completion logic + AcirProgram program = construct_mock_kernel_program(ivc.verification_queue, { num_app_public_inputs }); + Builder kernel = acir_format::create_kernel_circuit(program.constraints, ivc, program.witness); + ivc.accumulate(kernel); + expected_kernel_vk = ivc.verification_queue.back().honk_verification_key; + } + + // Now, construct the kernel VK by mocking the post app accumulation state of the IVC + std::shared_ptr kernel_vk; + { + ClientIVC ivc; + ivc.trace_settings = trace_settings; - // Save the single entry in the verification queue at this point - alternative_verification_queue_entry = ivc.verification_queue[0]; + acir_format::mock_ivc_oink_accumulation(ivc, num_app_public_inputs - bb::PAIRING_POINT_ACCUMULATOR_SIZE); - // Construct and accumulate kernel_0 - size_t num_pub_inputs_app = app_circuit.public_inputs.size(); - AcirProgram program_0 = construct_mock_kernel_program(ivc.verification_queue, { num_pub_inputs_app }); - Builder kernel_0 = acir_format::create_kernel_circuit(program_0.constraints, ivc, program_0.witness); - ivc.accumulate(kernel_0); + // Construct kernel consisting only of the kernel completion logic + AcirProgram program = construct_mock_kernel_program(ivc.verification_queue, { num_app_public_inputs }); + Builder kernel = acir_format::create_kernel_circuit(program.constraints, ivc); + // WORKTODO: this would normally happen in accumulate() + kernel.add_pairing_point_accumulator(stdlib::recursion::init_default_agg_obj_indices(kernel)); - EXPECT_TRUE(ivc.prove_and_verify()); + auto proving_key = std::make_shared>(kernel, trace_settings); + MegaProver prover(proving_key); + kernel_vk = std::make_shared(prover.proving_key->proving_key); } - // Repeat a similar IVC but use the alternative queue entry just created to provide different (but independently - // valid) witnesses during constraint system construction VS recursive verifier construction. + // PCS verification keys will not match so set to null before comparing + kernel_vk->pcs_verification_key = nullptr; + expected_kernel_vk->pcs_verification_key = nullptr; - ClientIVC ivc; - ivc.trace_structure = TraceStructure::SMALL_TEST; + EXPECT_EQ(*kernel_vk.get(), *expected_kernel_vk.get()); +} - // construct and accumulate a mock app circuit with a single unique public input - Builder app_circuit = construct_mock_app_circuit(ivc); - ivc.accumulate(app_circuit); +// Test generation of "init" kernel VK via dummy IVC data +TEST_F(IvcRecursionConstraintTest, GenerateVKFromConstraints) +{ + const TraceSettings trace_settings{ TraceStructure::SMALL_TEST }; - // Construct kernel_0 - AcirProgram program_0 = construct_mock_kernel_program(ivc.verification_queue, { app_circuit.public_inputs.size() }); + // First, construct the kernel VK by running the full IVC (accumulate one app and one kernel) + std::shared_ptr expected_kernel_vk; + size_t num_app_public_inputs = 0; + { + ClientIVC ivc; + ivc.trace_settings = trace_settings; - // Replace the existing verification queue entry that was used to construct the acir constraint system for the - // kernel with a different (but valid, as shown above) set of inputs - ivc.verification_queue[0] = alternative_verification_queue_entry; - Builder kernel_0 = acir_format::create_kernel_circuit(program_0.constraints, ivc, program_0.witness); + // Construct and accumulate mock app_circuit + Builder app_circuit = construct_mock_app_circuit(ivc); + ivc.accumulate(app_circuit); + num_app_public_inputs = app_circuit.public_inputs.size(); - // The witness should fail to check due to the business logic of the kernel failing - EXPECT_FALSE(CircuitChecker::check(kernel_0)); - ivc.accumulate(kernel_0); + // Construct and accumulate kernel consisting only of the kernel completion logic + AcirProgram program = construct_mock_kernel_program(ivc.verification_queue, { num_app_public_inputs }); + Builder kernel = acir_format::create_kernel_circuit(program.constraints, ivc, program.witness); - // The full IVC should of course also fail to verify since we've accumulated an invalid witness for the kernel - EXPECT_FALSE(ivc.prove_and_verify()); -} + ivc.accumulate(kernel); + expected_kernel_vk = ivc.verification_queue.back().honk_verification_key; + } + + // Now, construct the kernel VK by mocking the post app accumulation state of the IVC + std::shared_ptr kernel_vk; + { + ClientIVC ivc; + ivc.trace_settings = trace_settings; + + // Construct kernel consisting only of the kernel completion logic + acir_format::mock_ivc_oink_accumulation(ivc, num_app_public_inputs - bb::PAIRING_POINT_ACCUMULATOR_SIZE); + AcirProgram program = construct_mock_kernel_program(ivc.verification_queue, { num_app_public_inputs }); + program.witness = {}; // erase witness to mimic VK construction context + + // Create a mock IVC instance from the IVC recursion constraints in the kernel program + ClientIVC mock_ivc = create_mock_ivc_from_constraints(program.constraints.ivc_recursion_constraints); + + // Create a kernel circuit from the kernel program and the mocked IVC + Builder kernel = acir_format::create_kernel_circuit(program.constraints, mock_ivc); + // Note: adding pairing point normally happens in accumulate() + kernel.add_pairing_point_accumulator(stdlib::recursion::init_default_agg_obj_indices(kernel)); + + // Manually construct the VK for the kernel circuit + auto proving_key = std::make_shared>(kernel, ivc.trace_settings); + MegaProver prover(proving_key); + kernel_vk = std::make_shared(prover.proving_key->proving_key); + } + + // PCS verification keys will not match so set to null before comparing + kernel_vk->pcs_verification_key = nullptr; + expected_kernel_vk->pcs_verification_key = nullptr; + + // Compare the VK constructed via running the IVc with the one constructed via mocking + EXPECT_EQ(*kernel_vk.get(), *expected_kernel_vk.get()); +} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/proof_surgeon.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/proof_surgeon.hpp index 224d344ae8a..0b2d1768bca 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/proof_surgeon.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/proof_surgeon.hpp @@ -149,6 +149,7 @@ class ProofSurgeon { const size_t num_public_inputs) { // Extract all public inputs except for those corresponding to the aggregation object + ASSERT(num_public_inputs >= bb::PAIRING_POINT_ACCUMULATOR_SIZE); const size_t num_public_inputs_to_extract = num_public_inputs - bb::PAIRING_POINT_ACCUMULATOR_SIZE; std::vector public_input_witnesses = cut_public_inputs_from_proof(proof_witnesses, num_public_inputs_to_extract); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp index a96a5531a0e..d8bfc79dab0 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -720,8 +720,7 @@ struct BrilligOpcode { }; struct Stop { - uint64_t return_data_offset; - uint64_t return_data_size; + Program::HeapVector return_data; friend bool operator==(const Stop&, const Stop&); std::vector bincodeSerialize() const; @@ -6401,10 +6400,7 @@ namespace Program { inline bool operator==(const BrilligOpcode::Stop& lhs, const BrilligOpcode::Stop& rhs) { - if (!(lhs.return_data_offset == rhs.return_data_offset)) { - return false; - } - if (!(lhs.return_data_size == rhs.return_data_size)) { + if (!(lhs.return_data == rhs.return_data)) { return false; } return true; @@ -6434,8 +6430,7 @@ template void serde::Serializable::serialize(const Program::BrilligOpcode::Stop& obj, Serializer& serializer) { - serde::Serializable::serialize(obj.return_data_offset, serializer); - serde::Serializable::serialize(obj.return_data_size, serializer); + serde::Serializable::serialize(obj.return_data, serializer); } template <> @@ -6444,8 +6439,7 @@ Program::BrilligOpcode::Stop serde::Deserializable Deserializer& deserializer) { Program::BrilligOpcode::Stop obj; - obj.return_data_offset = serde::Deserializable::deserialize(deserializer); - obj.return_data_size = serde::Deserializable::deserialize(deserializer); + obj.return_data = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp index c623479d20c..5fbd1af77c9 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp @@ -11,6 +11,7 @@ #include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp" #include "barretenberg/serialize/msgpack.hpp" #include "barretenberg/srs/global_crs.hpp" +#include "honk_contract.hpp" #include #include @@ -98,7 +99,7 @@ WASM_EXPORT void acir_fold_and_verify_program_stack(uint8_t const* acir_vec, ClientIVC ivc; ivc.auto_verify_mode = true; - ivc.trace_structure = TraceStructure::SMALL_TEST; + ivc.trace_settings.structure = TraceStructure::SMALL_TEST; bool is_kernel = false; while (!program_stack.empty()) { @@ -239,7 +240,7 @@ WASM_EXPORT void acir_prove_and_verify_aztec_client(uint8_t const* acir_stack, // TODO(https://github.com/AztecProtocol/barretenberg/issues/1101): remove use of auto_verify_mode ClientIVC ivc; ivc.auto_verify_mode = true; - ivc.trace_structure = TraceStructure::E2E_FULL_TEST; + ivc.trace_settings.structure = TraceStructure::E2E_FULL_TEST; // Accumulate the entire program stack into the IVC // TODO(https://github.com/AztecProtocol/barretenberg/issues/1116): remove manual setting of is_kernel once databus @@ -320,6 +321,23 @@ WASM_EXPORT void acir_write_vk_ultra_honk(uint8_t const* acir_vec, bool const* r *out = to_heap_buffer(to_buffer(vk)); } +WASM_EXPORT void get_honk_solidity_verifier_vk(uint8_t const* acir_vec, bool const* recursive, uint8_t** out) +{ + using DeciderProvingKey = DeciderProvingKey_; + using VerificationKey = UltraFlavor::VerificationKey; + + auto constraint_system = + acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec), /*honk_recursion=*/true); + auto builder = + acir_format::create_circuit(constraint_system, *recursive, 0, {}, /*honk_recursion=*/true); + + DeciderProvingKey proving_key(builder); + VerificationKey vk(proving_key.proving_key); + + auto str = get_honk_solidity_verifier(&vk); + *out = to_heap_buffer(str); +} + WASM_EXPORT void acir_proof_as_fields_ultra_honk(uint8_t const* proof_buf, fr::vec_out_buf out) { auto proof = from_buffer>(from_buffer>(proof_buf)); @@ -342,4 +360,4 @@ WASM_EXPORT void acir_vk_as_fields_mega_honk(uint8_t const* vk_buf, fr::vec_out_ auto verification_key = std::make_shared(from_buffer(vk_buf)); std::vector vkey_as_fields = verification_key->to_field_elements(); *out_vkey = to_heap_buffer(vkey_as_fields); -} \ No newline at end of file +} diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp index 4fdd99e5610..364c602b7d2 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp @@ -63,7 +63,7 @@ TEST_F(ECCVMTests, BaseCase) { ECCVMCircuitBuilder builder = generate_circuit(&engine); ECCVMProver prover(builder); - HonkProof proof = prover.construct_proof(); + ECCVMProof proof = prover.construct_proof(); ECCVMVerifier verifier(prover.key); bool verified = verifier.verify_proof(proof); @@ -79,7 +79,7 @@ TEST_F(ECCVMTests, EqFails) builder.op_queue->num_transcript_rows++; ECCVMProver prover(builder); - auto proof = prover.construct_proof(); + ECCVMProof proof = prover.construct_proof(); ECCVMVerifier verifier(prover.key); bool verified = verifier.verify_proof(proof); ASSERT_FALSE(verified); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp index 778b43551f4..a44e827d90e 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp @@ -7,6 +7,7 @@ #include "barretenberg/flavor/flavor.hpp" #include "barretenberg/flavor/flavor_macros.hpp" #include "barretenberg/flavor/relation_definitions.hpp" +#include "barretenberg/flavor/repeated_commitments_data.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/polynomials/univariate.hpp" #include "barretenberg/relations/ecc_vm/ecc_bools_relation.hpp" @@ -52,8 +53,19 @@ class ECCVMFlavor { static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 3; // The total number of witness entities not including shifts. static constexpr size_t NUM_WITNESS_ENTITIES = 87; + // The number of entities in ShiftedEntities. + static constexpr size_t NUM_SHIFTED_ENTITIES = 26; + // The number of entities in DerivedWitnessEntities that are not going to be shifted. + static constexpr size_t NUM_DERIVED_WITNESS_ENTITIES_NON_SHIFTED = 1; // The total number of witnesses including shifts and derived entities. - static constexpr size_t NUM_ALL_WITNESS_ENTITIES = 113; + static constexpr size_t NUM_ALL_WITNESS_ENTITIES = NUM_WITNESS_ENTITIES + NUM_SHIFTED_ENTITIES; + // A container to be fed to ShpleminiVerifier to avoid redundant scalar muls, the first number is the index of the + // first witness to be shifted. + static constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS = + RepeatedCommitmentsData(NUM_PRECOMPUTED_ENTITIES + NUM_WITNESS_ENTITIES - + NUM_DERIVED_WITNESS_ENTITIES_NON_SHIFTED - NUM_SHIFTED_ENTITIES, + NUM_PRECOMPUTED_ENTITIES + NUM_WITNESS_ENTITIES, + NUM_SHIFTED_ENTITIES); using GrandProductRelations = std::tuple>; // define the tuple of Relations that comprise the Sumcheck relation @@ -121,91 +133,91 @@ class ECCVMFlavor { template class WireEntities { public: DEFINE_FLAVOR_MEMBERS(DataType, - transcript_add, // column 0 - transcript_mul, // column 1 - transcript_eq, // column 2 - transcript_msm_transition, // column 3 - transcript_pc, // column 4 - transcript_msm_count, // column 5 - transcript_Px, // column 6 - transcript_Py, // column 7 - transcript_z1, // column 8 - transcript_z2, // column 9 - transcript_z1zero, // column 10 - transcript_z2zero, // column 11 - transcript_op, // column 12 - transcript_accumulator_x, // column 13 - transcript_accumulator_y, // column 14 - transcript_msm_x, // column 15 - transcript_msm_y, // column 16 - precompute_pc, // column 17 - precompute_point_transition, // column 18 - precompute_round, // column 19 - precompute_scalar_sum, // column 20 - precompute_s1hi, // column 21 - precompute_s1lo, // column 22 - precompute_s2hi, // column 23 - precompute_s2lo, // column 24 - precompute_s3hi, // column 25 - precompute_s3lo, // column 26 - precompute_s4hi, // column 27 - precompute_s4lo, // column 28 - precompute_skew, // column 29 - precompute_dx, // column 30 - precompute_dy, // column 31 - precompute_tx, // column 32 - precompute_ty, // column 33 - msm_transition, // column 34 - msm_add, // column 35 - msm_double, // column 36 - msm_skew, // column 37 - msm_accumulator_x, // column 38 - msm_accumulator_y, // column 39 - msm_pc, // column 40 - msm_size_of_msm, // column 41 - msm_count, // column 42 - msm_round, // column 43 - msm_add1, // column 44 - msm_add2, // column 45 - msm_add3, // column 46 - msm_add4, // column 47 - msm_x1, // column 48 - msm_y1, // column 49 - msm_x2, // column 50 - msm_y2, // column 51 - msm_x3, // column 52 - msm_y3, // column 53 - msm_x4, // column 54 - msm_y4, // column 55 - msm_collision_x1, // column 56 - msm_collision_x2, // column 57 - msm_collision_x3, // column 58 - msm_collision_x4, // column 59 - msm_lambda1, // column 60 - msm_lambda2, // column 61 - msm_lambda3, // column 62 - msm_lambda4, // column 63 - msm_slice1, // column 64 - msm_slice2, // column 65 - msm_slice3, // column 66 - msm_slice4, // column 67 - transcript_accumulator_empty, // column 68 - transcript_reset_accumulator, // column 69 - precompute_select, // column 70 - lookup_read_counts_0, // column 71 - lookup_read_counts_1, // column 72 - transcript_base_infinity, // column 73 - transcript_base_x_inverse, // column 74 - transcript_base_y_inverse, // column 75 - transcript_add_x_equal, // column 76 - transcript_add_y_equal, // column 77 - transcript_add_lambda, // column 78 - transcript_msm_intermediate_x, // column 79 - transcript_msm_intermediate_y, // column 80 - transcript_msm_infinity, // column 81 - transcript_msm_x_inverse, // column 82 - transcript_msm_count_zero_at_transition, // column 83 - transcript_msm_count_at_transition_inverse); // column 84 + transcript_add, // column 0 + transcript_eq, // column 1 + transcript_msm_transition, // column 2 + transcript_Px, // column 3 + transcript_Py, // column 4 + transcript_z1, // column 5 + transcript_z2, // column 6 + transcript_z1zero, // column 7 + transcript_z2zero, // column 8 + transcript_op, // column 9 + transcript_msm_x, // column 10 + transcript_msm_y, // column 11 + precompute_point_transition, // column 12 + precompute_s1lo, // column 13 + precompute_s2hi, // column 14 + precompute_s2lo, // column 15 + precompute_s3hi, // column 16 + precompute_s3lo, // column 17 + precompute_s4hi, // column 18 + precompute_s4lo, // column 19 + precompute_skew, // column 20 + msm_size_of_msm, // column 21 + msm_add2, // column 22 + msm_add3, // column 23 + msm_add4, // column 24 + msm_x1, // column 25 + msm_y1, // column 26 + msm_x2, // column 27 + msm_y2, // column 28 + msm_x3, // column 29 + msm_y3, // column 30 + msm_x4, // column 31 + msm_y4, // column 32 + msm_collision_x1, // column 33 + msm_collision_x2, // column 34 + msm_collision_x3, // column 35 + msm_collision_x4, // column 36 + msm_lambda1, // column 37 + msm_lambda2, // column 38 + msm_lambda3, // column 39 + msm_lambda4, // column 40 + msm_slice1, // column 41 + msm_slice2, // column 42 + msm_slice3, // column 43 + msm_slice4, // column 44 + transcript_reset_accumulator, // column 45 + lookup_read_counts_0, // column 46 + lookup_read_counts_1, // column 47 + transcript_base_infinity, // column 48 + transcript_base_x_inverse, // column 49 + transcript_base_y_inverse, // column 50 + transcript_add_x_equal, // column 51 + transcript_add_y_equal, // column 52 + transcript_add_lambda, // column 53 + transcript_msm_intermediate_x, // column 54 + transcript_msm_intermediate_y, // column 55 + transcript_msm_infinity, // column 56 + transcript_msm_x_inverse, // column 57 + transcript_msm_count_zero_at_transition, // column 58 + transcript_msm_count_at_transition_inverse, // column 59 + transcript_mul, // column 60 + transcript_msm_count, // column 61 + transcript_accumulator_x, // column 62 + transcript_accumulator_y, // column 63 + precompute_scalar_sum, // column 64 + precompute_s1hi, // column 65 + precompute_dx, // column 66 + precompute_dy, // column 67 + precompute_tx, // column 68 + precompute_ty, // column 69 + msm_transition, // column 70 + msm_add, // column 71 + msm_double, // column 72 + msm_skew, // column 73 + msm_accumulator_x, // column 74 + msm_accumulator_y, // column 75 + msm_count, // column 76 + msm_round, // column 77 + msm_add1, // column 78 + msm_pc, // column 79 + precompute_pc, // column 80 + transcript_pc, // column 81 + precompute_round, // column 82 + transcript_accumulator_empty, // column 83 + precompute_select) // column 84 }; /** @@ -951,11 +963,6 @@ class ECCVMFlavor { FF translation_eval_z1; FF translation_eval_z2; Commitment shplonk_q2_comm; - uint32_t ipa_poly_degree; - std::vector ipa_l_comms; - std::vector ipa_r_comms; - Commitment ipa_G_0_eval; - FF ipa_a_0_eval; Transcript() = default; @@ -1188,20 +1195,6 @@ class ECCVMFlavor { NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); shplonk_q2_comm = NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read); - - ipa_poly_degree = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, - num_frs_read); - - for (size_t i = 0; i < CONST_ECCVM_LOG_N; ++i) { - ipa_l_comms.emplace_back(NativeTranscript::template deserialize_from_buffer( - NativeTranscript::proof_data, num_frs_read)); - ipa_r_comms.emplace_back(NativeTranscript::template deserialize_from_buffer( - NativeTranscript::proof_data, num_frs_read)); - } - ipa_G_0_eval = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, - num_frs_read); - ipa_a_0_eval = - NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); } void serialize_full_transcript() @@ -1344,6 +1337,52 @@ class ECCVMFlavor { NativeTranscript::template serialize_to_buffer(shplonk_q2_comm, NativeTranscript::proof_data); + ASSERT(NativeTranscript::proof_data.size() == old_proof_length); + } + }; + + /** + * @brief Derived class that defines proof structure for ECCVM IPA proof, as well as supporting functions. + * + */ + class IPATranscript : public NativeTranscript { + public: + uint32_t ipa_poly_degree; + std::vector ipa_l_comms; + std::vector ipa_r_comms; + Commitment ipa_G_0_eval; + FF ipa_a_0_eval; + + IPATranscript() = default; + + IPATranscript(const HonkProof& proof) + : NativeTranscript(proof) + {} + + void deserialize_full_transcript() + { + // take current proof and put them into the struct + size_t num_frs_read = 0; + ipa_poly_degree = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, + num_frs_read); + + for (size_t i = 0; i < CONST_ECCVM_LOG_N; ++i) { + ipa_l_comms.emplace_back(NativeTranscript::template deserialize_from_buffer( + NativeTranscript::proof_data, num_frs_read)); + ipa_r_comms.emplace_back(NativeTranscript::template deserialize_from_buffer( + NativeTranscript::proof_data, num_frs_read)); + } + ipa_G_0_eval = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, + num_frs_read); + ipa_a_0_eval = + NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); + } + + void serialize_full_transcript() + { + size_t old_proof_length = NativeTranscript::proof_data.size(); + NativeTranscript::proof_data.clear(); + NativeTranscript::template serialize_to_buffer(ipa_poly_degree, NativeTranscript::proof_data); for (size_t i = 0; i < CONST_ECCVM_LOG_N; ++i) { NativeTranscript::template serialize_to_buffer(ipa_l_comms[i], NativeTranscript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index f16243fbb1c..99f1350f920 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -12,8 +12,11 @@ namespace bb { -ECCVMProver::ECCVMProver(CircuitBuilder& builder, const std::shared_ptr& transcript) +ECCVMProver::ECCVMProver(CircuitBuilder& builder, + const std::shared_ptr& transcript, + const std::shared_ptr& ipa_transcript) : transcript(transcript) + , ipa_transcript(ipa_transcript) { PROFILE_THIS_NAME("ECCVMProver(CircuitBuilder&)"); @@ -183,7 +186,7 @@ void ECCVMProver::execute_pcs_rounds() const OpeningClaim batch_opening_claim = Shplonk::prove(key->commitment_key, opening_claims, transcript); // Compute the opening proof for the batched opening claim with the univariate PCS - PCS::compute_opening_proof(key->commitment_key, batch_opening_claim, transcript); + PCS::compute_opening_proof(key->commitment_key, batch_opening_claim, ipa_transcript); // Produce another challenge passed as input to the translator verifier translation_batching_challenge_v = transcript->template get_challenge("Translation:batching_challenge"); @@ -191,13 +194,12 @@ void ECCVMProver::execute_pcs_rounds() vinfo("computed opening proof"); } -HonkProof ECCVMProver::export_proof() +ECCVMProof ECCVMProver::export_proof() { - proof = transcript->export_proof(); - return proof; + return { transcript->export_proof(), ipa_transcript->export_proof() }; } -HonkProof ECCVMProver::construct_proof() +ECCVMProof ECCVMProver::construct_proof() { PROFILE_THIS_NAME("ECCVMProver::construct_proof"); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp index 88b58903803..dab9d015ab2 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp @@ -27,7 +27,8 @@ class ECCVMProver { using CircuitBuilder = typename Flavor::CircuitBuilder; explicit ECCVMProver(CircuitBuilder& builder, - const std::shared_ptr& transcript = std::make_shared()); + const std::shared_ptr& transcript = std::make_shared(), + const std::shared_ptr& ipa_transcript = std::make_shared()); BB_PROFILE void execute_preamble_round(); BB_PROFILE void execute_wire_commitments_round(); @@ -37,10 +38,11 @@ class ECCVMProver { BB_PROFILE void execute_pcs_rounds(); BB_PROFILE void execute_transcript_consistency_univariate_opening_round(); - HonkProof export_proof(); - HonkProof construct_proof(); + ECCVMProof export_proof(); + ECCVMProof construct_proof(); std::shared_ptr transcript; + std::shared_ptr ipa_transcript; TranslationEvaluations translation_evaluations; @@ -62,9 +64,6 @@ class ECCVMProver { FF translation_batching_challenge_v; // to be rederived by the translator verifier SumcheckOutput sumcheck_output; - - private: - HonkProof proof; }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp index 79d85d60929..92d3ffc5f13 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp @@ -41,11 +41,8 @@ class ECCVMTranscriptTests : public ::testing::Test { size_t round = 0; manifest_expected.add_entry(round, "circuit_size", frs_per_uint32); manifest_expected.add_entry(round, "TRANSCRIPT_ADD", frs_per_G); - manifest_expected.add_entry(round, "TRANSCRIPT_MUL", frs_per_G); manifest_expected.add_entry(round, "TRANSCRIPT_EQ", frs_per_G); manifest_expected.add_entry(round, "TRANSCRIPT_MSM_TRANSITION", frs_per_G); - manifest_expected.add_entry(round, "TRANSCRIPT_PC", frs_per_G); - manifest_expected.add_entry(round, "TRANSCRIPT_MSM_COUNT", frs_per_G); manifest_expected.add_entry(round, "TRANSCRIPT_PX", frs_per_G); manifest_expected.add_entry(round, "TRANSCRIPT_PY", frs_per_G); manifest_expected.add_entry(round, "TRANSCRIPT_Z1", frs_per_G); @@ -53,15 +50,9 @@ class ECCVMTranscriptTests : public ::testing::Test { manifest_expected.add_entry(round, "TRANSCRIPT_Z1ZERO", frs_per_G); manifest_expected.add_entry(round, "TRANSCRIPT_Z2ZERO", frs_per_G); manifest_expected.add_entry(round, "TRANSCRIPT_OP", frs_per_G); - manifest_expected.add_entry(round, "TRANSCRIPT_ACCUMULATOR_X", frs_per_G); - manifest_expected.add_entry(round, "TRANSCRIPT_ACCUMULATOR_Y", frs_per_G); manifest_expected.add_entry(round, "TRANSCRIPT_MSM_X", frs_per_G); manifest_expected.add_entry(round, "TRANSCRIPT_MSM_Y", frs_per_G); - manifest_expected.add_entry(round, "PRECOMPUTE_PC", frs_per_G); manifest_expected.add_entry(round, "PRECOMPUTE_POINT_TRANSITION", frs_per_G); - manifest_expected.add_entry(round, "PRECOMPUTE_ROUND", frs_per_G); - manifest_expected.add_entry(round, "PRECOMPUTE_SCALAR_SUM", frs_per_G); - manifest_expected.add_entry(round, "PRECOMPUTE_S1HI", frs_per_G); manifest_expected.add_entry(round, "PRECOMPUTE_S1LO", frs_per_G); manifest_expected.add_entry(round, "PRECOMPUTE_S2HI", frs_per_G); manifest_expected.add_entry(round, "PRECOMPUTE_S2LO", frs_per_G); @@ -70,21 +61,7 @@ class ECCVMTranscriptTests : public ::testing::Test { manifest_expected.add_entry(round, "PRECOMPUTE_S4HI", frs_per_G); manifest_expected.add_entry(round, "PRECOMPUTE_S4LO", frs_per_G); manifest_expected.add_entry(round, "PRECOMPUTE_SKEW", frs_per_G); - manifest_expected.add_entry(round, "PRECOMPUTE_DX", frs_per_G); - manifest_expected.add_entry(round, "PRECOMPUTE_DY", frs_per_G); - manifest_expected.add_entry(round, "PRECOMPUTE_TX", frs_per_G); - manifest_expected.add_entry(round, "PRECOMPUTE_TY", frs_per_G); - manifest_expected.add_entry(round, "MSM_TRANSITION", frs_per_G); - manifest_expected.add_entry(round, "MSM_ADD", frs_per_G); - manifest_expected.add_entry(round, "MSM_DOUBLE", frs_per_G); - manifest_expected.add_entry(round, "MSM_SKEW", frs_per_G); - manifest_expected.add_entry(round, "MSM_ACCUMULATOR_X", frs_per_G); - manifest_expected.add_entry(round, "MSM_ACCUMULATOR_Y", frs_per_G); - manifest_expected.add_entry(round, "MSM_PC", frs_per_G); manifest_expected.add_entry(round, "MSM_SIZE_OF_MSM", frs_per_G); - manifest_expected.add_entry(round, "MSM_COUNT", frs_per_G); - manifest_expected.add_entry(round, "MSM_ROUND", frs_per_G); - manifest_expected.add_entry(round, "MSM_ADD1", frs_per_G); manifest_expected.add_entry(round, "MSM_ADD2", frs_per_G); manifest_expected.add_entry(round, "MSM_ADD3", frs_per_G); manifest_expected.add_entry(round, "MSM_ADD4", frs_per_G); @@ -108,9 +85,7 @@ class ECCVMTranscriptTests : public ::testing::Test { manifest_expected.add_entry(round, "MSM_SLICE2", frs_per_G); manifest_expected.add_entry(round, "MSM_SLICE3", frs_per_G); manifest_expected.add_entry(round, "MSM_SLICE4", frs_per_G); - manifest_expected.add_entry(round, "TRANSCRIPT_ACCUMULATOR_EMPTY", frs_per_G); manifest_expected.add_entry(round, "TRANSCRIPT_RESET_ACCUMULATOR", frs_per_G); - manifest_expected.add_entry(round, "PRECOMPUTE_SELECT", frs_per_G); manifest_expected.add_entry(round, "LOOKUP_READ_COUNTS_0", frs_per_G); manifest_expected.add_entry(round, "LOOKUP_READ_COUNTS_1", frs_per_G); manifest_expected.add_entry(round, "TRANSCRIPT_BASE_INFINITY", frs_per_G); @@ -125,6 +100,31 @@ class ECCVMTranscriptTests : public ::testing::Test { manifest_expected.add_entry(round, "TRANSCRIPT_MSM_X_INVERSE", frs_per_G); manifest_expected.add_entry(round, "TRANSCRIPT_MSM_COUNT_ZERO_AT_TRANSITION", frs_per_G); manifest_expected.add_entry(round, "TRANSCRIPT_MSM_COUNT_AT_TRANSITION_INVERSE", frs_per_G); + manifest_expected.add_entry(round, "TRANSCRIPT_MUL", frs_per_G); + manifest_expected.add_entry(round, "TRANSCRIPT_MSM_COUNT", frs_per_G); + manifest_expected.add_entry(round, "TRANSCRIPT_ACCUMULATOR_X", frs_per_G); + manifest_expected.add_entry(round, "TRANSCRIPT_ACCUMULATOR_Y", frs_per_G); + manifest_expected.add_entry(round, "PRECOMPUTE_SCALAR_SUM", frs_per_G); + manifest_expected.add_entry(round, "PRECOMPUTE_S1HI", frs_per_G); + manifest_expected.add_entry(round, "PRECOMPUTE_DX", frs_per_G); + manifest_expected.add_entry(round, "PRECOMPUTE_DY", frs_per_G); + manifest_expected.add_entry(round, "PRECOMPUTE_TX", frs_per_G); + manifest_expected.add_entry(round, "PRECOMPUTE_TY", frs_per_G); + manifest_expected.add_entry(round, "MSM_TRANSITION", frs_per_G); + manifest_expected.add_entry(round, "MSM_ADD", frs_per_G); + manifest_expected.add_entry(round, "MSM_DOUBLE", frs_per_G); + manifest_expected.add_entry(round, "MSM_SKEW", frs_per_G); + manifest_expected.add_entry(round, "MSM_ACCUMULATOR_X", frs_per_G); + manifest_expected.add_entry(round, "MSM_ACCUMULATOR_Y", frs_per_G); + manifest_expected.add_entry(round, "MSM_COUNT", frs_per_G); + manifest_expected.add_entry(round, "MSM_ROUND", frs_per_G); + manifest_expected.add_entry(round, "MSM_ADD1", frs_per_G); + manifest_expected.add_entry(round, "MSM_PC", frs_per_G); + manifest_expected.add_entry(round, "PRECOMPUTE_PC", frs_per_G); + manifest_expected.add_entry(round, "TRANSCRIPT_PC", frs_per_G); + manifest_expected.add_entry(round, "PRECOMPUTE_ROUND", frs_per_G); + manifest_expected.add_entry(round, "TRANSCRIPT_ACCUMULATOR_EMPTY", frs_per_G); + manifest_expected.add_entry(round, "PRECOMPUTE_SELECT", frs_per_G); manifest_expected.add_challenge(round, "beta", "gamma"); round++; @@ -205,6 +205,19 @@ class ECCVMTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, "Shplonk:z"); round++; + manifest_expected.add_challenge(round, "Translation:batching_challenge"); + + return manifest_expected; + } + + TranscriptManifest construct_eccvm_ipa_manifest() + { + TranscriptManifest manifest_expected; + // Size of types is number of bb::frs needed to represent the type + size_t frs_per_Fr = bb::field_conversion::calc_num_bn254_frs(); + size_t frs_per_G = bb::field_conversion::calc_num_bn254_frs(); + size_t frs_per_uint32 = bb::field_conversion::calc_num_bn254_frs(); + size_t round = 0; manifest_expected.add_entry(round, "IPA:poly_degree_plus_1", frs_per_uint32); manifest_expected.add_challenge(round, "IPA:generator_challenge"); @@ -220,8 +233,6 @@ class ECCVMTranscriptTests : public ::testing::Test { round++; manifest_expected.add_entry(round, "IPA:G_0", frs_per_G); manifest_expected.add_entry(round, "IPA:a_0", frs_per_Fr); - manifest_expected.add_challenge(round, "Translation:batching_challenge"); - return manifest_expected; } @@ -271,7 +282,7 @@ TEST_F(ECCVMTranscriptTests, ProverManifestConsistency) // Automatically generate a transcript manifest by constructing a proof ECCVMProver prover(builder); - auto proof = prover.construct_proof(); + ECCVMProof proof = prover.construct_proof(); // Check that the prover generated manifest agrees with the manifest hard coded in this suite auto manifest_expected = this->construct_eccvm_honk_manifest(prover.key->circuit_size); @@ -281,6 +292,15 @@ TEST_F(ECCVMTranscriptTests, ProverManifestConsistency) for (size_t round = 0; round < manifest_expected.size(); ++round) { ASSERT_EQ(prover_manifest[round], manifest_expected[round]) << "Prover manifest discrepency in round " << round; } + + auto ipa_manifest_expected = this->construct_eccvm_ipa_manifest(); + auto prover_ipa_manifest = prover.ipa_transcript->get_manifest(); + + // Note: a manifest can be printed using manifest.print() + for (size_t round = 0; round < ipa_manifest_expected.size(); ++round) { + ASSERT_EQ(prover_ipa_manifest[round], ipa_manifest_expected[round]) + << "IPA prover manifest discrepency in round " << round; + } } /** @@ -295,7 +315,7 @@ TEST_F(ECCVMTranscriptTests, VerifierManifestConsistency) // Automatically generate a transcript manifest in the prover by constructing a proof ECCVMProver prover(builder); - auto proof = prover.construct_proof(); + ECCVMProof proof = prover.construct_proof(); // Automatically generate a transcript manifest in the verifier by verifying a proof ECCVMVerifier verifier(prover.key); @@ -347,24 +367,28 @@ TEST_F(ECCVMTranscriptTests, StructureTest) // Automatically generate a transcript manifest by constructing a proof ECCVMProver prover(builder); - auto proof = prover.construct_proof(); + ECCVMProof proof = prover.construct_proof(); ECCVMVerifier verifier(prover.key); EXPECT_TRUE(verifier.verify_proof(proof)); // try deserializing and serializing with no changes and check proof is still valid prover.transcript->deserialize_full_transcript(); prover.transcript->serialize_full_transcript(); - EXPECT_TRUE( - verifier.verify_proof(prover.transcript->proof_data)); // we have changed nothing so proof is still valid + EXPECT_TRUE(verifier.verify_proof( + { prover.transcript->proof_data, + prover.ipa_transcript->proof_data })); // we have changed nothing so proof is still valid typename Flavor::Commitment one_group_val = Flavor::Commitment::one(); auto rand_val = Flavor::FF::random_element(); prover.transcript->transcript_Px_comm = one_group_val * rand_val; // choose random object to modify EXPECT_TRUE(verifier.verify_proof( - prover.transcript->proof_data)); // we have not serialized it back to the proof so it should still be fine + { prover.transcript->proof_data, prover.ipa_transcript->proof_data })); // we have not serialized it back to the + // proof so it should still be fine prover.transcript->serialize_full_transcript(); - EXPECT_FALSE(verifier.verify_proof(prover.transcript->proof_data)); // the proof is now wrong after serializing it + EXPECT_FALSE( + verifier.verify_proof({ prover.transcript->proof_data, + prover.ipa_transcript->proof_data })); // the proof is now wrong after serializing it prover.transcript->deserialize_full_transcript(); EXPECT_EQ(static_cast(prover.transcript->transcript_Px_comm), diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index 7924f578387..f4a10683335 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -8,7 +8,7 @@ namespace bb { /** * @brief This function verifies an ECCVM Honk proof for given program settings. */ -bool ECCVMVerifier::verify_proof(const HonkProof& proof) +bool ECCVMVerifier::verify_proof(const ECCVMProof& proof) { using Curve = typename Flavor::Curve; using Shplemini = ShpleminiVerifier_; @@ -16,7 +16,8 @@ bool ECCVMVerifier::verify_proof(const HonkProof& proof) using OpeningClaim = OpeningClaim; RelationParameters relation_parameters; - transcript = std::make_shared(proof); + transcript = std::make_shared(proof.pre_ipa_proof); + ipa_transcript = std::make_shared(proof.ipa_proof); VerifierCommitments commitments{ key }; CommitmentLabels commitment_labels; @@ -79,6 +80,7 @@ bool ECCVMVerifier::verify_proof(const HonkProof& proof) multivariate_challenge, key->pcs_verification_key->get_g1_identity(), transcript, + Flavor::REPEATED_COMMITMENTS, RefVector(libra_commitments), libra_evaluations); @@ -127,7 +129,7 @@ bool ECCVMVerifier::verify_proof(const HonkProof& proof) Shplonk::reduce_verification(key->pcs_verification_key->get_g1_identity(), opening_claims, transcript); const bool batched_opening_verified = - PCS::reduce_verify(key->pcs_verification_key, batch_opening_claim, transcript); + PCS::reduce_verify(key->pcs_verification_key, batch_opening_claim, ipa_transcript); vinfo("eccvm sumcheck verified?: ", sumcheck_verified.value()); vinfo("batch opening verified?: ", batched_opening_verified); return sumcheck_verified.value() && batched_opening_verified; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.hpp index 10e49d08a76..c772d99b517 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.hpp @@ -22,10 +22,11 @@ class ECCVMVerifier { explicit ECCVMVerifier(const std::shared_ptr& proving_key) : ECCVMVerifier(std::make_shared(proving_key)){}; - bool verify_proof(const HonkProof& proof); + bool verify_proof(const ECCVMProof& proof); std::shared_ptr key; std::map commitments; std::shared_ptr transcript; + std::shared_ptr ipa_transcript; }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/examples/join_split/join_split.test.cpp b/barretenberg/cpp/src/barretenberg/examples/join_split/join_split.test.cpp index 1ef0dfe3305..f56dbf882e7 100644 --- a/barretenberg/cpp/src/barretenberg/examples/join_split/join_split.test.cpp +++ b/barretenberg/cpp/src/barretenberg/examples/join_split/join_split.test.cpp @@ -703,7 +703,7 @@ TEST_F(join_split_tests, test_0_input_notes_and_detect_circuit_change) // The below part detects any changes in the join-split circuit constexpr size_t DYADIC_CIRCUIT_SIZE = 1 << 16; - constexpr uint256_t CIRCUIT_HASH("0x2b30566e4d921ea9b0c76802d86ea5b8381ffa78ef143af1b0d0e3045862cb6b"); + constexpr uint256_t CIRCUIT_HASH("0xe833d0ffaa99f39ca31ef79ded0089b0ec614eb4a528c4e1c4af6221a003fa6e"); const uint256_t circuit_hash = circuit.hash_circuit(); // circuit is finalized now diff --git a/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.cpp b/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.cpp index 38b20b9891b..77b31165670 100644 --- a/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.cpp @@ -45,7 +45,7 @@ void ExecutionTrace_::populate(Builder& builder, typename Flavor::Provin add_memory_records_to_proving_key(trace_data, builder, proving_key); } - if constexpr (IsGoblinFlavor) { + if constexpr (IsMegaFlavor) { PROFILE_THIS_NAME("add_ecc_op_wires_to_proving_key"); @@ -100,7 +100,9 @@ typename ExecutionTrace_::TraceData ExecutionTrace_::construct_t // Save ranges over which the blocks are "active" for use in structured commitments if constexpr (IsHonkFlavor) { - proving_key.active_block_ranges.emplace_back(offset, offset + block.size()); + if (block.size() > 0) { + proving_key.active_block_ranges.emplace_back(offset, offset + block.size()); + } } // Update wire polynomials and copy cycles @@ -151,7 +153,7 @@ typename ExecutionTrace_::TraceData ExecutionTrace_::construct_t template void ExecutionTrace_::add_ecc_op_wires_to_proving_key(Builder& builder, typename Flavor::ProvingKey& proving_key) - requires IsGoblinFlavor + requires IsMegaFlavor { auto& ecc_op_selector = proving_key.polynomials.lagrange_ecc_op; const size_t op_wire_offset = Flavor::has_zero_row ? 1 : 0; diff --git a/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.hpp b/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.hpp index 2f107a3444d..6092e0f5cc7 100644 --- a/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/execution_trace/execution_trace.hpp @@ -125,7 +125,7 @@ template class ExecutionTrace_ { * @param proving_key */ static void add_ecc_op_wires_to_proving_key(Builder& builder, typename Flavor::ProvingKey& proving_key) - requires IsGoblinFlavor; + requires IsMegaFlavor; }; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp index 3b7fa66b826..a354e03235f 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp @@ -123,7 +123,7 @@ template class ProvingKey_ { // folded element by element. std::vector public_inputs; - // Ranges over which the execution trace is "active" + // Ranges of the form [start, end) over which the execution trace is "active" std::vector> active_block_ranges; ProvingKey_() = default; @@ -360,7 +360,7 @@ template concept IsUltraPlonkFlavor = IsAnyOf; template -concept IsUltraPlonkOrHonk = IsAnyOf; +concept IsUltraPlonkOrHonk = IsAnyOf; template concept IsHonkFlavor = IsAnyOf; @@ -369,7 +369,7 @@ template concept IsUltraFlavor = IsAnyOf; template -concept IsGoblinFlavor = IsAnyOf, MegaRecursiveFlavor_, MegaRecursiveFlavor_, @@ -377,7 +377,7 @@ MegaZKRecursiveFlavor_, MegaZKRecursiveFlavor_>; template -concept HasDataBus = IsGoblinFlavor; +concept HasDataBus = IsMegaFlavor; template concept IsRecursiveFlavor = IsAnyOf, diff --git a/barretenberg/cpp/src/barretenberg/flavor/repeated_commitments_data.hpp b/barretenberg/cpp/src/barretenberg/flavor/repeated_commitments_data.hpp new file mode 100644 index 00000000000..c5b697ded49 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/flavor/repeated_commitments_data.hpp @@ -0,0 +1,36 @@ +#pragma once +#include + +namespace bb { +struct RepeatedCommitmentsData { + size_t first_range_to_be_shifted_start = 0; + size_t first_range_shifted_start = 0; + size_t first_range_size = 0; + size_t second_range_to_be_shifted_start = 0; + size_t second_range_shifted_start = 0; + size_t second_range_size = 0; + + RepeatedCommitmentsData() = default; + // Constructor for a single range + constexpr RepeatedCommitmentsData(size_t first_to_be_shifted_start, size_t first_shifted_start, size_t first_size) + : first_range_to_be_shifted_start(first_to_be_shifted_start) + , first_range_shifted_start(first_shifted_start) + , first_range_size(first_size) + {} + + // Constructor for both ranges + constexpr RepeatedCommitmentsData(size_t first_to_be_shifted_start, + size_t first_shifted_start, + size_t first_size, + size_t second_to_be_shifted_start, + size_t second_shifted_start, + size_t second_size) + : first_range_to_be_shifted_start(first_to_be_shifted_start) + , first_range_shifted_start(first_shifted_start) + , first_range_size(first_size) + , second_range_to_be_shifted_start(second_to_be_shifted_start) + , second_range_shifted_start(second_shifted_start) + , second_range_size(second_size) + {} +}; +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits_pinning.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits_pinning.test.cpp index 53e7c5b2644..afba3ac5402 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits_pinning.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits_pinning.test.cpp @@ -58,7 +58,8 @@ TEST_F(MegaMockCircuitsPinning, SmallTestStructuredCircuitSize) { GoblinProver goblin; MegaCircuitBuilder app_circuit{ goblin.op_queue }; - auto proving_key = std::make_shared(app_circuit, TraceStructure::SMALL_TEST); + TraceSettings trace_settings{ TraceStructure::SMALL_TEST }; + auto proving_key = std::make_shared(app_circuit, trace_settings); EXPECT_EQ(proving_key->proving_key.log_circuit_size, 18); } @@ -66,7 +67,8 @@ TEST_F(MegaMockCircuitsPinning, ClientIVCBenchStructuredCircuitSize) { GoblinProver goblin; MegaCircuitBuilder app_circuit{ goblin.op_queue }; - auto proving_key = std::make_shared(app_circuit, TraceStructure::CLIENT_IVC_BENCH); + TraceSettings trace_settings{ TraceStructure::CLIENT_IVC_BENCH }; + auto proving_key = std::make_shared(app_circuit, trace_settings); EXPECT_EQ(proving_key->proving_key.log_circuit_size, 19); } @@ -74,6 +76,7 @@ TEST_F(MegaMockCircuitsPinning, E2EStructuredCircuitSize) { GoblinProver goblin; MegaCircuitBuilder app_circuit{ goblin.op_queue }; - auto proving_key = std::make_shared(app_circuit, TraceStructure::E2E_FULL_TEST); + TraceSettings trace_settings{ TraceStructure::E2E_FULL_TEST }; + auto proving_key = std::make_shared(app_circuit, trace_settings); EXPECT_EQ(proving_key->proving_key.log_circuit_size, 20); } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/goblin/types.hpp b/barretenberg/cpp/src/barretenberg/goblin/types.hpp index c9c13d81e93..ab3f772d17d 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/types.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/types.hpp @@ -15,13 +15,14 @@ struct GoblinProof { using FF = MegaFlavor::FF; HonkProof merge_proof; - HonkProof eccvm_proof; + ECCVMProof eccvm_proof; HonkProof translator_proof; ECCVMProver::TranslationEvaluations translation_evaluations; size_t size() const { - return merge_proof.size() + eccvm_proof.size() + translator_proof.size() + TranslationEvaluations::size(); + return merge_proof.size() + eccvm_proof.pre_ipa_proof.size() + eccvm_proof.ipa_proof.size() + + translator_proof.size() + TranslationEvaluations::size(); }; MSGPACK_FIELDS(merge_proof, eccvm_proof, translator_proof, translation_evaluations); diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp index 5cc245ee985..bbe394315ad 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/permutation_library.hpp @@ -180,7 +180,7 @@ void compute_translator_range_constraint_ordered_polynomials(typename Flavor::Pr #ifdef NO_PAR_ALGOS std::sort(extra_denominator_uint.begin(), extra_denominator_uint.end()); #else - std::sort(std::execution::par_unseq, extra_denominator_uint.begin(), extra_denominator.end()); + std::sort(std::execution::par_unseq, extra_denominator_uint.begin(), extra_denominator_uint.end()); #endif // Copy the values into the actual polynomial diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/types/proof.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/types/proof.hpp index 297c5c2abbc..2f1777adb90 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/types/proof.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/types/proof.hpp @@ -12,6 +12,12 @@ static constexpr size_t HONK_PROOF_PUBLIC_INPUT_OFFSET = 3; static constexpr size_t PUBLIC_INPUTS_SIZE_INDEX = 1; using HonkProof = std::vector; // this can be fr? +struct ECCVMProof { + HonkProof pre_ipa_proof; + HonkProof ipa_proof; + + MSGPACK_FIELDS(pre_ipa_proof, ipa_proof); +}; template using StdlibProof = std::vector>; diff --git a/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp b/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp index 90fb89c785d..e535e58acda 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp @@ -2,6 +2,7 @@ #include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" #include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp" +#include namespace bb::plonk { struct SelectorProperties { diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp index b5408341edb..066504bdb40 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp @@ -30,7 +30,14 @@ struct StackTraces { // A set of fixed block size conigurations to be used with the structured execution trace. The actual block sizes // corresponding to these settings are defined in the corresponding arithmetization classes (Ultra/Mega). For efficiency // it is best to use the smallest possible block sizes to accommodate a given situation. -enum class TraceStructure { NONE, SMALL_TEST, CLIENT_IVC_BENCH, E2E_FULL_TEST }; +enum class TraceStructure { NONE, TINY_TEST, SMALL_TEST, CLIENT_IVC_BENCH, E2E_FULL_TEST }; + +struct TraceSettings { + TraceStructure structure = TraceStructure::NONE; + // The size of the overflow block. Specified separately because it is allowed to be determined at runtime in the + // context of VK computation + uint32_t overflow_capacity = 0; +}; /** * @brief Basic structure for storing gate data in a builder diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/execution_trace_usage_tracker.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/execution_trace_usage_tracker.hpp index b1fcfcb0702..f1798fa3c76 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/execution_trace_usage_tracker.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/execution_trace_usage_tracker.hpp @@ -29,15 +29,15 @@ struct ExecutionTraceUsageTracker { size_t max_databus_size = 0; size_t max_tables_size = 0; - TraceStructure trace_structure = TraceStructure::NONE; + TraceSettings trace_settings; - ExecutionTraceUsageTracker(const TraceStructure& trace_structure = TraceStructure::NONE) - : trace_structure(trace_structure) + ExecutionTraceUsageTracker(const TraceSettings& trace_settings = TraceSettings{}) + : trace_settings(trace_settings) { for (auto& size : max_sizes.get()) { size = 0; // init max sizes to zero } - fixed_sizes.set_fixed_block_sizes(trace_structure); + fixed_sizes.set_fixed_block_sizes(trace_settings); fixed_sizes.compute_offsets(/*is_structured=*/true); } @@ -67,7 +67,7 @@ struct ExecutionTraceUsageTracker { // The active ranges for the databus and lookup relations (both based on log-deriv lookup argument) must // incorporate both the lookup/read gate blocks as well as the rows containing the data that is being read. // Update the corresponding ranges accordingly. (Note: tables are constructed at the 'bottom' of the trace). - size_t dyadic_circuit_size = circuit.get_circuit_subgroup_size(fixed_sizes.get_total_structured_size()); + size_t dyadic_circuit_size = fixed_sizes.get_structured_dyadic_size(); active_ranges.busread.first = 0; // databus data is stored at the top of the trace active_ranges.busread.second = std::max(max_databus_size, active_ranges.busread.second); active_ranges.lookup.first = std::min(dyadic_circuit_size - max_tables_size, active_ranges.lookup.first); @@ -78,7 +78,7 @@ struct ExecutionTraceUsageTracker { bool check_is_active(const size_t idx) { // If structured trace is not in use, assume the whole trace is active - if (trace_structure == TraceStructure::NONE) { + if (trace_settings.structure == TraceStructure::NONE) { return true; } for (auto& range : active_ranges.get()) { @@ -90,10 +90,17 @@ struct ExecutionTraceUsageTracker { } // For printing only. Must match the order of the members in the arithmetization - std::vector block_labels{ "ecc_op", "pub_inputs", "busread", - "arithmetic", "delta_range", "elliptic", - "aux", "poseidon2_external", "poseidon2_internal", - "lookup" }; + std::vector block_labels{ "ecc_op", + "pub_inputs", + "busread", + "arithmetic", + "delta_range", + "elliptic", + "aux", + "poseidon2_external", + "poseidon2_internal", + "lookup", + "overflow" }; void print() { @@ -140,7 +147,7 @@ struct ExecutionTraceUsageTracker { // Convert the active ranges for each gate type into a set of sorted non-overlapping ranges (union of the input) std::vector simplified_active_ranges; - if (trace_structure == TraceStructure::NONE) { + if (trace_settings.structure == TraceStructure::NONE) { // If not using a structured trace, set the active range to the whole domain simplified_active_ranges.push_back(Range{ 0, full_domain_size }); } else { diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/mega_arithmetization.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/mega_arithmetization.hpp index 6e8ed04a669..dffe7d5d25a 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/mega_arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/mega_arithmetization.hpp @@ -1,7 +1,9 @@ #pragma once +#include "barretenberg/common/ref_vector.hpp" #include "barretenberg/common/zip_view.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/numeric/bitop/get_msb.hpp" #include "barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp" #include "barretenberg/plonk_honk_shared/types/circuit_type.hpp" @@ -34,20 +36,44 @@ template class MegaArith { T poseidon2_external; T poseidon2_internal; T lookup; + T overflow; // block gates of arbitrary type that overflow their designated block + + std::vector get_labels() const + { + return { "ecc_op", "pub_inputs", "busread", + "arithmetic", "delta_range", "elliptic", + "aux", "poseidon2_external", "poseidon2_internal", + "lookup" }; + } auto get() { - return RefArray{ ecc_op, pub_inputs, busread, - arithmetic, delta_range, elliptic, - aux, poseidon2_external, poseidon2_internal, - lookup }; + return RefArray{ ecc_op, + pub_inputs, + busread, + arithmetic, + delta_range, + elliptic, + aux, + poseidon2_external, + poseidon2_internal, + lookup, + overflow }; } + auto get() const { - return RefArray{ ecc_op, pub_inputs, busread, - arithmetic, delta_range, elliptic, - aux, poseidon2_external, poseidon2_internal, - lookup }; + return RefArray{ ecc_op, + pub_inputs, + busread, + arithmetic, + delta_range, + elliptic, + aux, + poseidon2_external, + poseidon2_internal, + lookup, + overflow }; } auto get_gate_blocks() @@ -59,6 +85,23 @@ template class MegaArith { bool operator==(const MegaTraceBlocks& other) const = default; }; + // A tiny structuring (for testing without recursive verifications only) + struct TinyTestStructuredBlockSizes : public MegaTraceBlocks { + TinyTestStructuredBlockSizes() + { + this->ecc_op = 18; + this->pub_inputs = 1; + this->busread = 3; + this->arithmetic = 1 << 14; + this->delta_range = 5; + this->elliptic = 2; + this->aux = 10; + this->poseidon2_external = 2; + this->poseidon2_internal = 2; + this->lookup = 2; + this->overflow = 0; + } + }; // An arbitrary but small-ish structuring that can be used for generic unit testing with non-trivial circuits struct SmallTestStructuredBlockSizes : public MegaTraceBlocks { SmallTestStructuredBlockSizes() @@ -74,6 +117,7 @@ template class MegaArith { this->poseidon2_external = FIXED_SIZE; this->poseidon2_internal = 1 << 15; this->lookup = FIXED_SIZE; + this->overflow = 0; } }; @@ -92,6 +136,7 @@ template class MegaArith { this->poseidon2_external = 2500; this->poseidon2_internal = 14000; this->lookup = 72000; + this->overflow = 0; // Additional structurings for testing // // 2^18 (Only viable if no 2^19 circuit is used!) @@ -105,6 +150,7 @@ template class MegaArith { // this->poseidon2_external = 2500; // this->poseidon2_internal = 14000; // this->lookup = 36000; + // this->overflow = 0; // // 2^20 // this->ecc_op = 1 << 11; @@ -117,6 +163,7 @@ template class MegaArith { // this->poseidon2_external = 5000; // this->poseidon2_internal = 28000; // this->lookup = 144000; + // this->overflow = 0; } }; @@ -134,6 +181,7 @@ template class MegaArith { this->poseidon2_external = 30128; this->poseidon2_internal = 172000; this->lookup = 200000; + this->overflow = 0; } }; @@ -143,6 +191,8 @@ template class MegaArith { using FF = FF_; class MegaTraceBlock : public ExecutionTraceBlock { + using SelectorType = ExecutionTraceBlock::SelectorType; + public: void populate_wires(const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3, const uint32_t& idx_4) { @@ -176,6 +226,18 @@ template class MegaArith { auto& q_poseidon2_internal() { return this->selectors[12]; }; auto& q_lookup_type() { return this->selectors[13]; }; + RefVector get_gate_selectors() + { + return { q_busread(), + q_arith(), + q_delta_range(), + q_elliptic(), + q_aux(), + q_poseidon2_external(), + q_poseidon2_internal(), + q_lookup_type() }; + } + /** * @brief Add zeros to all selectors which are not part of the conventional Ultra arithmetization * @details Facilitates reuse of Ultra gate construction functions in arithmetizations which extend the @@ -195,6 +257,8 @@ template class MegaArith { struct TraceBlocks : public MegaTraceBlocks { + bool has_overflow = false; // indicates whether the overflow block has non-zero fixed or actual size + TraceBlocks() { this->aux.has_ram_rom = true; @@ -202,13 +266,16 @@ template class MegaArith { } // Set fixed block sizes for use in structured trace - void set_fixed_block_sizes(TraceStructure setting) + void set_fixed_block_sizes(TraceSettings settings) { MegaTraceBlocks fixed_block_sizes{}; // zero initialized - switch (setting) { + switch (settings.structure) { case TraceStructure::NONE: break; + case TraceStructure::TINY_TEST: + fixed_block_sizes = TinyTestStructuredBlockSizes(); + break; case TraceStructure::SMALL_TEST: fixed_block_sizes = SmallTestStructuredBlockSizes(); break; @@ -222,6 +289,8 @@ template class MegaArith { for (auto [block, size] : zip_view(this->get(), fixed_block_sizes.get())) { block.set_fixed_size(size); } + // Set the size of overflow block containing the overflow from all other blocks + this->overflow.set_fixed_size(settings.overflow_capacity); } void compute_offsets(bool is_structured) @@ -237,7 +306,11 @@ template class MegaArith { { info("Gate blocks summary: (actual gates / fixed capacity)"); info("goblin ecc op :\t", this->ecc_op.size(), "/", this->ecc_op.get_fixed_size()); - info("pub inputs :\t", this->pub_inputs.size(), "/", this->pub_inputs.get_fixed_size()); + info("pub inputs :\t", + this->pub_inputs.size(), + "/", + this->pub_inputs.get_fixed_size(), + " (populated in decider pk constructor)"); info("busread :\t", this->busread.size(), "/", this->busread.get_fixed_size()); info("arithmetic :\t", this->arithmetic.size(), "/", this->arithmetic.get_fixed_size()); info("delta range :\t", this->delta_range.size(), "/", this->delta_range.get_fixed_size()); @@ -246,29 +319,22 @@ template class MegaArith { info("poseidon ext :\t", this->poseidon2_external.size(), "/", this->poseidon2_external.get_fixed_size()); info("poseidon int :\t", this->poseidon2_internal.size(), "/", this->poseidon2_internal.get_fixed_size()); info("lookups :\t", this->lookup.size(), "/", this->lookup.get_fixed_size()); + info("overflow :\t", this->overflow.size(), "/", this->overflow.get_fixed_size()); info(""); } - size_t get_total_structured_size() + size_t get_structured_dyadic_size() { - size_t total_size = 0; + size_t total_size = 1; // start at 1 because the 0th row is unused for selectors for Honk for (auto block : this->get()) { total_size += block.get_fixed_size(); } - return total_size; - } - - void check_within_fixed_sizes() - { - for (auto block : this->get()) { - if (block.size() > block.get_fixed_size()) { - info("WARNING: Num gates in circuit block exceeds the specified fixed size - execution trace will " - "not be constructed correctly!"); - summarize(); - ASSERT(false); - } + auto log2_n = static_cast(numeric::get_msb(total_size)); + if ((1UL << log2_n) != (total_size)) { + ++log2_n; } + return 1UL << log2_n; } bool operator==(const TraceBlocks& other) const = default; diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/ultra_arithmetization.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/ultra_arithmetization.hpp index be1e47fac17..d4443a11dbd 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/ultra_arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/ultra_arithmetization.hpp @@ -1,5 +1,7 @@ #pragma once +#include "barretenberg/common/ref_vector.hpp" +#include "barretenberg/numeric/bitop/get_msb.hpp" #include "barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp" namespace bb { @@ -23,11 +25,12 @@ template class UltraArith { T lookup; T poseidon2_external; T poseidon2_internal; + T overflow; auto get() { - return RefArray{ pub_inputs, arithmetic, delta_range, elliptic, - aux, lookup, poseidon2_external, poseidon2_internal }; + return RefArray{ pub_inputs, arithmetic, delta_range, elliptic, aux, + lookup, poseidon2_external, poseidon2_internal, overflow }; } auto get_gate_blocks() @@ -51,6 +54,7 @@ template class UltraArith { this->lookup = FIXED_SIZE; this->poseidon2_external = FIXED_SIZE; this->poseidon2_internal = FIXED_SIZE; + this->overflow = 0; } }; @@ -60,6 +64,8 @@ template class UltraArith { using FF = FF_; class UltraTraceBlock : public ExecutionTraceBlock { + using SelectorType = ExecutionTraceBlock::SelectorType; + public: void populate_wires(const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3, const uint32_t& idx_4) { @@ -91,10 +97,19 @@ template class UltraArith { auto& q_lookup_type() { return this->selectors[10]; }; auto& q_poseidon2_external() { return this->selectors[11]; }; auto& q_poseidon2_internal() { return this->selectors[12]; }; + + RefVector get_gate_selectors() + { + return { q_arith(), q_delta_range(), q_elliptic(), + q_aux(), q_poseidon2_external(), q_poseidon2_internal(), + q_lookup_type() }; + } }; struct TraceBlocks : public UltraTraceBlocks { + bool has_overflow = false; + TraceBlocks() { this->aux.has_ram_rom = true; @@ -102,14 +117,15 @@ template class UltraArith { } // Set fixed block sizes for use in structured trace - void set_fixed_block_sizes(TraceStructure setting) + void set_fixed_block_sizes(TraceSettings settings) { UltraTraceBlocks fixed_block_sizes{}; // zero initialized - switch (setting) { + switch (settings.structure) { case TraceStructure::NONE: break; // We don't use Ultra in ClientIvc so no need for anything other than sizing for simple unit tests + case TraceStructure::TINY_TEST: case TraceStructure::SMALL_TEST: case TraceStructure::CLIENT_IVC_BENCH: case TraceStructure::E2E_FULL_TEST: @@ -119,6 +135,7 @@ template class UltraArith { for (auto [block, size] : zip_view(this->get(), fixed_block_sizes.get())) { block.set_fixed_size(size); } + this->overflow.set_fixed_size(settings.overflow_capacity); } void compute_offsets(bool is_structured) @@ -133,7 +150,8 @@ template class UltraArith { auto get() { return RefArray{ this->pub_inputs, this->arithmetic, this->delta_range, this->elliptic, - this->aux, this->lookup, this->poseidon2_external, this->poseidon2_internal }; + this->aux, this->lookup, this->poseidon2_external, this->poseidon2_internal, + this->overflow }; } void summarize() const @@ -147,31 +165,21 @@ template class UltraArith { info("lookups :\t", this->lookup.size()); info("poseidon ext :\t", this->poseidon2_external.size()); info("poseidon int :\t", this->poseidon2_internal.size()); + info("overflow :\t", this->overflow.size()); } - size_t get_total_structured_size() + size_t get_structured_dyadic_size() { size_t total_size = 1; // start at 1 because the 0th row is unused for selectors for Honk for (auto block : this->get()) { total_size += block.get_fixed_size(); } - return total_size; - } - /** - * @brief Check that the number of rows populated in each block does not exceed the specified fixed size - * @note This check is only applicable when utilizing a structured trace - * - */ - void check_within_fixed_sizes() - { - for (auto block : this->get()) { - if (block.size() > block.get_fixed_size()) { - info("WARNING: Num gates in circuit block exceeds the specified fixed size - execution trace will " - "not be constructed correctly!"); - ASSERT(false); - } + auto log2_n = static_cast(numeric::get_msb(total_size)); + if ((1UL << log2_n) != (total_size)) { + ++log2_n; } + return 1UL << log2_n; } bool operator==(const TraceBlocks& other) const = default; diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp index bf2859365d0..58b1d35630a 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_library.hpp @@ -13,7 +13,7 @@ namespace bb { // product. Update comments accordingly. /** * @brief Compute a permutation grand product polynomial Z_perm(X) - * * + * * @details * Z_perm may be defined in terms of its values on X_i = 0,1,...,n-1 as Z_perm[0] = 1 and for i = 1:n-1 * relation::numerator(j) @@ -46,31 +46,52 @@ namespace bb { * Step 3) Compute Z_perm[i + 1] = numerator[i] / denominator[i] (recall: Z_perm[0] = 1) * * Note: Step (3) utilizes Montgomery batch inversion to replace n-many inversions with + * + * @tparam Flavor + * @tparam GrandProdRelation + * @param full_polynomials + * @param relation_parameters + * @param size_override optional size of the domain; otherwise based on dyadic polynomial domain */ template void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, - bb::RelationParameters& relation_parameters) + bb::RelationParameters& relation_parameters, + size_t size_override = 0) { using FF = typename Flavor::FF; using Polynomial = typename Flavor::Polynomial; using Accumulator = std::tuple_element_t<0, typename GrandProdRelation::SumcheckArrayOfValuesOverSubrelations>; + // Set the domain over which the grand product must be computed. This may be less than the dyadic circuit size, e.g + // the permutation grand product does not need to be computed beyond the index of the last active wire + size_t domain_size = size_override == 0 ? full_polynomials.get_polynomial_size() : size_override; + + const size_t num_threads = domain_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; + const size_t block_size = domain_size / num_threads; + const size_t final_idx = domain_size - 1; + + // Cumpute the index bounds for each thread for reuse in the computations below + std::vector> idx_bounds; + idx_bounds.reserve(num_threads); + for (size_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) { + const size_t start = thread_idx * block_size; + const size_t end = (thread_idx == num_threads - 1) ? final_idx : (thread_idx + 1) * block_size; + idx_bounds.push_back(std::make_pair(start, end)); + } + // Allocate numerator/denominator polynomials that will serve as scratch space // TODO(zac) we can re-use the permutation polynomial as the numerator polynomial. Reduces readability - size_t circuit_size = full_polynomials.get_polynomial_size(); - Polynomial numerator{ circuit_size, circuit_size }; - Polynomial denominator{ circuit_size, circuit_size }; + Polynomial numerator{ domain_size, domain_size }; + Polynomial denominator{ domain_size, domain_size }; // Step (1) // Populate `numerator` and `denominator` with the algebra described by Relation - const size_t num_threads = circuit_size >= get_num_cpus_pow2() ? get_num_cpus_pow2() : 1; - const size_t block_size = circuit_size / num_threads; parallel_for(num_threads, [&](size_t thread_idx) { - const size_t start = thread_idx * block_size; - const size_t end = (thread_idx + 1) * block_size; typename Flavor::AllValues evaluations; // TODO(https://github.com/AztecProtocol/barretenberg/issues/940): construction of evaluations is equivalent to // calling get_row which creates full copies. avoid? + const size_t start = idx_bounds[thread_idx].first; + const size_t end = idx_bounds[thread_idx].second; for (size_t i = start; i < end; ++i) { for (auto [eval, full_poly] : zip_view(evaluations.get_all(), full_polynomials.get_all())) { eval = full_poly.size() > i ? full_poly[i] : 0; @@ -101,8 +122,8 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, std::vector partial_denominators(num_threads); parallel_for(num_threads, [&](size_t thread_idx) { - const size_t start = thread_idx * block_size; - const size_t end = (thread_idx + 1) * block_size; + const size_t start = idx_bounds[thread_idx].first; + const size_t end = idx_bounds[thread_idx].second; for (size_t i = start; i < end - 1; ++i) { numerator.at(i + 1) *= numerator[i]; denominator.at(i + 1) *= denominator[i]; @@ -115,8 +136,8 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, DEBUG_LOG_ALL(partial_denominators); parallel_for(num_threads, [&](size_t thread_idx) { - const size_t start = thread_idx * block_size; - const size_t end = (thread_idx + 1) * block_size; + const size_t start = idx_bounds[thread_idx].first; + const size_t end = idx_bounds[thread_idx].second; if (thread_idx > 0) { FF numerator_scaling = 1; FF denominator_scaling = 1; @@ -132,7 +153,7 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, } // Final step: invert denominator - FF::batch_invert(std::span{ &denominator.data()[start], block_size }); + FF::batch_invert(std::span{ &denominator.data()[start], end - start }); }); DEBUG_LOG_ALL(numerator.coeffs()); @@ -143,8 +164,8 @@ void compute_grand_product(typename Flavor::ProverPolynomials& full_polynomials, // We have a 'virtual' 0 at the start (as this is a to-be-shifted polynomial) ASSERT(grand_product_polynomial.start_index() == 1); parallel_for(num_threads, [&](size_t thread_idx) { - const size_t start = thread_idx * block_size; - const size_t end = (thread_idx == num_threads - 1) ? circuit_size - 1 : (thread_idx + 1) * block_size; + const size_t start = idx_bounds[thread_idx].first; + const size_t end = idx_bounds[thread_idx].second; for (size_t i = start; i < end; ++i) { grand_product_polynomial.at(i + 1) = numerator[i] * denominator[i]; } diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp index 0483f2214a8..a765b439daf 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp @@ -48,16 +48,16 @@ template class ProtogalaxyTests : public testing::Test { static void construct_circuit(Builder& builder) { MockCircuits::add_arithmetic_gates(builder); - if constexpr (IsGoblinFlavor) { + if constexpr (IsMegaFlavor) { GoblinMockCircuits::add_some_ecc_op_gates(builder); } } // Construct decider keys for a provided circuit and add to tuple - static void construct_keys(TupleOfKeys& keys, Builder& builder, TraceStructure structure = TraceStructure::NONE) + static void construct_keys(TupleOfKeys& keys, Builder& builder, TraceSettings trace_settings = TraceSettings{}) { - auto decider_proving_key = std::make_shared(builder, structure); + auto decider_proving_key = std::make_shared(builder, trace_settings); auto verification_key = std::make_shared(decider_proving_key->proving_key); auto decider_verification_keys = std::make_shared(verification_key); get<0>(keys).emplace_back(decider_proving_key); @@ -65,7 +65,7 @@ template class ProtogalaxyTests : public testing::Test { } // Construct a given numer of decider key pairs - static TupleOfKeys construct_keys(size_t num_keys, TraceStructure structure = TraceStructure::NONE) + static TupleOfKeys construct_keys(size_t num_keys, TraceSettings trace_settings = TraceSettings{}) { TupleOfKeys keys; // TODO(https://github.com/AztecProtocol/barretenberg/issues/938): Parallelize this loop @@ -73,7 +73,7 @@ template class ProtogalaxyTests : public testing::Test { auto builder = typename Flavor::CircuitBuilder(); construct_circuit(builder); - construct_keys(keys, builder, structure); + construct_keys(keys, builder, trace_settings); } return keys; } @@ -143,7 +143,8 @@ template class ProtogalaxyTests : public testing::Test { decider_pk->relation_parameters.eta_two, decider_pk->relation_parameters.eta_three); decider_pk->proving_key.compute_logderivative_inverses(decider_pk->relation_parameters); - decider_pk->proving_key.compute_grand_product_polynomials(decider_pk->relation_parameters); + decider_pk->proving_key.compute_grand_product_polynomial(decider_pk->relation_parameters, + decider_pk->final_active_wire_idx + 1); for (auto& alpha : decider_pk->alphas) { alpha = FF::random_element(); @@ -442,13 +443,13 @@ template class ProtogalaxyTests : public testing::Test { */ static void test_full_protogalaxy_structured_trace() { - TraceStructure trace_structure = TraceStructure::SMALL_TEST; - TupleOfKeys keys_1 = construct_keys(2, trace_structure); + TraceSettings trace_settings{ TraceStructure::SMALL_TEST }; + TupleOfKeys keys_1 = construct_keys(2, trace_settings); auto [prover_accumulator, verifier_accumulator] = fold_and_verify(get<0>(keys_1), get<1>(keys_1)); check_accumulator_target_sum_manual(prover_accumulator, true); - TupleOfKeys keys_2 = construct_keys(1, trace_structure); // just one key pair + TupleOfKeys keys_2 = construct_keys(1, trace_settings); // just one key pair auto [prover_accumulator_2, verifier_accumulator_2] = fold_and_verify({ prover_accumulator, get<0>(keys_2)[0] }, { verifier_accumulator, get<1>(keys_2)[0] }); @@ -465,7 +466,7 @@ template class ProtogalaxyTests : public testing::Test { */ static void test_full_protogalaxy_structured_trace_inhomogeneous_circuits() { - TraceStructure trace_structure = TraceStructure::SMALL_TEST; + TraceSettings trace_settings{ TraceStructure::SMALL_TEST }; // Construct three circuits to be folded, each with a different number of constraints Builder builder1; @@ -482,8 +483,8 @@ template class ProtogalaxyTests : public testing::Test { // Construct the decider key pairs for the first two circuits TupleOfKeys keys_1; - construct_keys(keys_1, builder1, trace_structure); - construct_keys(keys_1, builder2, trace_structure); + construct_keys(keys_1, builder1, trace_settings); + construct_keys(keys_1, builder2, trace_settings); // Fold the first two pairs auto [prover_accumulator, verifier_accumulator] = fold_and_verify(get<0>(keys_1), get<1>(keys_1)); @@ -491,7 +492,7 @@ template class ProtogalaxyTests : public testing::Test { // Construct the decider key pair for the third circuit TupleOfKeys keys_2; - construct_keys(keys_2, builder3, trace_structure); + construct_keys(keys_2, builder3, trace_settings); // Fold 3rd pair of keys into their respective accumulators auto [prover_accumulator_2, verifier_accumulator_2] = diff --git a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_flavor.hpp index f486752a9cb..637fe115c07 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_flavor.hpp @@ -45,8 +45,8 @@ template class ECCVMRecursiveFlavor_ { static constexpr size_t NUM_PRECOMPUTED_ENTITIES = ECCVMFlavor::NUM_PRECOMPUTED_ENTITIES; // The total number of witness entities not including shifts. static constexpr size_t NUM_WITNESS_ENTITIES = ECCVMFlavor::NUM_WITNESS_ENTITIES; - static constexpr size_t NUM_ALL_WITNESS_ENTITIES = ECCVMFlavor::NUM_ALL_WITNESS_ENTITIES; + static constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS = ECCVMFlavor::REPEATED_COMMITMENTS; // define the tuple of Relations that comprise the Sumcheck relation // Reuse the Relations from ECCVM using Relations = ECCVMFlavor::Relations_; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp index e6f677aeb3b..dd1868f2cc6 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.cpp @@ -16,7 +16,7 @@ ECCVMRecursiveVerifier_::ECCVMRecursiveVerifier_( /** * @brief This function verifies an ECCVM Honk proof for given program settings up to sumcheck. */ -template void ECCVMRecursiveVerifier_::verify_proof(const HonkProof& proof) +template void ECCVMRecursiveVerifier_::verify_proof(const ECCVMProof& proof) { using Curve = typename Flavor::Curve; using Shplemini = ShpleminiVerifier_; @@ -25,8 +25,10 @@ template void ECCVMRecursiveVerifier_::verify_proof(co RelationParameters relation_parameters; - StdlibProof stdlib_proof = bb::convert_proof_to_witness(builder, proof); + StdlibProof stdlib_proof = bb::convert_proof_to_witness(builder, proof.pre_ipa_proof); + StdlibProof stdlib_ipa_proof = bb::convert_proof_to_witness(builder, proof.ipa_proof); transcript = std::make_shared(stdlib_proof); + ipa_transcript = std::make_shared(stdlib_ipa_proof); VerifierCommitments commitments{ key }; CommitmentLabels commitment_labels; @@ -92,8 +94,10 @@ template void ECCVMRecursiveVerifier_::verify_proof(co multivariate_challenge, key->pcs_verification_key->get_g1_identity(), transcript, + Flavor::REPEATED_COMMITMENTS, RefVector(libra_commitments), libra_evaluations); + // Reduce the accumulator to a single opening claim const OpeningClaim multivariate_to_univariate_opening_claim = PCS::reduce_batch_opening_claim(sumcheck_batch_opening_claims); @@ -140,7 +144,7 @@ template void ECCVMRecursiveVerifier_::verify_proof(co // TODO(https://github.com/AztecProtocol/barretenberg/issues/1142): Handle this return value correctly. const typename PCS::VerifierAccumulator batched_opening_accumulator = - PCS::reduce_verify(batch_opening_claim, transcript); + PCS::reduce_verify(batch_opening_claim, ipa_transcript); ASSERT(sumcheck_verified); } diff --git a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.hpp index 6a590ebba40..58103e9644b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.hpp @@ -21,11 +21,12 @@ template class ECCVMRecursiveVerifier_ { const std::shared_ptr& native_verifier_key); // TODO(https://github.com/AztecProtocol/barretenberg/issues/991): switch recursive verifiers to StdlibProof - void verify_proof(const HonkProof& proof); + void verify_proof(const ECCVMProof& proof); std::shared_ptr key; Builder* builder; std::shared_ptr transcript; + std::shared_ptr ipa_transcript; }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.test.cpp index 1c2d82719aa..0aae8567845 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.test.cpp @@ -77,7 +77,7 @@ template class ECCVMRecursiveTests : public ::testing { InnerBuilder builder = generate_circuit(&engine); InnerProver prover(builder); - auto proof = prover.construct_proof(); + ECCVMProof proof = prover.construct_proof(); auto verification_key = std::make_shared(prover.key); info("ECCVM Recursive Verifier"); @@ -128,7 +128,7 @@ template class ECCVMRecursiveTests : public ::testing InnerBuilder builder = generate_circuit(&engine); builder.op_queue->add_erroneous_equality_op_for_testing(); InnerProver prover(builder); - auto proof = prover.construct_proof(); + ECCVMProof proof = prover.construct_proof(); auto verification_key = std::make_shared(prover.key); OuterBuilder outer_circuit; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp index 1449b0695b4..80ee773f2df 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp @@ -112,7 +112,7 @@ TEST_F(GoblinRecursiveVerifierTests, ECCVMFailure) auto [proof, verifier_input] = create_goblin_prover_output(); // Tamper with the ECCVM proof - for (auto& val : proof.eccvm_proof) { + for (auto& val : proof.eccvm_proof.pre_ipa_proof) { if (val > 0) { // tamper by finding the tenth non-zero value and incrementing it by 1 // tamper by finding the first non-zero value // and incrementing it by 1 diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp index a47470cf577..3bbb2611cfb 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp @@ -31,14 +31,15 @@ std::array DeciderRecursiveVerifier_:: sumcheck.verify(accumulator->relation_parameters, accumulator->alphas, accumulator->gate_challenges); // Execute Shplemini rounds. - auto opening_claim = Shplemini::compute_batch_opening_claim(accumulator->verification_key->circuit_size, - commitments.get_unshifted(), - commitments.get_to_be_shifted(), - claimed_evaluations.get_unshifted(), - claimed_evaluations.get_shifted(), - multivariate_challenge, - Commitment::one(builder), - transcript); + const auto opening_claim = Shplemini::compute_batch_opening_claim(accumulator->verification_key->circuit_size, + commitments.get_unshifted(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + Commitment::one(builder), + transcript, + Flavor::REPEATED_COMMITMENTS); auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); return pairing_points; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp index 8c79fa753f0..6e09db90b52 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp @@ -68,7 +68,7 @@ template void OinkRecursiveVerifier_::verify() commitments.w_o = transcript->template receive_from_prover(domain_separator + labels.w_o); // If Goblin, get commitments to ECC op wire polynomials and DataBus columns - if constexpr (IsGoblinFlavor) { + if constexpr (IsMegaFlavor) { // Receive ECC op wire commitments for (auto [commitment, label] : zip_view(commitments.get_ecc_op_wires(), labels.get_ecc_op_wires())) { commitment = transcript->template receive_from_prover(domain_separator + label); @@ -98,7 +98,7 @@ template void OinkRecursiveVerifier_::verify() transcript->template receive_from_prover(domain_separator + labels.lookup_inverses); // If Goblin (i.e. using DataBus) receive commitments to log-deriv inverses polynomials - if constexpr (IsGoblinFlavor) { + if constexpr (IsMegaFlavor) { for (auto [commitment, label] : zip_view(commitments.get_databus_inverses(), labels.get_databus_inverses())) { commitment = transcript->template receive_from_prover(domain_separator + label); } diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index 5928b8a0bff..26c2297b41d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -117,8 +117,10 @@ UltraRecursiveVerifier_::AggregationObject UltraRecursiveVerifier_ @@ -240,7 +242,10 @@ cycle_group cycle_group::dbl() const auto x3 = lambda_squared - x1 - x1; auto y3 = lambda * (x1 - x3) - y1; if (is_constant()) { - return cycle_group(x3, y3, is_point_at_infinity().get_value()); + auto result = cycle_group(x3, y3, is_point_at_infinity().get_value()); + // We need to manually propagate the origin tag + result.set_origin_tag(get_origin_tag()); + return result; } cycle_group result(witness_t(context, x3), witness_t(context, y3), is_point_at_infinity()); context->create_ecc_dbl_gate(bb::ecc_dbl_gate_{ @@ -249,6 +254,10 @@ cycle_group cycle_group::dbl() const .x3 = result.x.get_witness_index(), .y3 = result.y.get_witness_index(), }); + + // We need to manually propagate the origin tag + result.x.set_origin_tag(OriginTag(x.get_origin_tag(), y.get_origin_tag())); + result.y.set_origin_tag(OriginTag(x.get_origin_tag(), y.get_origin_tag())); return result; } @@ -297,10 +306,14 @@ cycle_group cycle_group::unconditional_add(const cycle_group& const bool rhs_constant = other.is_constant(); if (lhs_constant && !rhs_constant) { auto lhs = cycle_group::from_constant_witness(context, get_value()); + // We need to manually propagate the origin tag + lhs.set_origin_tag(get_origin_tag()); return lhs.unconditional_add(other); } if (!lhs_constant && rhs_constant) { auto rhs = cycle_group::from_constant_witness(context, other.get_value()); + // We need to manually propagate the origin tag + rhs.set_origin_tag(other.get_origin_tag()); return unconditional_add(rhs); } @@ -308,7 +321,10 @@ cycle_group cycle_group::unconditional_add(const cycle_group& const auto p2 = other.get_value(); AffineElement p3(Element(p1) + Element(p2)); if (lhs_constant && rhs_constant) { - return cycle_group(p3); + auto result = cycle_group(p3); + // We need to manually propagate the origin tag + result.set_origin_tag(OriginTag(get_origin_tag(), other.get_origin_tag())); + return result; } field_t r_x(witness_t(context, p3.x)); field_t r_y(witness_t(context, p3.y)); @@ -325,6 +341,8 @@ cycle_group cycle_group::unconditional_add(const cycle_group& }; context->create_ecc_add_gate(add_gate); + // We need to manually propagate the origin tag (merging the tag of two inputs) + result.set_origin_tag(OriginTag(get_origin_tag(), other.get_origin_tag())); return result; } @@ -350,17 +368,24 @@ cycle_group cycle_group::unconditional_subtract(const cycle_gr if (lhs_constant && !rhs_constant) { auto lhs = cycle_group::from_constant_witness(context, get_value()); + // We need to manually propagate the origin tag + lhs.set_origin_tag(get_origin_tag()); return lhs.unconditional_subtract(other); } if (!lhs_constant && rhs_constant) { auto rhs = cycle_group::from_constant_witness(context, other.get_value()); + // We need to manually propagate the origin tag + rhs.set_origin_tag(other.get_origin_tag()); return unconditional_subtract(rhs); } auto p1 = get_value(); auto p2 = other.get_value(); AffineElement p3(Element(p1) - Element(p2)); if (lhs_constant && rhs_constant) { - return cycle_group(p3); + auto result = cycle_group(p3); + // We need to manually propagate the origin tag + result.set_origin_tag(OriginTag(get_origin_tag(), other.get_origin_tag())); + return result; } field_t r_x(witness_t(context, p3.x)); field_t r_y(witness_t(context, p3.y)); @@ -377,6 +402,8 @@ cycle_group cycle_group::unconditional_subtract(const cycle_gr }; context->create_ecc_add_gate(add_gate); + // We need to manually propagate the origin tag (merging the tag of two inputs) + result.set_origin_tag(OriginTag(get_origin_tag(), other.get_origin_tag())); return result; } } @@ -593,6 +620,9 @@ template cycle_group::cycle_scalar::cycle_scalar(con // bb::fq modulus otherwise we could have two representations for in validate_scalar_is_in_field(); } + // We need to manually propagate the origin tag + lo.set_origin_tag(in.get_origin_tag()); + hi.set_origin_tag(in.get_origin_tag()); } template cycle_group::cycle_scalar::cycle_scalar(const ScalarField& in) @@ -663,6 +693,11 @@ typename cycle_group::cycle_scalar cycle_group::cycle_scalar:: field_t lo = witness_t(in.get_context(), lo_v); field_t hi = witness_t(in.get_context(), hi_v); lo.add_two(hi * (uint256_t(1) << LO_BITS), -in).assert_equal(0); + + // We need to manually propagate the origin tag + lo.set_origin_tag(in.get_origin_tag()); + hi.set_origin_tag(in.get_origin_tag()); + cycle_scalar result{ lo, hi, NUM_BITS, skip_primality_test, true }; return result; } @@ -783,6 +818,9 @@ template cycle_group::cycle_scalar::cycle_scalar(Big // construct *this.hi out of limb2, limb3 and the remaining term from limb1 not contributing to `lo` hi = limb_1_hi.add_two(limb2 * limb_2_shift, limb3 * limb_3_shift); } + // We need to manually propagate the origin tag + lo.set_origin_tag(scalar.get_origin_tag()); + hi.set_origin_tag(scalar.get_origin_tag()); }; template bool cycle_group::cycle_scalar::is_constant() const @@ -876,6 +914,7 @@ cycle_group::straus_scalar_slice::straus_scalar_slice(Builder* context, result.push_back(field_t(slice_v)); raw_value = raw_value >> table_bits; } + return result; } if constexpr (IS_ULTRA) { @@ -919,6 +958,11 @@ cycle_group::straus_scalar_slice::straus_scalar_slice(Builder* context, std::copy(lo_slices.begin(), lo_slices.end(), std::back_inserter(slices)); std::copy(hi_slices.begin(), hi_slices.end(), std::back_inserter(slices)); + const auto tag = scalar.get_origin_tag(); + for (auto& element : slices) { + // All slices need to have the same origin tag + element.set_origin_tag(tag); + } } /** @@ -960,6 +1004,7 @@ cycle_group::straus_lookup_table::straus_lookup_table(Builder* context, size_t table_bits) : _table_bits(table_bits) , _context(context) + , tag(OriginTag(base_point.get_origin_tag(), offset_generator.get_origin_tag())) { const size_t table_size = 1UL << table_bits; point_table.resize(table_size); @@ -1020,10 +1065,17 @@ template cycle_group cycle_group::straus_lo auto output_indices = _context->read_ROM_array_pair(rom_id, index.get_witness_index()); field_t x = field_t::from_witness_index(_context, output_indices[0]); field_t y = field_t::from_witness_index(_context, output_indices[1]); + // Merge tag of table with tag of index + x.set_origin_tag(OriginTag(tag, _index.get_origin_tag())); + y.set_origin_tag(OriginTag(tag, _index.get_origin_tag())); return cycle_group(x, y, false); } field_t x = _index * (point_table[1].x - point_table[0].x) + point_table[0].x; field_t y = _index * (point_table[1].y - point_table[0].y) + point_table[0].y; + + // Merge tag of table with tag of index + x.set_origin_tag(OriginTag(tag, _index.get_origin_tag())); + y.set_origin_tag(OriginTag(tag, _index.get_origin_tag())); return cycle_group(x, y, false); } @@ -1086,7 +1138,10 @@ typename cycle_group::batch_mul_internal_output cycle_group::_ std::vector scalar_slices; std::vector point_tables; + OriginTag tag{}; for (size_t i = 0; i < num_points; ++i) { + // Merge tags + tag = OriginTag(tag, scalars[i].get_origin_tag(), base_points[i].get_origin_tag()); scalar_slices.emplace_back(straus_scalar_slice(context, scalars[i], TABLE_BITS)); point_tables.emplace_back(straus_lookup_table(context, base_points[i], offset_generators[i + 1], TABLE_BITS)); } @@ -1140,6 +1195,9 @@ typename cycle_group::batch_mul_internal_output cycle_group::_ auto x_diff = x2 - x1; x_diff.assert_is_not_zero("_variable_base_batch_mul_internal x-coordinate collision"); } + + // Set the final accumulator's tag to the union of all points' and scalars' tags + accumulator.set_origin_tag(tag); /** * offset_generator_accumulator represents the sum of all the offset generator terms present in `accumulator`. * We don't subtract off yet, as we may be able to combine `offset_generator_accumulator` with other constant terms @@ -1177,7 +1235,11 @@ typename cycle_group::batch_mul_internal_output cycle_group::_ std::vector plookup_base_points; std::vector plookup_scalars; + OriginTag tag{}; for (size_t i = 0; i < num_points; ++i) { + // Merge all tags of scalars (we don't have to account for CircuitSimulator in cycle_group yet, because it + // breaks) + tag = OriginTag(tag, scalars[i].get_origin_tag()); std::optional> table_id = plookup::fixed_base::table::get_lookup_table_ids_for_point(base_points[i]); ASSERT(table_id.has_value()); @@ -1218,6 +1280,8 @@ typename cycle_group::batch_mul_internal_output cycle_group::_ * We don't subtract off yet, as we may be able to combine `offset_generator_accumulator` with other constant terms * in `batch_mul` before performing the subtraction. */ + // Set accumulator's origin tag to the union of all scalars' tags + accumulator.set_origin_tag(tag); return { accumulator, offset_generator_accumulator }; } @@ -1354,6 +1418,11 @@ cycle_group cycle_group::batch_mul(const std::vector fixed_base_scalars; std::vector fixed_base_points; + // Merge all tags + OriginTag result_tag; + for (auto [point, scalar] : zip_view(base_points, scalars)) { + result_tag = OriginTag(result_tag, OriginTag(point.get_origin_tag(), scalar.get_origin_tag())); + } size_t num_bits = 0; for (auto& s : scalars) { num_bits = std::max(num_bits, s.num_bits()); @@ -1409,7 +1478,9 @@ cycle_group cycle_group::batch_mul(const std::vector cycle_group::batch_mul(const std::vector namespace bb::stdlib { @@ -107,6 +108,22 @@ template class cycle_group { void validate_scalar_is_in_field() const; explicit cycle_scalar(BigScalarField&); + /** + * @brief Get the origin tag of the cycle_scalar (a merge of the lo and hi tags) + * + * @return OriginTag + */ + OriginTag get_origin_tag() const { return OriginTag(lo.get_origin_tag(), hi.get_origin_tag()); } + /** + * @brief Set the origin tag of lo and hi members of cycle scalar + * + * @param tag + */ + void set_origin_tag(const OriginTag& tag) + { + lo.set_origin_tag(tag); + hi.set_origin_tag(tag); + } }; /** @@ -158,6 +175,7 @@ template class cycle_group { Builder* _context; std::vector point_table; size_t rom_id = 0; + OriginTag tag{}; }; private: @@ -223,6 +241,28 @@ template class cycle_group { void assert_equal(const cycle_group& other, std::string const& msg = "cycle_group::assert_equal") const; static cycle_group conditional_assign(const bool_t& predicate, const cycle_group& lhs, const cycle_group& rhs); cycle_group operator/(const cycle_group& other) const; + + /** + * @brief Set the origin tag for x, y and _is_infinity members of cycle_group + * + * @param tag + */ + void set_origin_tag(OriginTag tag) + { + x.set_origin_tag(tag); + y.set_origin_tag(tag); + _is_infinity.set_origin_tag(tag); + } + /** + * @brief Get the origin tag of cycle_group (a merege of origin tags of x, y and _is_infinity members) + * + * @return OriginTag + */ + OriginTag get_origin_tag() const + { + return OriginTag(x.get_origin_tag(), y.get_origin_tag(), _is_infinity.get_origin_tag()); + } + field_t x; field_t y; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.test.cpp index 37a3c19f47c..def534437d1 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/group/cycle_group.test.cpp @@ -1,5 +1,6 @@ #include "barretenberg/stdlib/primitives/group/cycle_group.hpp" #include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/common/ref_span.hpp" #include "barretenberg/crypto/pedersen_commitment/pedersen.hpp" #include "barretenberg/crypto/pedersen_hash/pedersen.hpp" #include "barretenberg/numeric/random/engine.hpp" @@ -7,6 +8,7 @@ #include "barretenberg/stdlib/primitives/field/field.hpp" #include "barretenberg/stdlib/primitives/witness/witness.hpp" #include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" +#include "barretenberg/transcript/origin_tag.hpp" #include #define STDLIB_TYPE_ALIASES \ @@ -51,6 +53,37 @@ template class CycleGroupTest : public ::testing::Test { using CircuitTypes = ::testing::Types; TYPED_TEST_SUITE(CycleGroupTest, CircuitTypes); +STANDARD_TESTING_TAGS +/** + * @brief Check basic tag interactions + * + */ +TYPED_TEST(CycleGroupTest, TestBasicTagLogic) +{ + STDLIB_TYPE_ALIASES + Builder builder; + + auto lhs = TestFixture::generators[0]; + cycle_group_ct a = cycle_group_ct::from_witness(&builder, lhs); + // Set the whole tag first + a.set_origin_tag(next_challenge_tag); + // Set tags of x an y + a.x.set_origin_tag(submitted_value_origin_tag); + a.y.set_origin_tag(challenge_origin_tag); + + // The tag of the _is_point_at_infinity member should stay as next_challenge_tag, so the whole thing should be the + // union of all 3 + + EXPECT_EQ(a.get_origin_tag(), first_second_third_merged_tag); + +#ifndef NDEBUG + cycle_group_ct b = cycle_group_ct::from_witness(&builder, TestFixture::generators[1]); + b.x.set_origin_tag(instant_death_tag); + // Even requesting the tag of the whole structure can cause instant death + EXPECT_THROW(b.get_origin_tag(), std::runtime_error); +#endif +} + /** * @brief Checks that a point on the curve passes the validate_is_on_curve check * @@ -110,29 +143,62 @@ TYPED_TEST(CycleGroupTest, TestStandardForm) STDLIB_TYPE_ALIASES; auto builder = Builder(); - size_t num_repetitions = 5; - for (size_t i = 0; i < num_repetitions; ++i) { - cycle_group_ct input_a(Element::random_element()); - cycle_group_ct input_b(Element::random_element()); - input_b.set_point_at_infinity(true); - auto standard_a = input_a.get_standard_form(); - auto standard_b = input_b.get_standard_form(); - EXPECT_EQ(standard_a.is_point_at_infinity().get_value(), false); - EXPECT_EQ(standard_b.is_point_at_infinity().get_value(), true); - auto input_a_x = input_a.x.get_value(); - auto input_a_y = input_a.y.get_value(); - - auto standard_a_x = standard_a.x.get_value(); - auto standard_a_y = standard_a.y.get_value(); - - auto standard_b_x = standard_b.x.get_value(); - auto standard_b_y = standard_b.y.get_value(); - - EXPECT_EQ(input_a_x, standard_a_x); - EXPECT_EQ(input_a_y, standard_a_y); - EXPECT_EQ(standard_b_x, 0); - EXPECT_EQ(standard_b_y, 0); - } + cycle_group_ct input_a = cycle_group_ct::from_witness(&builder, Element::random_element()); + cycle_group_ct input_b = cycle_group_ct::from_witness(&builder, Element::random_element()); + cycle_group_ct input_c = cycle_group_ct(Element::random_element()); + cycle_group_ct input_d = cycle_group_ct(Element::random_element()); + + input_b.set_point_at_infinity(true); + input_d.set_point_at_infinity(true); + + // Assign different tags to all inputs + input_a.set_origin_tag(submitted_value_origin_tag); + input_b.set_origin_tag(challenge_origin_tag); + input_c.set_origin_tag(next_challenge_tag); + input_d.set_origin_tag(first_two_merged_tag); + + auto standard_a = input_a.get_standard_form(); + auto standard_b = input_b.get_standard_form(); + auto standard_c = input_c.get_standard_form(); + auto standard_d = input_d.get_standard_form(); + + EXPECT_EQ(standard_a.is_point_at_infinity().get_value(), false); + EXPECT_EQ(standard_b.is_point_at_infinity().get_value(), true); + EXPECT_EQ(standard_c.is_point_at_infinity().get_value(), false); + EXPECT_EQ(standard_d.is_point_at_infinity().get_value(), true); + + // Ensure that the tags in the standard form remain the same + EXPECT_EQ(standard_a.get_origin_tag(), submitted_value_origin_tag); + EXPECT_EQ(standard_b.get_origin_tag(), challenge_origin_tag); + EXPECT_EQ(standard_c.get_origin_tag(), next_challenge_tag); + EXPECT_EQ(standard_d.get_origin_tag(), first_two_merged_tag); + + auto input_a_x = input_a.x.get_value(); + auto input_a_y = input_a.y.get_value(); + auto input_c_x = input_c.x.get_value(); + auto input_c_y = input_c.y.get_value(); + + auto standard_a_x = standard_a.x.get_value(); + auto standard_a_y = standard_a.y.get_value(); + + auto standard_b_x = standard_b.x.get_value(); + auto standard_b_y = standard_b.y.get_value(); + + auto standard_c_x = standard_c.x.get_value(); + auto standard_c_y = standard_c.y.get_value(); + + auto standard_d_x = standard_d.x.get_value(); + auto standard_d_y = standard_d.y.get_value(); + + EXPECT_EQ(input_a_x, standard_a_x); + EXPECT_EQ(input_a_y, standard_a_y); + EXPECT_EQ(standard_b_x, 0); + EXPECT_EQ(standard_b_y, 0); + EXPECT_EQ(input_c_x, standard_c_x); + EXPECT_EQ(input_c_y, standard_c_y); + EXPECT_EQ(standard_d_x, 0); + EXPECT_EQ(standard_d_y, 0); + EXPECT_TRUE(CircuitChecker::check(builder)); } TYPED_TEST(CycleGroupTest, TestDbl) @@ -142,18 +208,29 @@ TYPED_TEST(CycleGroupTest, TestDbl) auto lhs = TestFixture::generators[0]; cycle_group_ct a = cycle_group_ct::from_witness(&builder, lhs); + cycle_group_ct b = cycle_group_ct(lhs); + // Assign two different tags + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); cycle_group_ct c; + cycle_group_ct d; std::cout << "pre = " << builder.get_estimated_num_finalized_gates() << std::endl; for (size_t i = 0; i < 3; ++i) { c = a.dbl(); } std::cout << "post = " << builder.get_estimated_num_finalized_gates() << std::endl; + d = b.dbl(); AffineElement expected(Element(lhs).dbl()); AffineElement result = c.get_value(); EXPECT_EQ(result, expected); + EXPECT_EQ(d.get_value(), expected); bool proof_result = CircuitChecker::check(builder); EXPECT_EQ(proof_result, true); + + // Ensure the tags stay the same after doubling + EXPECT_EQ(c.get_origin_tag(), submitted_value_origin_tag); + EXPECT_EQ(d.get_origin_tag(), challenge_origin_tag); } TYPED_TEST(CycleGroupTest, TestUnconditionalAdd) @@ -165,10 +242,15 @@ TYPED_TEST(CycleGroupTest, TestUnconditionalAdd) [&](const AffineElement& lhs, const AffineElement& rhs, const bool lhs_constant, const bool rhs_constant) { cycle_group_ct a = lhs_constant ? cycle_group_ct(lhs) : cycle_group_ct::from_witness(&builder, lhs); cycle_group_ct b = rhs_constant ? cycle_group_ct(rhs) : cycle_group_ct::from_witness(&builder, rhs); + // Assign two different tags + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); cycle_group_ct c = a.unconditional_add(b); AffineElement expected(Element(lhs) + Element(rhs)); AffineElement result = c.get_value(); EXPECT_EQ(result, expected); + // Ensure the tags in the result are merged + EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag); }; add(TestFixture::generators[0], TestFixture::generators[1], false, false); @@ -234,56 +316,81 @@ TYPED_TEST(CycleGroupTest, TestAdd) { cycle_group_ct a = cycle_group_ct::from_witness(&builder, lhs); cycle_group_ct b = cycle_group_ct::from_witness(&builder, rhs); + // Here and in the following cases we assign two different tags + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); cycle_group_ct c = a + b; AffineElement expected(Element(lhs) + Element(rhs)); AffineElement result = c.get_value(); EXPECT_EQ(result, expected); + // We expect the tags to be merged in the result + EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag); } // case 2. lhs is point at infinity { cycle_group_ct a = point_at_infinity; cycle_group_ct b = cycle_group_ct::from_witness(&builder, rhs); + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); + cycle_group_ct c = a + b; AffineElement result = c.get_value(); EXPECT_EQ(result, rhs); + EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag); } // case 3. rhs is point at infinity { cycle_group_ct a = cycle_group_ct::from_witness(&builder, lhs); cycle_group_ct b = point_at_infinity; + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); + cycle_group_ct c = a + b; AffineElement result = c.get_value(); EXPECT_EQ(result, lhs); + EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag); } // case 4. both points are at infinity { cycle_group_ct a = point_at_infinity; cycle_group_ct b = point_at_infinity; + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); + cycle_group_ct c = a + b; EXPECT_TRUE(c.is_point_at_infinity().get_value()); EXPECT_TRUE(c.get_value().is_point_at_infinity()); + EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag); } // case 5. lhs = -rhs { cycle_group_ct a = cycle_group_ct::from_witness(&builder, lhs); cycle_group_ct b = cycle_group_ct::from_witness(&builder, -lhs); + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); + cycle_group_ct c = a + b; EXPECT_TRUE(c.is_point_at_infinity().get_value()); EXPECT_TRUE(c.get_value().is_point_at_infinity()); + EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag); } // case 6. lhs = rhs { cycle_group_ct a = cycle_group_ct::from_witness(&builder, lhs); cycle_group_ct b = cycle_group_ct::from_witness(&builder, lhs); + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); + cycle_group_ct c = a + b; AffineElement expected((Element(lhs)).dbl()); AffineElement result = c.get_value(); EXPECT_EQ(result, expected); + EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag); } bool proof_result = CircuitChecker::check(builder); @@ -295,20 +402,26 @@ TYPED_TEST(CycleGroupTest, TestUnconditionalSubtract) STDLIB_TYPE_ALIASES; auto builder = Builder(); - auto add = + auto subtract = [&](const AffineElement& lhs, const AffineElement& rhs, const bool lhs_constant, const bool rhs_constant) { cycle_group_ct a = lhs_constant ? cycle_group_ct(lhs) : cycle_group_ct::from_witness(&builder, lhs); cycle_group_ct b = rhs_constant ? cycle_group_ct(rhs) : cycle_group_ct::from_witness(&builder, rhs); + // Assign two different tags + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); + cycle_group_ct c = a.unconditional_subtract(b); AffineElement expected(Element(lhs) - Element(rhs)); AffineElement result = c.get_value(); EXPECT_EQ(result, expected); + // Expect tags to be merged in the result + EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag); }; - add(TestFixture::generators[0], TestFixture::generators[1], false, false); - add(TestFixture::generators[0], TestFixture::generators[1], false, true); - add(TestFixture::generators[0], TestFixture::generators[1], true, false); - add(TestFixture::generators[0], TestFixture::generators[1], true, true); + subtract(TestFixture::generators[0], TestFixture::generators[1], false, false); + subtract(TestFixture::generators[0], TestFixture::generators[1], false, true); + subtract(TestFixture::generators[0], TestFixture::generators[1], true, false); + subtract(TestFixture::generators[0], TestFixture::generators[1], true, true); bool proof_result = CircuitChecker::check(builder); EXPECT_EQ(proof_result, true); @@ -370,56 +483,82 @@ TYPED_TEST(CycleGroupTest, TestSubtract) { cycle_group_ct a = cycle_group_ct::from_witness(&builder, lhs); cycle_group_ct b = cycle_group_ct::from_witness(&builder, rhs); + // Here and in the following cases we set 2 different tags to a and b + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); + cycle_group_ct c = a - b; AffineElement expected(Element(lhs) - Element(rhs)); AffineElement result = c.get_value(); EXPECT_EQ(result, expected); + // We expect the tag of the result to be the union of a and b tags + EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag); } // case 2. lhs is point at infinity { cycle_group_ct a = point_at_infinity; cycle_group_ct b = cycle_group_ct::from_witness(&builder, rhs); + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); + cycle_group_ct c = a - b; AffineElement result = c.get_value(); EXPECT_EQ(result, -rhs); + EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag); } // case 3. rhs is point at infinity { cycle_group_ct a = cycle_group_ct::from_witness(&builder, lhs); cycle_group_ct b = point_at_infinity; + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); + cycle_group_ct c = a - b; AffineElement result = c.get_value(); EXPECT_EQ(result, lhs); + EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag); } // case 4. both points are at infinity { cycle_group_ct a = point_at_infinity; cycle_group_ct b = point_at_infinity; + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); + cycle_group_ct c = a - b; EXPECT_TRUE(c.is_point_at_infinity().get_value()); EXPECT_TRUE(c.get_value().is_point_at_infinity()); + EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag); } // case 5. lhs = -rhs { cycle_group_ct a = cycle_group_ct::from_witness(&builder, lhs); cycle_group_ct b = cycle_group_ct::from_witness(&builder, -lhs); + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); + cycle_group_ct c = a - b; AffineElement expected((Element(lhs)).dbl()); AffineElement result = c.get_value(); EXPECT_EQ(result, expected); + EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag); } // case 6. lhs = rhs { cycle_group_ct a = cycle_group_ct::from_witness(&builder, lhs); cycle_group_ct b = cycle_group_ct::from_witness(&builder, lhs); + a.set_origin_tag(submitted_value_origin_tag); + b.set_origin_tag(challenge_origin_tag); + cycle_group_ct c = a - b; EXPECT_TRUE(c.is_point_at_infinity().get_value()); EXPECT_TRUE(c.get_value().is_point_at_infinity()); + EXPECT_EQ(c.get_origin_tag(), first_two_merged_tag); } bool proof_result = CircuitChecker::check(builder); @@ -432,7 +571,24 @@ TYPED_TEST(CycleGroupTest, TestBatchMul) auto builder = Builder(); const size_t num_muls = 1; - + /** + * @brief Assign different tags to all points and scalars and return the union of that tag + * + *@details We assign the tags with the same round index to a (point,scalar) pair, but the point is treated as + *submitted value, while scalar as a challenge. Merging these tags should not run into any edgecases + */ + auto assign_and_merge_tags = [](auto& points, auto& scalars) { + OriginTag merged_tag; + for (size_t i = 0; i < points.size(); i++) { + const auto point_tag = OriginTag(/*parent_index=*/0, /*round_index=*/i, /*is_submitted=*/true); + const auto scalar_tag = OriginTag(/*parent_index=*/0, /*round_index=*/i, /*is_submitted=*/false); + + merged_tag = OriginTag(merged_tag, OriginTag(point_tag, scalar_tag)); + points[i].set_origin_tag(point_tag); + scalars[i].set_origin_tag(scalar_tag); + } + return merged_tag; + }; // case 1, general MSM with inputs that are combinations of constant and witnesses { std::vector points; @@ -463,8 +619,14 @@ TYPED_TEST(CycleGroupTest, TestBatchMul) points.emplace_back(cycle_group_ct(element)); scalars.emplace_back(typename cycle_group_ct::cycle_scalar(scalar)); } + + // Here and in the following cases assign different tags to points and scalars and get the union of them back + const auto expected_tag = assign_and_merge_tags(points, scalars); + auto result = cycle_group_ct::batch_mul(points, scalars); EXPECT_EQ(result.get_value(), AffineElement(expected)); + // The tag should the union of all tags + EXPECT_EQ(result.get_origin_tag(), expected_tag); } // case 2, MSM that produces point at infinity @@ -480,8 +642,12 @@ TYPED_TEST(CycleGroupTest, TestBatchMul) points.emplace_back(cycle_group_ct::from_witness(&builder, element)); scalars.emplace_back(cycle_group_ct::cycle_scalar::from_witness(&builder, -scalar)); + const auto expected_tag = assign_and_merge_tags(points, scalars); + auto result = cycle_group_ct::batch_mul(points, scalars); EXPECT_TRUE(result.is_point_at_infinity().get_value()); + + EXPECT_EQ(result.get_origin_tag(), expected_tag); } // case 3. Multiply by zero @@ -493,8 +659,11 @@ TYPED_TEST(CycleGroupTest, TestBatchMul) typename Group::subgroup_field scalar = 0; points.emplace_back(cycle_group_ct::from_witness(&builder, element)); scalars.emplace_back(cycle_group_ct::cycle_scalar::from_witness(&builder, scalar)); + + const auto expected_tag = assign_and_merge_tags(points, scalars); auto result = cycle_group_ct::batch_mul(points, scalars); EXPECT_TRUE(result.is_point_at_infinity().get_value()); + EXPECT_EQ(result.get_origin_tag(), expected_tag); } // case 4. Inputs are points at infinity @@ -519,8 +688,11 @@ TYPED_TEST(CycleGroupTest, TestBatchMul) points.emplace_back(point); scalars.emplace_back(cycle_group_ct::cycle_scalar::from_witness(&builder, scalar)); } + + const auto expected_tag = assign_and_merge_tags(points, scalars); auto result = cycle_group_ct::batch_mul(points, scalars); EXPECT_TRUE(result.is_point_at_infinity().get_value()); + EXPECT_EQ(result.get_origin_tag(), expected_tag); } // case 5, fixed-base MSM with inputs that are combinations of constant and witnesses (group elements are in @@ -547,9 +719,11 @@ TYPED_TEST(CycleGroupTest, TestBatchMul) scalars.emplace_back(typename cycle_group_ct::cycle_scalar(scalar)); scalars_native.emplace_back(uint256_t(scalar)); } + const auto expected_tag = assign_and_merge_tags(points, scalars); auto result = cycle_group_ct::batch_mul(points, scalars); EXPECT_EQ(result.get_value(), AffineElement(expected)); EXPECT_EQ(result.get_value(), crypto::pedersen_commitment::commit_native(scalars_native)); + EXPECT_EQ(result.get_origin_tag(), expected_tag); } // case 6, fixed-base MSM with inputs that are combinations of constant and witnesses (some group elements are @@ -584,8 +758,10 @@ TYPED_TEST(CycleGroupTest, TestBatchMul) scalars.emplace_back(cycle_group_ct::cycle_scalar::from_witness(&builder, scalar)); scalars_native.emplace_back(scalar); } + const auto expected_tag = assign_and_merge_tags(points, scalars); auto result = cycle_group_ct::batch_mul(points, scalars); EXPECT_EQ(result.get_value(), AffineElement(expected)); + EXPECT_EQ(result.get_origin_tag(), expected_tag); } // case 7, Fixed-base MSM where input scalars are 0 @@ -605,8 +781,10 @@ TYPED_TEST(CycleGroupTest, TestBatchMul) points.emplace_back((element)); scalars.emplace_back(typename cycle_group_ct::cycle_scalar(scalar)); } + const auto expected_tag = assign_and_merge_tags(points, scalars); auto result = cycle_group_ct::batch_mul(points, scalars); EXPECT_EQ(result.is_point_at_infinity().get_value(), true); + EXPECT_EQ(result.get_origin_tag(), expected_tag); } bool check_result = CircuitChecker::check(builder); @@ -624,28 +802,34 @@ TYPED_TEST(CycleGroupTest, TestMul) { cycle_group_ct point; typename cycle_group_ct::cycle_scalar scalar; + cycle_group_ct result; for (size_t i = 0; i < num_muls; ++i) { auto element = TestFixture::generators[i]; typename Group::subgroup_field native_scalar = Group::subgroup_field::random_element(&engine); + auto expected_result = element * native_scalar; // 1: add entry where point, scalar are witnesses point = (cycle_group_ct::from_witness(&builder, element)); scalar = (cycle_group_ct::cycle_scalar::from_witness(&builder, native_scalar)); - EXPECT_EQ((point * scalar).get_value(), (element * native_scalar)); + point.set_origin_tag(submitted_value_origin_tag); + scalar.set_origin_tag(challenge_origin_tag); + result = point * scalar; + + EXPECT_EQ((result).get_value(), (expected_result)); // 2: add entry where point is constant, scalar is witness point = (cycle_group_ct(element)); scalar = (cycle_group_ct::cycle_scalar::from_witness(&builder, native_scalar)); - EXPECT_EQ((point * scalar).get_value(), (element * native_scalar)); + EXPECT_EQ((result).get_value(), (expected_result)); // 3: add entry where point is witness, scalar is constant point = (cycle_group_ct::from_witness(&builder, element)); - EXPECT_EQ((point * scalar).get_value(), (element * native_scalar)); + EXPECT_EQ((result).get_value(), (expected_result)); // 4: add entry where point is constant, scalar is constant point = (cycle_group_ct(element)); - EXPECT_EQ((point * scalar).get_value(), (element * native_scalar)); + EXPECT_EQ((result).get_value(), (expected_result)); } } @@ -684,14 +868,13 @@ TYPED_TEST(CycleGroupTest, TestConversionFromBigfield) } else { big_elt = FF_ct(elt); } - cycle_scalar_ct scalar_from_big(big_elt); - EXPECT_EQ(elt, scalar_from_big.get_value()); - cycle_scalar_ct scalar_from_elt(big_elt); - EXPECT_EQ(elt, scalar_from_elt.get_value()); + big_elt.set_origin_tag(submitted_value_origin_tag); + cycle_scalar_ct scalar_from_big_elt(big_elt); + EXPECT_EQ(elt, scalar_from_big_elt.get_value()); + EXPECT_EQ(scalar_from_big_elt.get_origin_tag(), big_elt.get_origin_tag()); if (construct_witnesses) { EXPECT_FALSE(big_elt.is_constant()); - EXPECT_FALSE(scalar_from_big.is_constant()); - EXPECT_FALSE(scalar_from_elt.is_constant()); + EXPECT_FALSE(scalar_from_big_elt.is_constant()); EXPECT_TRUE(CircuitChecker::check(builder)); } }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_key.hpp b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_key.hpp index 95833c465d1..e11674a2c82 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_key.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/protogalaxy_verifier/recursive_decider_verification_key.hpp @@ -109,7 +109,7 @@ template class RecursiveDeciderVerificationKey_ { native_honk_vk->contains_pairing_point_accumulator = verification_key->contains_pairing_point_accumulator; native_honk_vk->pairing_point_accumulator_public_input_indices = verification_key->pairing_point_accumulator_public_input_indices; - if constexpr (IsGoblinFlavor) { + if constexpr (IsMegaFlavor) { native_honk_vk->databus_propagation_data = verification_key->databus_propagation_data; } diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_flavor.hpp index 63b3c56eddf..ffbf91dea89 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_flavor.hpp @@ -87,6 +87,8 @@ template class TranslatorRecursiveFlavor_ { // The total number of witness entities not including shifts. static constexpr size_t NUM_WITNESS_ENTITIES = NativeFlavor::NUM_WITNESS_ENTITIES; + static constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS = NativeFlavor::REPEATED_COMMITMENTS; + using Relations = TranslatorFlavor::Relations_; static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp index 1dbae562d7d..2849fdd48b5 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.cpp @@ -120,6 +120,9 @@ std::array TranslatorRecursiveVerifier_ opening_claim = Shplemini::compute_batch_opening_claim(circuit_size, commitments.get_unshifted_without_concatenated(), @@ -129,6 +132,7 @@ std::array TranslatorRecursiveVerifier_ class GrandProductTests : public testing::Test { .lookup_grand_product_delta = 1, }; - // Method 1: Compute z_perm using 'compute_grand_product_polynomial' as the prover would in practice - constexpr size_t PERMUTATION_RELATION_INDEX = 0; - using LHS = - typename std::tuple_element::type; - ASSERT(Flavor::NUM_WIRES == 4); - using RHS = typename bb::UltraPermutationRelation; - static_assert(std::same_as); - compute_grand_product(prover_polynomials, params); + compute_grand_product>(prover_polynomials, params); // Method 2: Compute z_perm locally using the simplest non-optimized syntax possible. The comment below, // which describes the computation in 4 steps, is adapted from a similar comment in diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp index dd51a5424f9..a9f51823547 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp @@ -236,6 +236,44 @@ template class MegaCircuitBuilder_ : public UltraCircuitBuilder_(BusId::CALLDATA)]; } const BusVector& get_secondary_calldata() const { return databus[static_cast(BusId::SECONDARY_CALLDATA)]; } const BusVector& get_return_data() const { return databus[static_cast(BusId::RETURNDATA)]; } + uint64_t estimate_memory() const + { + vinfo("++Estimating builder memory++"); + uint64_t result{ 0 }; + + // gates: + for (auto [block, label] : zip_view(this->blocks.get(), this->blocks.get_labels())) { + uint64_t size{ 0 }; + for (const auto& wire : block.wires) { + size += wire.capacity() * sizeof(uint32_t); + } + for (const auto& selector : block.selectors) { + size += selector.capacity() * sizeof(FF); + } + vinfo(label, " size ", size >> 10, " KiB"); + result += size; + } + + // variables + size_t to_add{ this->variables.capacity() * sizeof(FF) }; + result += to_add; + vinfo("variables: ", to_add); + + // public inputs + to_add = this->public_inputs.capacity() * sizeof(uint32_t); + result += to_add; + vinfo("public inputs: ", to_add); + + // other variable indices + to_add = this->next_var_index.capacity() * sizeof(uint32_t); + to_add += this->prev_var_index.capacity() * sizeof(uint32_t); + to_add += this->real_variable_index.capacity() * sizeof(uint32_t); + to_add += this->real_variable_tags.capacity() * sizeof(uint32_t); + result += to_add; + vinfo("variable indices: ", to_add); + + return result; + } }; using MegaCircuitBuilder = MegaCircuitBuilder_; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp index 13f6e3cbe85..5df52d1997e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp @@ -4,6 +4,7 @@ #include "barretenberg/flavor/flavor.hpp" #include "barretenberg/flavor/flavor_macros.hpp" #include "barretenberg/flavor/relation_definitions.hpp" +#include "barretenberg/flavor/repeated_commitments_data.hpp" #include "barretenberg/honk/proof_system/types/proof.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_delta.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" @@ -50,8 +51,15 @@ class MegaFlavor { static constexpr size_t NUM_WITNESS_ENTITIES = 24; // Total number of folded polynomials, which is just all polynomials except the shifts static constexpr size_t NUM_FOLDED_ENTITIES = NUM_PRECOMPUTED_ENTITIES + NUM_WITNESS_ENTITIES; + // The number of shifted witness entities including derived witness entities + static constexpr size_t NUM_SHIFTED_WITNESSES = 5; + // The number of shifted tables + static constexpr size_t NUM_SHIFTED_TABLES = 4; - using GrandProductRelations = std::tuple>; + static constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS = + RepeatedCommitmentsData(NUM_PRECOMPUTED_ENTITIES, + NUM_PRECOMPUTED_ENTITIES + NUM_WITNESS_ENTITIES + NUM_SHIFTED_TABLES, + NUM_SHIFTED_WITNESSES); // define the tuple of Relations that comprise the Sumcheck relation // Note: made generic for use in MegaRecursive. @@ -77,7 +85,7 @@ class MegaFlavor { static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = MAX_PARTIAL_RELATION_LENGTH + 1; static constexpr size_t NUM_RELATIONS = std::tuple_size_v; // The total number of witnesses including shifts and derived entities. - static constexpr size_t NUM_ALL_WITNESS_ENTITIES = 23; + static constexpr size_t NUM_ALL_WITNESS_ENTITIES = NUM_WITNESS_ENTITIES + NUM_SHIFTED_WITNESSES; // For instances of this flavour, used in folding, we need a unique sumcheck batching challenges for each // subrelation. This @@ -274,6 +282,7 @@ class MegaFlavor { /** * @brief Class for ShiftedEntities, containing shifted witness and table polynomials. + * TODO: Remove NUM_SHIFTED_TABLES once these entities are deprecated. */ template class ShiftedTables { public: @@ -497,18 +506,37 @@ class MegaFlavor { * @brief Computes public_input_delta and the permutation grand product polynomial * * @param relation_parameters + * @param size_override override the size of the domain over which to compute the grand product */ - void compute_grand_product_polynomials(RelationParameters& relation_parameters) + void compute_grand_product_polynomial(RelationParameters& relation_parameters, size_t size_override = 0) { - auto public_input_delta = compute_public_input_delta(this->public_inputs, - relation_parameters.beta, - relation_parameters.gamma, - this->circuit_size, - this->pub_inputs_offset); - relation_parameters.public_input_delta = public_input_delta; - - // Compute permutation and lookup grand product polynomials - compute_grand_products(this->polynomials, relation_parameters); + relation_parameters.public_input_delta = compute_public_input_delta(this->public_inputs, + relation_parameters.beta, + relation_parameters.gamma, + this->circuit_size, + this->pub_inputs_offset); + + // Compute permutation grand product polynomial + compute_grand_product>( + this->polynomials, relation_parameters, size_override); + } + + uint64_t estimate_memory() + { + vinfo("++Estimating proving key memory++"); + for (auto [polynomial, label] : zip_view(polynomials.get_all(), polynomials.get_labels())) { + uint64_t size = polynomial.size(); + vinfo(label, " num: ", size, " size: ", (size * sizeof(FF)) >> 10, " KiB"); + } + + uint64_t result(0); + for (auto& polynomial : polynomials.get_unshifted()) { + result += polynomial.size() * sizeof(FF); + } + + result += public_inputs.capacity() * sizeof(FF); + + return result; } }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp index 94ef17d6c8d..9fc58872fab 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_recursive_flavor.hpp @@ -68,6 +68,9 @@ template class MegaRecursiveFlavor_ { // random polynomial e.g. For \sum(x) [A(x) * B(x) + C(x)] * PowZeta(X), relation length = 2 and random relation // length = 3 static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = MAX_PARTIAL_RELATION_LENGTH + 1; + + static constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS = MegaFlavor::REPEATED_COMMITMENTS; + static constexpr size_t NUM_RELATIONS = std::tuple_size_v; // For instances of this flavour, used in folding, we need a unique sumcheck batching challenge for each diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp index 0682a8a44ab..070046f3f15 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp @@ -87,6 +87,41 @@ class MockCircuits { } } + /** + * @brief Add some simple RAM (aux) gates for testing memory read/write functionality + * @brief Each iteration adds 18 gates (including finalization) + * + * @param builder + */ + template static void add_RAM_gates(Builder& builder) + { + std::array ram_values{ builder.add_variable(5), + builder.add_variable(10), + builder.add_variable(20) }; + + size_t ram_id = builder.create_RAM_array(3); + + for (size_t i = 0; i < 3; ++i) { + builder.init_RAM_element(ram_id, i, ram_values[i]); + } + + auto val_idx_1 = builder.read_RAM_array(ram_id, builder.add_variable(1)); + auto val_idx_2 = builder.read_RAM_array(ram_id, builder.add_variable(2)); + auto val_idx_3 = builder.read_RAM_array(ram_id, builder.add_variable(0)); + + builder.create_big_add_gate({ + val_idx_1, + val_idx_2, + val_idx_3, + builder.zero_idx, + 1, + 1, + 1, + 0, + -35, + }); + } + /** * @brief Populate a builder with a specified number of arithmetic gates; includes a PI * diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp index 259082820eb..9ba18ab891f 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp @@ -111,7 +111,6 @@ enum MultiTableId { BLAKE_XOR_ROTATE_16, BLAKE_XOR_ROTATE_8, BLAKE_XOR_ROTATE_7, - PEDERSEN_IV, HONK_DUMMY_MULTI, KECCAK_THETA_OUTPUT, KECCAK_CHI_OUTPUT, diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.cpp index 0e00ba6adc2..0f9063b6574 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.cpp @@ -8,6 +8,7 @@ #include "ultra_circuit_builder.hpp" #include "barretenberg/crypto/poseidon2/poseidon2_params.hpp" #include +#include #include #include diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp index 76b8e1ed56a..d8be56ad096 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp @@ -3,6 +3,7 @@ #include "barretenberg/ecc/curves/bn254/g1.hpp" #include "barretenberg/flavor/flavor.hpp" #include "barretenberg/flavor/flavor_macros.hpp" +#include "barretenberg/flavor/repeated_commitments_data.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_delta.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" #include "barretenberg/polynomials/barycentric.hpp" @@ -47,12 +48,22 @@ class UltraFlavor { static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 27; // The total number of witness entities not including shifts. static constexpr size_t NUM_WITNESS_ENTITIES = 8; - // The total number of witnesses including shifts and derived entities. - static constexpr size_t NUM_ALL_WITNESS_ENTITIES = 13; // Total number of folded polynomials, which is just all polynomials except the shifts static constexpr size_t NUM_FOLDED_ENTITIES = NUM_PRECOMPUTED_ENTITIES + NUM_WITNESS_ENTITIES; + // The number of shifted witness entities including derived witness entities + static constexpr size_t NUM_SHIFTED_WITNESSES = 5; + // The number of shifted tables + static constexpr size_t NUM_SHIFTED_TABLES = 4; + + // A container to be fed to ShpleminiVerifier to avoid redundant scalar muls + static constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS = + RepeatedCommitmentsData(NUM_PRECOMPUTED_ENTITIES, + NUM_PRECOMPUTED_ENTITIES + NUM_WITNESS_ENTITIES + NUM_SHIFTED_TABLES, + NUM_SHIFTED_WITNESSES); + + // The total number of witnesses including shifts and derived entities. + static constexpr size_t NUM_ALL_WITNESS_ENTITIES = NUM_WITNESS_ENTITIES + NUM_SHIFTED_WITNESSES; - using GrandProductRelations = std::tuple>; // define the tuple of Relations that comprise the Sumcheck relation // Note: made generic for use in MegaRecursive. template @@ -194,6 +205,7 @@ class UltraFlavor { /** * @brief Class for ShiftedEntities, containing shifted witness and table polynomials. + * TODO: Remove NUM_SHIFTED_TABLES once these entities are deprecated. */ template class ShiftedTables { public: @@ -401,18 +413,19 @@ class UltraFlavor { * @brief Computes public_input_delta and the permutation grand product polynomial * * @param relation_parameters + * @param size_override override the size of the domain over which to compute the grand product */ - void compute_grand_product_polynomials(RelationParameters& relation_parameters) + void compute_grand_product_polynomial(RelationParameters& relation_parameters, size_t size_override = 0) { - auto public_input_delta = compute_public_input_delta(this->public_inputs, - relation_parameters.beta, - relation_parameters.gamma, - this->circuit_size, - this->pub_inputs_offset); - relation_parameters.public_input_delta = public_input_delta; - - // Compute permutation and lookup grand product polynomials - compute_grand_products(this->polynomials, relation_parameters); + relation_parameters.public_input_delta = compute_public_input_delta(this->public_inputs, + relation_parameters.beta, + relation_parameters.gamma, + this->circuit_size, + this->pub_inputs_offset); + + // Compute permutation grand product polynomial + compute_grand_product>( + this->polynomials, relation_parameters, size_override); } }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp index 972e1bf909c..9b28f0de7d9 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp @@ -69,6 +69,8 @@ template class UltraRecursiveFlavor_ { // The total number of witness entities not including shifts. static constexpr size_t NUM_WITNESS_ENTITIES = UltraFlavor::NUM_WITNESS_ENTITIES; + static constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS = UltraFlavor::REPEATED_COMMITMENTS; + // define the tuple of Relations that comprise the Sumcheck relation using Relations = UltraFlavor::Relations_; diff --git a/barretenberg/cpp/src/barretenberg/transcript/origin_tag.hpp b/barretenberg/cpp/src/barretenberg/transcript/origin_tag.hpp index da12a1b35c7..4b08be6a9d6 100644 --- a/barretenberg/cpp/src/barretenberg/transcript/origin_tag.hpp +++ b/barretenberg/cpp/src/barretenberg/transcript/origin_tag.hpp @@ -54,13 +54,13 @@ struct OriginTag { // Parent tag is supposed to represent the index of a unique trancript object that generated the value. It uses // a concrete index, not bits for now, since we never expect two different indices to be used in the same // computation apart from equality assertion - size_t parent_tag; + size_t parent_tag = 0; // Child tag specifies which submitted values and challenges have been used to generate this element // The lower 128 bits represent using a submitted value from a corresponding round (the shift represents the // round) The higher 128 bits represent using a challenge value from an corresponding round (the shift // represents the round) - numeric::uint256_t child_tag; + numeric::uint256_t child_tag = 0; // Instant death is used for poisoning values we should never use in arithmetic bool instant_death = false; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp index 2c8e0d2c9c4..6820125e050 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.hpp @@ -96,53 +96,58 @@ class TranslatorCircuitBuilder : public CircuitBuilderBase { X_LOW_Y_HI, X_HIGH_Z_1, Y_LOW_Z_2, - P_X_LOW_LIMBS, // P.xₗₒ split into 2 68 bit limbs + P_X_LOW_LIMBS, // P.xₗₒ split into 2 68 bit limbs + P_X_HIGH_LIMBS, // P.xₕᵢ split into a 68 and a 50 bit limb + P_Y_LOW_LIMBS, // P.yₗₒ split into 2 68 bit limbs + P_Y_HIGH_LIMBS, // P.yₕᵢ split into a 68 and a 50 bit limb + Z_LOW_LIMBS, // Low limbs of z_1 and z_2 (68 bits each) + Z_HIGH_LIMBS, // High Limbs of z_1 and z_2 (60 bits each) + ACCUMULATORS_BINARY_LIMBS_0, // Contain 68-bit limbs of current and previous accumulator (previous at higher + // indices because of the nuances of KZG commitment). + ACCUMULATORS_BINARY_LIMBS_1, + ACCUMULATORS_BINARY_LIMBS_2, + ACCUMULATORS_BINARY_LIMBS_3, // Highest limb is 50 bits (254 mod 68) P_X_LOW_LIMBS_RANGE_CONSTRAINT_0, // Low + // limbs split further into smaller chunks for range constraints + QUOTIENT_LOW_BINARY_LIMBS, // Quotient limbs + QUOTIENT_HIGH_BINARY_LIMBS, + RELATION_WIDE_LIMBS, // Limbs for checking the correctness of mod 2²⁷² relations. P_X_LOW_LIMBS_RANGE_CONSTRAINT_0, // Low limbs split further into smaller chunks for range constraints P_X_LOW_LIMBS_RANGE_CONSTRAINT_1, P_X_LOW_LIMBS_RANGE_CONSTRAINT_2, P_X_LOW_LIMBS_RANGE_CONSTRAINT_3, P_X_LOW_LIMBS_RANGE_CONSTRAINT_4, P_X_LOW_LIMBS_RANGE_CONSTRAINT_TAIL, - P_X_HIGH_LIMBS, // P.xₕᵢ split into a 68 and a 50 bit limb P_X_HIGH_LIMBS_RANGE_CONSTRAINT_0, // High limbs split into chunks for range constraints P_X_HIGH_LIMBS_RANGE_CONSTRAINT_1, P_X_HIGH_LIMBS_RANGE_CONSTRAINT_2, P_X_HIGH_LIMBS_RANGE_CONSTRAINT_3, P_X_HIGH_LIMBS_RANGE_CONSTRAINT_4, P_X_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL, - P_Y_LOW_LIMBS, // P.yₗₒ split into 2 68 bit limbs P_Y_LOW_LIMBS_RANGE_CONSTRAINT_0, // Low limbs split into chunks for range constraints P_Y_LOW_LIMBS_RANGE_CONSTRAINT_1, P_Y_LOW_LIMBS_RANGE_CONSTRAINT_2, P_Y_LOW_LIMBS_RANGE_CONSTRAINT_3, P_Y_LOW_LIMBS_RANGE_CONSTRAINT_4, P_Y_LOW_LIMBS_RANGE_CONSTRAINT_TAIL, - P_Y_HIGH_LIMBS, // P.yₕᵢ split into a 68 and a 50 bit limb P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_0, // High limbs split into chunks for range constraints P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_1, P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_2, P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_3, P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_4, P_Y_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL, - Z_LOW_LIMBS, // Low limbs of z_1 and z_2 (68 bits each) Z_LOW_LIMBS_RANGE_CONSTRAINT_0, // Range constraints for low limbs of z_1 and z_2 Z_LOW_LIMBS_RANGE_CONSTRAINT_1, Z_LOW_LIMBS_RANGE_CONSTRAINT_2, Z_LOW_LIMBS_RANGE_CONSTRAINT_3, Z_LOW_LIMBS_RANGE_CONSTRAINT_4, Z_LOW_LIMBS_RANGE_CONSTRAINT_TAIL, - Z_HIGH_LIMBS, // High Limbs of z_1 and z_2 (60 bits each) Z_HIGH_LIMBS_RANGE_CONSTRAINT_0, // Range constraints for high limbs of z_1 and z_2 Z_HIGH_LIMBS_RANGE_CONSTRAINT_1, Z_HIGH_LIMBS_RANGE_CONSTRAINT_2, Z_HIGH_LIMBS_RANGE_CONSTRAINT_3, Z_HIGH_LIMBS_RANGE_CONSTRAINT_4, Z_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL, - ACCUMULATORS_BINARY_LIMBS_0, // Contain 68-bit limbs of current and previous accumulator (previous at higher - // indices because of the nuances of KZG commitment). - ACCUMULATORS_BINARY_LIMBS_1, - ACCUMULATORS_BINARY_LIMBS_2, - ACCUMULATORS_BINARY_LIMBS_3, // Highest limb is 50 bits (254 mod 68) + ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_0, // Range constraints for the current accumulator limbs (no need to // redo previous accumulator) ACCUMULATOR_LOW_LIMBS_RANGE_CONSTRAINT_1, @@ -156,8 +161,7 @@ class TranslatorCircuitBuilder : public CircuitBuilderBase { ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_3, ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_4, ACCUMULATOR_HIGH_LIMBS_RANGE_CONSTRAINT_TAIL, - QUOTIENT_LOW_BINARY_LIMBS, // Quotient limbs - QUOTIENT_HIGH_BINARY_LIMBS, + QUOTIENT_LOW_LIMBS_RANGE_CONSTRAIN_0, // Range constraints for quotient QUOTIENT_LOW_LIMBS_RANGE_CONSTRAIN_1, QUOTIENT_LOW_LIMBS_RANGE_CONSTRAIN_2, @@ -170,7 +174,6 @@ class TranslatorCircuitBuilder : public CircuitBuilderBase { QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAIN_3, QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAIN_4, QUOTIENT_HIGH_LIMBS_RANGE_CONSTRAIN_TAIL, - RELATION_WIDE_LIMBS, // Limbs for checking the correctness of mod 2²⁷² relations. RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_0, RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_1, RELATION_WIDE_LIMBS_RANGE_CONSTRAINT_2, diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp index dced2b66d4f..7167437d4e3 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp @@ -6,6 +6,7 @@ #include "barretenberg/flavor/flavor.hpp" #include "barretenberg/flavor/flavor_macros.hpp" #include "barretenberg/flavor/relation_definitions.hpp" +#include "barretenberg/flavor/repeated_commitments_data.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/polynomials/univariate.hpp" @@ -81,7 +82,30 @@ class TranslatorFlavor { static constexpr size_t NUM_WITNESS_ENTITIES = 91; // The total number of witnesses including shifts and derived entities. static constexpr size_t NUM_ALL_WITNESS_ENTITIES = 177; - + static constexpr size_t NUM_WIRES_NON_SHIFTED = 1; + static constexpr size_t NUM_SHIFTED_WITNESSES = 86; + static constexpr size_t NUM_CONCATENATED = NUM_CONCATENATED_WIRES * CONCATENATION_GROUP_SIZE; + // Number of elements in WireToBeShiftedWithoutConcatenated + static constexpr size_t NUM_WIRES_TO_BE_SHIFTED_WITHOUT_CONCATENATED = 16; + // The index of the first unshifted witness that is going to be shifted when AllEntities are partitioned into + // get_unshifted_without_concatenated(), get_to_be_shifted(), and get_groups_to_be_concatenated() + static constexpr size_t TO_BE_SHIFTED_WITNESSES_START = NUM_PRECOMPUTED_ENTITIES + NUM_WIRES_NON_SHIFTED; + // The index of the shift of the first to be shifted witness + static constexpr size_t SHIFTED_WITNESSES_START = NUM_SHIFTED_WITNESSES + TO_BE_SHIFTED_WITNESSES_START; + // The index of the first unshifted witness that is contained in the groups to be concatenated, when AllEntities are + // partitioned into get_unshifted_without_concatenated(), get_to_be_shifted(), and get_groups_to_be_concatenated() + static constexpr size_t TO_BE_CONCATENATED_START = + NUM_PRECOMPUTED_ENTITIES + NUM_WIRES_NON_SHIFTED + NUM_WIRES_TO_BE_SHIFTED_WITHOUT_CONCATENATED; + // The index of the first concatenation groups element inside AllEntities + static constexpr size_t CONCATENATED_START = NUM_SHIFTED_WITNESSES + SHIFTED_WITNESSES_START; + // A container to be fed to ShpleminiVerifier to avoid redundant scalar muls + static constexpr RepeatedCommitmentsData REPEATED_COMMITMENTS = + RepeatedCommitmentsData(NUM_PRECOMPUTED_ENTITIES + NUM_WIRES_NON_SHIFTED, + NUM_PRECOMPUTED_ENTITIES + NUM_WIRES_NON_SHIFTED + NUM_SHIFTED_WITNESSES, + NUM_SHIFTED_WITNESSES, + TO_BE_CONCATENATED_START, + CONCATENATED_START, + NUM_CONCATENATED); using GrandProductRelations = std::tuple>; // define the tuple of Relations that comprise the Sumcheck relation template @@ -141,91 +165,103 @@ class TranslatorFlavor { concatenated_range_constraints_3) // column 3 }; // TODO(https://github.com/AztecProtocol/barretenberg/issues/790) dedupe with shifted? - template class WireToBeShiftedEntities { + template class WireToBeShiftedWithoutConcatenated { + public: + DEFINE_FLAVOR_MEMBERS(DataType, + x_lo_y_hi, // column 0 + x_hi_z_1, // column 1 + y_lo_z_2, // column 2 + p_x_low_limbs, // column 3 + p_x_high_limbs, // column 4 + p_y_low_limbs, // column 5 + p_y_high_limbs, // column 6 + z_low_limbs, // column 7 + z_high_limbs, // column 8 + accumulators_binary_limbs_0, // column 9 + accumulators_binary_limbs_1, // column 10 + accumulators_binary_limbs_2, // column 11 + accumulators_binary_limbs_3, // column 12 + quotient_low_binary_limbs, // column 13 + quotient_high_binary_limbs, // column 14 + relation_wide_limbs); // column 15 + }; + + template class WireToBeShiftedAndConcatenated { public: DEFINE_FLAVOR_MEMBERS(DataType, - x_lo_y_hi, // column 0 - x_hi_z_1, // column 1 - y_lo_z_2, // column 2 - p_x_low_limbs, // column 3 - p_x_low_limbs_range_constraint_0, // column 4 - p_x_low_limbs_range_constraint_1, // column 5 - p_x_low_limbs_range_constraint_2, // column 6 - p_x_low_limbs_range_constraint_3, // column 7 - p_x_low_limbs_range_constraint_4, // column 8 - p_x_low_limbs_range_constraint_tail, // column 9 - p_x_high_limbs, // column 10 - p_x_high_limbs_range_constraint_0, // column 11 - p_x_high_limbs_range_constraint_1, // column 12 - p_x_high_limbs_range_constraint_2, // column 13 - p_x_high_limbs_range_constraint_3, // column 14 - p_x_high_limbs_range_constraint_4, // column 15 - p_x_high_limbs_range_constraint_tail, // column 16 - p_y_low_limbs, // column 17 - p_y_low_limbs_range_constraint_0, // column 18 - p_y_low_limbs_range_constraint_1, // column 19 - p_y_low_limbs_range_constraint_2, // column 20 - p_y_low_limbs_range_constraint_3, // column 21 - p_y_low_limbs_range_constraint_4, // column 22 - p_y_low_limbs_range_constraint_tail, // column 23 - p_y_high_limbs, // column 24 - p_y_high_limbs_range_constraint_0, // column 25 - p_y_high_limbs_range_constraint_1, // column 26 - p_y_high_limbs_range_constraint_2, // column 27 - p_y_high_limbs_range_constraint_3, // column 28 - p_y_high_limbs_range_constraint_4, // column 29 - p_y_high_limbs_range_constraint_tail, // column 30 - z_low_limbs, // column 31 - z_low_limbs_range_constraint_0, // column 32 - z_low_limbs_range_constraint_1, // column 33 - z_low_limbs_range_constraint_2, // column 34 - z_low_limbs_range_constraint_3, // column 35 - z_low_limbs_range_constraint_4, // column 36 - z_low_limbs_range_constraint_tail, // column 37 - z_high_limbs, // column 38 - z_high_limbs_range_constraint_0, // column 39 - z_high_limbs_range_constraint_1, // column 40 - z_high_limbs_range_constraint_2, // column 41 - z_high_limbs_range_constraint_3, // column 42 - z_high_limbs_range_constraint_4, // column 43 - z_high_limbs_range_constraint_tail, // column 44 - accumulators_binary_limbs_0, // column 45 - accumulators_binary_limbs_1, // column 46 - accumulators_binary_limbs_2, // column 47 - accumulators_binary_limbs_3, // column 48 - accumulator_low_limbs_range_constraint_0, // column 49 - accumulator_low_limbs_range_constraint_1, // column 50 - accumulator_low_limbs_range_constraint_2, // column 51 - accumulator_low_limbs_range_constraint_3, // column 52 - accumulator_low_limbs_range_constraint_4, // column 53 - accumulator_low_limbs_range_constraint_tail, // column 54 - accumulator_high_limbs_range_constraint_0, // column 55 - accumulator_high_limbs_range_constraint_1, // column 56 - accumulator_high_limbs_range_constraint_2, // column 57 - accumulator_high_limbs_range_constraint_3, // column 58 - accumulator_high_limbs_range_constraint_4, // column 59 - accumulator_high_limbs_range_constraint_tail, // column 60 - quotient_low_binary_limbs, // column 61 - quotient_high_binary_limbs, // column 62 - quotient_low_limbs_range_constraint_0, // column 63 - quotient_low_limbs_range_constraint_1, // column 64 - quotient_low_limbs_range_constraint_2, // column 65 - quotient_low_limbs_range_constraint_3, // column 66 - quotient_low_limbs_range_constraint_4, // column 67 - quotient_low_limbs_range_constraint_tail, // column 68 - quotient_high_limbs_range_constraint_0, // column 69 - quotient_high_limbs_range_constraint_1, // column 70 - quotient_high_limbs_range_constraint_2, // column 71 - quotient_high_limbs_range_constraint_3, // column 72 - quotient_high_limbs_range_constraint_4, // column 73 - quotient_high_limbs_range_constraint_tail, // column 74 - relation_wide_limbs, // column 75 + p_x_low_limbs_range_constraint_0, // column 16 + p_x_low_limbs_range_constraint_1, // column 17 + p_x_low_limbs_range_constraint_2, // column 18 + p_x_low_limbs_range_constraint_3, // column 19 + p_x_low_limbs_range_constraint_4, // column 20 + p_x_low_limbs_range_constraint_tail, // column 21 + p_x_high_limbs_range_constraint_0, // column 22 + p_x_high_limbs_range_constraint_1, // column 23 + p_x_high_limbs_range_constraint_2, // column 24 + p_x_high_limbs_range_constraint_3, // column 25 + p_x_high_limbs_range_constraint_4, // column 26 + p_x_high_limbs_range_constraint_tail, // column 27 + p_y_low_limbs_range_constraint_0, // column 28 + p_y_low_limbs_range_constraint_1, // column 29 + p_y_low_limbs_range_constraint_2, // column 30 + p_y_low_limbs_range_constraint_3, // column 31 + p_y_low_limbs_range_constraint_4, // column 32 + p_y_low_limbs_range_constraint_tail, // column 33 + p_y_high_limbs_range_constraint_0, // column 34 + p_y_high_limbs_range_constraint_1, // column 35 + p_y_high_limbs_range_constraint_2, // column 36 + p_y_high_limbs_range_constraint_3, // column 37 + p_y_high_limbs_range_constraint_4, // column 38 + p_y_high_limbs_range_constraint_tail, // column 39 + z_low_limbs_range_constraint_0, // column 40 + z_low_limbs_range_constraint_1, // column 41 + z_low_limbs_range_constraint_2, // column 42 + z_low_limbs_range_constraint_3, // column 43 + z_low_limbs_range_constraint_4, // column 44 + z_low_limbs_range_constraint_tail, // column 45 + z_high_limbs_range_constraint_0, // column 46 + z_high_limbs_range_constraint_1, // column 47 + z_high_limbs_range_constraint_2, // column 48 + z_high_limbs_range_constraint_3, // column 49 + z_high_limbs_range_constraint_4, // column 50 + z_high_limbs_range_constraint_tail, // column 51 + accumulator_low_limbs_range_constraint_0, // column 52 + accumulator_low_limbs_range_constraint_1, // column 53 + accumulator_low_limbs_range_constraint_2, // column 54 + accumulator_low_limbs_range_constraint_3, // column 55 + accumulator_low_limbs_range_constraint_4, // column 56 + accumulator_low_limbs_range_constraint_tail, // column 57 + accumulator_high_limbs_range_constraint_0, // column 58 + accumulator_high_limbs_range_constraint_1, // column 59 + accumulator_high_limbs_range_constraint_2, // column 60 + accumulator_high_limbs_range_constraint_3, // column 61 + accumulator_high_limbs_range_constraint_4, // column 62 + accumulator_high_limbs_range_constraint_tail, // column 63 + quotient_low_limbs_range_constraint_0, // column 64 + quotient_low_limbs_range_constraint_1, // column 65 + quotient_low_limbs_range_constraint_2, // column 66 + quotient_low_limbs_range_constraint_3, // column 67 + quotient_low_limbs_range_constraint_4, // column 68 + quotient_low_limbs_range_constraint_tail, // column 69 + quotient_high_limbs_range_constraint_0, // column 70 + quotient_high_limbs_range_constraint_1, // column 71 + quotient_high_limbs_range_constraint_2, // column 72 + quotient_high_limbs_range_constraint_3, // column 73 + quotient_high_limbs_range_constraint_4, // column 74 + quotient_high_limbs_range_constraint_tail, // column 75 relation_wide_limbs_range_constraint_0, // column 76 relation_wide_limbs_range_constraint_1, // column 77 relation_wide_limbs_range_constraint_2, // column 78 relation_wide_limbs_range_constraint_3); // column 79 }; + template + class WireToBeShiftedEntities : public WireToBeShiftedWithoutConcatenated, + public WireToBeShiftedAndConcatenated { + public: + DEFINE_COMPOUND_GET_ALL(WireToBeShiftedWithoutConcatenated, WireToBeShiftedAndConcatenated) + }; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/907) // Note: These are technically derived from wires but do not depend on challenges (like z_perm). They are committed // to in the wires commitment round. @@ -407,51 +443,54 @@ class TranslatorFlavor { x_hi_z_1_shift, // column 1 y_lo_z_2_shift, // column 2 p_x_low_limbs_shift, // column 3 + p_x_high_limbs_shift, // column 10 + p_y_low_limbs_shift, // column 17 + p_y_high_limbs_shift, // column 24 + z_low_limbs_shift, // column 31 + z_high_limbs_shift, // column 38 + accumulators_binary_limbs_0_shift, // column 45 + accumulators_binary_limbs_1_shift, // column 46 + accumulators_binary_limbs_2_shift, // column 47 + accumulators_binary_limbs_3_shift, // column 48 + quotient_low_binary_limbs_shift, // column 61 + quotient_high_binary_limbs_shift, // column 62 + relation_wide_limbs_shift, // column 75 p_x_low_limbs_range_constraint_0_shift, // column 4 p_x_low_limbs_range_constraint_1_shift, // column 5 p_x_low_limbs_range_constraint_2_shift, // column 6 p_x_low_limbs_range_constraint_3_shift, // column 7 p_x_low_limbs_range_constraint_4_shift, // column 8 p_x_low_limbs_range_constraint_tail_shift, // column 9 - p_x_high_limbs_shift, // column 10 p_x_high_limbs_range_constraint_0_shift, // column 11 p_x_high_limbs_range_constraint_1_shift, // column 12 p_x_high_limbs_range_constraint_2_shift, // column 13 p_x_high_limbs_range_constraint_3_shift, // column 14 p_x_high_limbs_range_constraint_4_shift, // column 15 p_x_high_limbs_range_constraint_tail_shift, // column 16 - p_y_low_limbs_shift, // column 17 p_y_low_limbs_range_constraint_0_shift, // column 18 p_y_low_limbs_range_constraint_1_shift, // column 19 p_y_low_limbs_range_constraint_2_shift, // column 20 p_y_low_limbs_range_constraint_3_shift, // column 21 p_y_low_limbs_range_constraint_4_shift, // column 22 p_y_low_limbs_range_constraint_tail_shift, // column 23 - p_y_high_limbs_shift, // column 24 p_y_high_limbs_range_constraint_0_shift, // column 25 p_y_high_limbs_range_constraint_1_shift, // column 26 p_y_high_limbs_range_constraint_2_shift, // column 27 p_y_high_limbs_range_constraint_3_shift, // column 28 p_y_high_limbs_range_constraint_4_shift, // column 29 p_y_high_limbs_range_constraint_tail_shift, // column 30 - z_low_limbs_shift, // column 31 z_low_limbs_range_constraint_0_shift, // column 32 z_low_limbs_range_constraint_1_shift, // column 33 z_low_limbs_range_constraint_2_shift, // column 34 z_low_limbs_range_constraint_3_shift, // column 35 z_low_limbs_range_constraint_4_shift, // column 36 z_low_limbs_range_constraint_tail_shift, // column 37 - z_high_limbs_shift, // column 38 z_high_limbs_range_constraint_0_shift, // column 39 z_high_limbs_range_constraint_1_shift, // column 40 z_high_limbs_range_constraint_2_shift, // column 41 z_high_limbs_range_constraint_3_shift, // column 42 z_high_limbs_range_constraint_4_shift, // column 43 z_high_limbs_range_constraint_tail_shift, // column 44 - accumulators_binary_limbs_0_shift, // column 45 - accumulators_binary_limbs_1_shift, // column 46 - accumulators_binary_limbs_2_shift, // column 47 - accumulators_binary_limbs_3_shift, // column 48 accumulator_low_limbs_range_constraint_0_shift, // column 49 accumulator_low_limbs_range_constraint_1_shift, // column 50 accumulator_low_limbs_range_constraint_2_shift, // column 51 @@ -464,8 +503,6 @@ class TranslatorFlavor { accumulator_high_limbs_range_constraint_3_shift, // column 58 accumulator_high_limbs_range_constraint_4_shift, // column 59 accumulator_high_limbs_range_constraint_tail_shift, // column 60 - quotient_low_binary_limbs_shift, // column 61 - quotient_high_binary_limbs_shift, // column 62 quotient_low_limbs_range_constraint_0_shift, // column 63 quotient_low_limbs_range_constraint_1_shift, // column 64 quotient_low_limbs_range_constraint_2_shift, // column 65 @@ -478,7 +515,6 @@ class TranslatorFlavor { quotient_high_limbs_range_constraint_3_shift, // column 72 quotient_high_limbs_range_constraint_4_shift, // column 73 quotient_high_limbs_range_constraint_tail_shift, // column 74 - relation_wide_limbs_shift, // column 75 relation_wide_limbs_range_constraint_0_shift, // column 76 relation_wide_limbs_range_constraint_1_shift, // column 77 relation_wide_limbs_range_constraint_2_shift, // column 78 @@ -839,13 +875,13 @@ class TranslatorFlavor { this->x_hi_z_1 = "X_HI_Z_1"; this->y_lo_z_2 = "Y_LO_Z_2"; this->p_x_low_limbs = "P_X_LOW_LIMBS"; + this->p_x_high_limbs = "P_X_HIGH_LIMBS"; this->p_x_low_limbs_range_constraint_0 = "P_X_LOW_LIMBS_RANGE_CONSTRAINT_0"; this->p_x_low_limbs_range_constraint_1 = "P_X_LOW_LIMBS_RANGE_CONSTRAINT_1"; this->p_x_low_limbs_range_constraint_2 = "P_X_LOW_LIMBS_RANGE_CONSTRAINT_2"; this->p_x_low_limbs_range_constraint_3 = "P_X_LOW_LIMBS_RANGE_CONSTRAINT_3"; this->p_x_low_limbs_range_constraint_4 = "P_X_LOW_LIMBS_RANGE_CONSTRAINT_4"; this->p_x_low_limbs_range_constraint_tail = "P_X_LOW_LIMBS_RANGE_CONSTRAINT_TAIL"; - this->p_x_high_limbs = "P_X_HIGH_LIMBS"; this->p_x_high_limbs_range_constraint_0 = "P_X_HIGH_LIMBS_RANGE_CONSTRAINT_0"; this->p_x_high_limbs_range_constraint_1 = "P_X_HIGH_LIMBS_RANGE_CONSTRAINT_1"; this->p_x_high_limbs_range_constraint_2 = "P_X_HIGH_LIMBS_RANGE_CONSTRAINT_2"; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 1aabba2e607..628d3b0aab1 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -117,6 +117,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) if (sumcheck_verified.has_value() && !sumcheck_verified.value()) { return false; } + // Execute Shplemini const BatchOpeningClaim opening_claim = Shplemini::compute_batch_opening_claim(circuit_size, @@ -127,6 +128,7 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) multivariate_challenge, Commitment::one(), transcript, + Flavor::REPEATED_COMMITMENTS, RefVector(libra_commitments), libra_evaluations, commitments.get_groups_to_be_concatenated(), diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.cpp index baa129c691c..b28affc45cb 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.cpp @@ -18,7 +18,7 @@ template size_t DeciderProvingKey_::compute_dyadic // minimum size of execution trace due to everything else size_t min_size_of_execution_trace = circuit.public_inputs.size() + circuit.num_gates; - if constexpr (IsGoblinFlavor) { + if constexpr (IsMegaFlavor) { min_size_of_execution_trace += circuit.blocks.ecc_op.size(); } @@ -39,7 +39,7 @@ template size_t DeciderProvingKey_::compute_dyadic */ template void DeciderProvingKey_::construct_databus_polynomials(Circuit& circuit) - requires IsGoblinFlavor + requires IsMegaFlavor { auto& calldata_poly = proving_key.polynomials.calldata; auto& calldata_read_counts = proving_key.polynomials.calldata_read_counts; @@ -80,6 +80,113 @@ void DeciderProvingKey_::construct_databus_polynomials(Circuit& circuit) } } +/** + * @brief Check that the number of gates in each block does not exceed its fixed capacity. Move any overflow to the + * overflow block. + * @details Using a structured trace (fixed capcity for each gate type) optimizes the efficiency of folding. However, + * to accommodate circuits which cannot fit into a prescribed trace, gates which overflow their corresponding block are + * placed into an overflow block which can contain arbitrary gate types. + * @note One sublety is that gates at row i may in general utilize the values at row i+1 via shifts. If the last row in + * a full-capacity block is such a gate, then moving the overflow out of sequence will cause that gate not to be + * satisfied. To avoid this, when a block overflows, the final gate in the block is duplicated, once in the main block + * with the selectors turned off but the wires values maintained (so that the prior gate can read into it but it does + * not itself try to read into the next row) and again as a normal gate in the overflow block. Therefore, the total + * number of gates in the circuit increases by one for each block that overflows. + * + * @tparam Flavor + * @param circuit + */ +template +void DeciderProvingKey_::move_structured_trace_overflow_to_overflow_block(Circuit& circuit) +{ + auto& blocks = circuit.blocks; + auto& overflow_block = circuit.blocks.overflow; + + // Set has_overflow to true if a nonzero fixed size has been prescribed for the overflow block + blocks.has_overflow = (overflow_block.get_fixed_size() > 0); + + blocks.compute_offsets(/*is_structured=*/true); // compute the offset of each fixed size block + + // Check each block for capacity overflow; if necessary move gates into the overflow block + for (auto& block : blocks.get()) { + size_t block_size = block.size(); + uint32_t fixed_block_size = block.get_fixed_size(); + if (block_size > fixed_block_size && block != overflow_block) { + // Disallow overflow in blocks that are not expected to be used by App circuits + ASSERT(!block.is_pub_inputs); + if constexpr (IsMegaFlavor) { + ASSERT(block != blocks.ecc_op); + } + + // Set has_overflow to true if at least one block exceeds its capacity + blocks.has_overflow = true; + + // The circuit memory read/write records store the indices at which a RAM/ROM read/write has occurred. If + // the block containing RAM/ROM gates overflows, the indices of the corresponding gates in the memory + // records need to be updated to reflect their new position in the overflow block + if (block.has_ram_rom) { + + uint32_t overflow_cur_idx = overflow_block.trace_offset + static_cast(overflow_block.size()); + overflow_cur_idx -= block.trace_offset; // we'll add block.trace_offset to everything later + uint32_t offset = overflow_cur_idx + 1; // +1 accounts for duplication of final gate + for (auto& idx : circuit.memory_read_records) { + // last gate in the main block will be duplicated; if necessary, duplicate the memory read idx too + if (idx == fixed_block_size - 1) { + circuit.memory_read_records.push_back(overflow_cur_idx); + } + if (idx >= fixed_block_size) { + idx -= fixed_block_size; // redefine index from zero + idx += offset; // shift to correct location in overflow block + } + } + for (auto& idx : circuit.memory_write_records) { + // last gate in the main block will be duplicated; if necessary, duplicate the memory write idx too + if (idx == fixed_block_size - 1) { + circuit.memory_write_records.push_back(overflow_cur_idx); + } + if (idx >= fixed_block_size) { + idx -= fixed_block_size; // redefine index from zero + idx += offset; // shift to correct location in overflow block + } + } + } + + // Move the excess wire and selector data from the offending block to the overflow block + size_t overflow_start = fixed_block_size - 1; // the final gate in the main block is duplicated + size_t overflow_end = block_size; + for (auto [wire, overflow_wire] : zip_view(block.wires, overflow_block.wires)) { + for (size_t i = overflow_start; i < overflow_end; ++i) { + overflow_wire.push_back(wire[i]); + } + wire.resize(fixed_block_size); // shrink the main block to its max capacity + } + for (auto [selector, overflow_selector] : zip_view(block.selectors, overflow_block.selectors)) { + for (size_t i = overflow_start; i < overflow_end; ++i) { + overflow_selector.push_back(selector[i]); + } + selector.resize(fixed_block_size); // shrink the main block to its max capacity + } + // Convert duplicated final gate in the main block to a 'dummy' gate by turning off all selectors. This + // ensures it can be read into by the previous gate but does not itself try to read into the next gate. + for (auto& selector : block.get_gate_selectors()) { + selector.back() = 0; + } + } + } + + // Set the fixed size of the overflow block to its current size + if (overflow_block.size() > overflow_block.get_fixed_size()) { + info("WARNING: Structured trace overflowed beyond the prescribed fixed overflow size. This is valid in the " + "context of one-off VK/proof generation but not in the IVC setting. \nPrescribed overflow size: ", + overflow_block.get_fixed_size(), + ". \nActual overflow size: ", + overflow_block.size(), + "\n"); + overflow_block.set_fixed_size(static_cast(overflow_block.size())); + blocks.summarize(); + } +} + template class DeciderProvingKey_; template class DeciderProvingKey_; template class DeciderProvingKey_; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp index 0a5b224a540..e09628038e3 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_proving_key.hpp @@ -30,12 +30,12 @@ template class DeciderProvingKey_ { using Polynomial = typename Flavor::Polynomial; using RelationSeparator = typename Flavor::RelationSeparator; - using Trace = ExecutionTrace_; - // Flag indicating whether the polynomials will be constructed with fixed block sizes for each gate type bool is_structured; public: + using Trace = ExecutionTrace_; + ProvingKey proving_key; bool is_accumulator = false; @@ -45,10 +45,12 @@ template class DeciderProvingKey_ { // The target sum, which is typically nonzero for a ProtogalaxyProver's accmumulator FF target_sum; + size_t final_active_wire_idx{ 0 }; // idx of last non-trivial wire value in the trace + DeciderProvingKey_(Circuit& circuit, - TraceStructure trace_structure = TraceStructure::NONE, + TraceSettings trace_settings = TraceSettings{}, std::shared_ptr commitment_key = nullptr) - : is_structured(trace_structure != TraceStructure::NONE) + : is_structured(trace_settings.structure != TraceStructure::NONE) { PROFILE_THIS_NAME("DeciderProvingKey(Circuit&)"); vinfo("Constructing DeciderProvingKey"); @@ -58,8 +60,9 @@ template class DeciderProvingKey_ { // If using a structured trace, set fixed block sizes, check their validity, and set the dyadic circuit size if (is_structured) { - circuit.blocks.set_fixed_block_sizes(trace_structure); // set the fixed sizes for each block - circuit.blocks.check_within_fixed_sizes(); // ensure that no block exceeds its fixed size + circuit.blocks.set_fixed_block_sizes(trace_settings); // set the fixed sizes for each block + circuit.blocks.summarize(); + move_structured_trace_overflow_to_overflow_block(circuit); dyadic_circuit_size = compute_structured_dyadic_size(circuit); // set the dyadic size accordingly } else { dyadic_circuit_size = compute_dyadic_size(circuit); // set dyadic size directly from circuit block sizes @@ -74,10 +77,17 @@ template class DeciderProvingKey_ { Trace::populate_public_inputs_block(circuit); circuit.blocks.compute_offsets(is_structured); + // Find index of last non-trivial wire value in the trace + for (auto& block : circuit.blocks.get()) { + if (block.size() > 0) { + final_active_wire_idx = block.trace_offset + block.size() - 1; + } + } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/905): This is adding ops to the op queue but NOT to // the circuit, meaning the ECCVM/Translator will use different ops than the main circuit. This will lead to // failure once https://github.com/AztecProtocol/barretenberg/issues/746 is resolved. - if constexpr (IsGoblinFlavor) { + if constexpr (IsMegaFlavor) { circuit.op_queue->append_nonzero_ops(); } { @@ -85,7 +95,9 @@ template class DeciderProvingKey_ { PROFILE_THIS_NAME("constructing proving key"); proving_key = ProvingKey(dyadic_circuit_size, circuit.public_inputs.size(), commitment_key); - if (IsGoblinFlavor && !is_structured) { + // If not using structured trace OR if using structured trace but overflow has occurred (overflow block in + // use), allocate full size polys + if ((IsMegaFlavor && !is_structured) || (is_structured && circuit.blocks.has_overflow)) { // Allocate full size polynomials proving_key.polynomials = typename Flavor::ProverPolynomials(dyadic_circuit_size); } else { // Allocate only a correct amount of memory for each polynomial @@ -126,7 +138,7 @@ template class DeciderProvingKey_ { selector = Polynomial(proving_key.circuit_size); } } - if constexpr (IsGoblinFlavor) { + if constexpr (IsMegaFlavor) { PROFILE_THIS_NAME("allocating ecc op wires and selector"); // Allocate the ecc op wires and selector @@ -235,8 +247,14 @@ template class DeciderProvingKey_ { PROFILE_THIS_NAME("allocating lagrange polynomials"); // First and last lagrange polynomials (in the full circuit size) - proving_key.polynomials.lagrange_first = Polynomial(1, dyadic_circuit_size, 0); - proving_key.polynomials.lagrange_last = Polynomial(1, dyadic_circuit_size, dyadic_circuit_size - 1); + proving_key.polynomials.lagrange_first = Polynomial( + /* size=*/1, /*virtual size=*/dyadic_circuit_size, /*start_idx=*/0); + + // Even though lagrange_last has a singe non-zero element, we cannot set its size to 0 as different + // keys being folded might have lagrange_last set at different indexes and folding does not work + // correctly unless the polynomial is allocated in the correct range to accomodate this + proving_key.polynomials.lagrange_last = Polynomial( + /* size=*/dyadic_circuit_size, /*virtual size=*/dyadic_circuit_size, /*start_idx=*/0); } } // We can finally set the shifted polynomials now that all of the to_be_shifted polynomials are @@ -253,7 +271,7 @@ template class DeciderProvingKey_ { PROFILE_THIS_NAME("constructing prover instance after trace populate"); // If Goblin, construct the databus polynomials - if constexpr (IsGoblinFlavor) { + if constexpr (IsMegaFlavor) { PROFILE_THIS_NAME("constructing databus polynomials"); construct_databus_polynomials(circuit); @@ -261,7 +279,7 @@ template class DeciderProvingKey_ { } // Set the lagrange polynomials proving_key.polynomials.lagrange_first.at(0) = 1; - proving_key.polynomials.lagrange_last.at(dyadic_circuit_size - 1) = 1; + proving_key.polynomials.lagrange_last.at(final_active_wire_idx) = 1; { PROFILE_THIS_NAME("constructing lookup table polynomials"); @@ -290,7 +308,7 @@ template class DeciderProvingKey_ { circuit.pairing_point_accumulator_public_input_indices; proving_key.contains_pairing_point_accumulator = circuit.contains_pairing_point_accumulator; - if constexpr (IsGoblinFlavor) { // Set databus commitment propagation data + if constexpr (IsMegaFlavor) { // Set databus commitment propagation data proving_key.databus_propagation_data = circuit.databus_propagation_data; } auto end = std::chrono::steady_clock::now(); @@ -314,14 +332,12 @@ template class DeciderProvingKey_ { * @brief Compute dyadic size based on a structured trace with fixed block size * */ - size_t compute_structured_dyadic_size(Circuit& circuit) - { - size_t minimum_size = circuit.blocks.get_total_structured_size(); - return circuit.get_circuit_subgroup_size(minimum_size); - } + size_t compute_structured_dyadic_size(Circuit& circuit) { return circuit.blocks.get_structured_dyadic_size(); } void construct_databus_polynomials(Circuit&) - requires IsGoblinFlavor; + requires IsMegaFlavor; + + static void move_structured_trace_overflow_to_overflow_block(Circuit& circuit); }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp index 6f7b1d8e919..996df320f95 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp @@ -79,11 +79,11 @@ template bool DeciderVerifier_::verify() sumcheck_output.challenge, Commitment::one(), transcript, + Flavor::REPEATED_COMMITMENTS, RefVector(libra_commitments), libra_evaluations); const auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); bool verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); - return sumcheck_output.verified.value() && verified; } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index ae7ffca7466..92159f626a6 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -2,6 +2,7 @@ #include #include +#include "barretenberg/circuit_checker/circuit_checker.hpp" #include "barretenberg/common/log.hpp" #include "barretenberg/goblin/mock_circuits.hpp" #include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" @@ -48,6 +49,28 @@ template class MegaHonkTests : public ::testing::Test { return verified; } + /** + * @brief Construct and a verify a Honk proof using a specified structured trace + * + */ + bool construct_and_verify_honk_proof_with_structured_trace(auto& builder, TraceSettings& trace_settings) + { + // no ZK flavor for now + using Prover = UltraProver_; + using Verifier = UltraVerifier_; + using VerificationKey = typename MegaFlavor::VerificationKey; + using DeciderProvingKey = DeciderProvingKey_; + auto proving_key = std::make_shared(builder, trace_settings); + + Prover prover(proving_key); + auto verification_key = std::make_shared(proving_key->proving_key); + Verifier verifier(verification_key); + auto proof = prover.construct_proof(); + bool verified = verifier.verify_proof(proof); + + return verified; + } + /** * @brief Construct and verify a Goblin ECC op queue merge proof * @@ -96,8 +119,8 @@ TYPED_TEST(MegaHonkTests, BasicStructured) GoblinMockCircuits::construct_simple_circuit(builder); // Construct and verify Honk proof using a structured trace - TraceStructure trace_structure = TraceStructure::SMALL_TEST; - auto proving_key = std::make_shared>(builder, trace_structure); + TraceSettings trace_settings{ TraceStructure::SMALL_TEST }; + auto proving_key = std::make_shared>(builder, trace_settings); Prover prover(proving_key); auto verification_key = std::make_shared(proving_key->proving_key); Verifier verifier(verification_key); @@ -225,3 +248,69 @@ TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkAndMerge) EXPECT_EQ(result, expected); } } + +/** + * @brief Test the structured trace overflow mechanism for various circuits which overflow in different ways + * + */ +TYPED_TEST(MegaHonkTests, StructuredTraceOverflow) +{ + using Flavor = TypeParam; + using Builder = Flavor::CircuitBuilder; + + TraceSettings trace_settings{ TraceStructure::TINY_TEST }; + + { // Overflow in Arithmetic block only + Builder builder; + + GoblinMockCircuits::construct_simple_circuit(builder); + MockCircuits::add_arithmetic_gates(builder, 1 << 15); + + bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); + EXPECT_TRUE(verified); + + // We expect that the circuit has overflowed the provided structured trace + EXPECT_TRUE(builder.blocks.has_overflow); + } + + { // Overflow in Aux block (RAM gates; uses memory records which requires specific logic in overflow mechanism) + Builder builder; + + GoblinMockCircuits::construct_simple_circuit(builder); + MockCircuits::add_RAM_gates(builder); + + bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); + EXPECT_TRUE(verified); + + // We expect that the circuit has overflowed the provided structured trace + EXPECT_TRUE(builder.blocks.has_overflow); + } + + { // Overflow in Lookup block only + Builder builder; + + GoblinMockCircuits::construct_simple_circuit(builder); + MockCircuits::add_lookup_gates(builder, /*num_iterations=*/8); + + bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); + EXPECT_TRUE(verified); + + // We expect that the circuit has overflowed the provided structured trace + EXPECT_TRUE(builder.blocks.has_overflow); + } + + { // Overflow in Multiple blocks simultaneously + Builder builder; + + GoblinMockCircuits::construct_simple_circuit(builder); + MockCircuits::add_arithmetic_gates(builder, 1 << 15); + MockCircuits::add_RAM_gates(builder); + MockCircuits::add_lookup_gates(builder, /*num_iterations=*/8); + + bool verified = this->construct_and_verify_honk_proof_with_structured_trace(builder, trace_settings); + EXPECT_TRUE(verified); + + // We expect that the circuit has overflowed the provided structured trace + EXPECT_TRUE(builder.blocks.has_overflow); + } +} diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp index 594ba28d05c..cbea1470ab5 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp @@ -119,7 +119,7 @@ template void OinkProver::execute_wire_commitment transcript->send_to_verifier(domain_separator + wire_labels[idx], wire_comms[idx]); } - if constexpr (IsGoblinFlavor) { + if constexpr (IsMegaFlavor) { // Commit to Goblin ECC op wires for (auto [commitment, polynomial, label] : zip_view(witness_commitments.get_ecc_op_wires(), @@ -211,7 +211,7 @@ template void OinkProver::execute_log_derivative_ witness_commitments.lookup_inverses); // If Mega, commit to the databus inverse polynomials and send - if constexpr (IsGoblinFlavor) { + if constexpr (IsMegaFlavor) { for (auto [commitment, polynomial, label] : zip_view(witness_commitments.get_databus_inverses(), proving_key->proving_key.polynomials.get_databus_inverses(), @@ -232,8 +232,9 @@ template void OinkProver::execute_log_derivative_ template void OinkProver::execute_grand_product_computation_round() { PROFILE_THIS_NAME("OinkProver::execute_grand_product_computation_round"); - // Compute the permutation and lookup grand product polynomials - proving_key->proving_key.compute_grand_product_polynomials(proving_key->relation_parameters); + // Compute the permutation grand product polynomial + proving_key->proving_key.compute_grand_product_polynomial(proving_key->relation_parameters, + proving_key->final_active_wire_idx + 1); { PROFILE_THIS_NAME("COMMIT::z_perm"); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp index 96ca8161f1d..bd7aa34fb88 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp @@ -70,7 +70,7 @@ template void OinkVerifier::execute_wire_commitme witness_comms.w_o = transcript->template receive_from_prover(domain_separator + comm_labels.w_o); // If Goblin, get commitments to ECC op wire polynomials and DataBus columns - if constexpr (IsGoblinFlavor) { + if constexpr (IsMegaFlavor) { // Receive ECC op wire commitments for (auto [commitment, label] : zip_view(witness_comms.get_ecc_op_wires(), comm_labels.get_ecc_op_wires())) { commitment = transcript->template receive_from_prover(domain_separator + label); @@ -106,7 +106,7 @@ template void OinkVerifier::execute_sorted_list_a } /** - * @brief Get log derivative inverse polynomial and its commitment, if GoblinFlavor + * @brief Get log derivative inverse polynomial and its commitment, if MegaFlavor * */ template void OinkVerifier::execute_log_derivative_inverse_round() @@ -120,7 +120,7 @@ template void OinkVerifier::execute_log_derivativ transcript->template receive_from_prover(domain_separator + comm_labels.lookup_inverses); // If Goblin (i.e. using DataBus) receive commitments to log-deriv inverses polynomials - if constexpr (IsGoblinFlavor) { + if constexpr (IsMegaFlavor) { for (auto [commitment, label] : zip_view(witness_comms.get_databus_inverses(), comm_labels.get_databus_inverses())) { commitment = transcript->template receive_from_prover(domain_separator + label); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp index 1958860a83a..334a7d6e5f0 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp @@ -219,7 +219,7 @@ template void create_some_ecc_op_queue_gates(auto& circuit_bui { using G1 = typename Flavor::Curve::Group; using FF = typename Flavor::FF; - static_assert(IsGoblinFlavor); + static_assert(IsMegaFlavor); const size_t num_ecc_operations = 10; // arbitrary for (size_t i = 0; i < num_ecc_operations; ++i) { auto point = G1::affine_one * FF::random_element(); @@ -249,7 +249,7 @@ TEST_F(UltraRelationCorrectnessTests, Ultra) using Flavor = UltraFlavor; using FF = typename Flavor::FF; - // Create a composer and then add an assortment of gates designed to ensure that the constraint(s) represented + // Create a builder and then add an assortment of gates designed to ensure that the constraint(s) represented // by each relation are non-trivially exercised. auto builder = UltraCircuitBuilder(); @@ -276,7 +276,8 @@ TEST_F(UltraRelationCorrectnessTests, Ultra) decider_pk->relation_parameters.eta_two, decider_pk->relation_parameters.eta_three); decider_pk->proving_key.compute_logderivative_inverses(decider_pk->relation_parameters); - decider_pk->proving_key.compute_grand_product_polynomials(decider_pk->relation_parameters); + decider_pk->proving_key.compute_grand_product_polynomial(decider_pk->relation_parameters, + decider_pk->final_active_wire_idx + 1); // Check that selectors are nonzero to ensure corresponding relation has nontrivial contribution ensure_non_zero(proving_key.polynomials.q_arith); @@ -329,7 +330,8 @@ TEST_F(UltraRelationCorrectnessTests, Mega) decider_pk->relation_parameters.eta_two, decider_pk->relation_parameters.eta_three); decider_pk->proving_key.compute_logderivative_inverses(decider_pk->relation_parameters); - decider_pk->proving_key.compute_grand_product_polynomials(decider_pk->relation_parameters); + decider_pk->proving_key.compute_grand_product_polynomial(decider_pk->relation_parameters, + decider_pk->final_active_wire_idx + 1); // Check that selectors are nonzero to ensure corresponding relation has nontrivial contribution ensure_non_zero(proving_key.polynomials.q_arith); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp index 45f5a78c4d3..2a7c3d5646b 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp @@ -160,7 +160,8 @@ TEST_F(SumcheckTestsRealCircuit, Ultra) decider_pk->relation_parameters.eta_two, decider_pk->relation_parameters.eta_three); decider_pk->proving_key.compute_logderivative_inverses(decider_pk->relation_parameters); - decider_pk->proving_key.compute_grand_product_polynomials(decider_pk->relation_parameters); + decider_pk->proving_key.compute_grand_product_polynomial(decider_pk->relation_parameters, + decider_pk->final_active_wire_idx + 1); auto prover_transcript = Transcript::prover_init_empty(); auto circuit_size = decider_pk->proving_key.circuit_size; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp index 79f6406cbe6..b8564e9ae75 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp @@ -100,8 +100,8 @@ TYPED_TEST(UltraHonkTests, StructuredTrace) MockCircuits::add_arithmetic_gates_with_public_inputs(builder, num_gates); // Construct an proving_key with a structured execution trace - TraceStructure trace_structure = TraceStructure::SMALL_TEST; - auto proving_key = std::make_shared(builder, trace_structure); + TraceSettings trace_settings{ TraceStructure::SMALL_TEST }; + auto proving_key = std::make_shared(builder, trace_settings); typename TestFixture::Prover prover(proving_key); auto verification_key = std::make_shared(proving_key->proving_key); typename TestFixture::Verifier verifier(verification_key); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/circuit_builder.cpp index d900a1f8506..6a3d9ae9f17 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/circuit_builder.cpp @@ -139,6 +139,7 @@ AvmCircuitBuilder::ProverPolynomials AvmCircuitBuilder::compute_polynomials() co polys.alu_cmp_gadget_gt.set_if_valid_index(i, rows[i].alu_cmp_gadget_gt); polys.alu_cmp_gadget_input_a.set_if_valid_index(i, rows[i].alu_cmp_gadget_input_a); polys.alu_cmp_gadget_input_b.set_if_valid_index(i, rows[i].alu_cmp_gadget_input_b); + polys.alu_cmp_gadget_non_ff_gt.set_if_valid_index(i, rows[i].alu_cmp_gadget_non_ff_gt); polys.alu_cmp_gadget_result.set_if_valid_index(i, rows[i].alu_cmp_gadget_result); polys.alu_cmp_gadget_sel.set_if_valid_index(i, rows[i].alu_cmp_gadget_sel); polys.alu_ff_tag.set_if_valid_index(i, rows[i].alu_ff_tag); @@ -218,11 +219,13 @@ AvmCircuitBuilder::ProverPolynomials AvmCircuitBuilder::compute_polynomials() co polys.cmp_borrow.set_if_valid_index(i, rows[i].cmp_borrow); polys.cmp_clk.set_if_valid_index(i, rows[i].cmp_clk); polys.cmp_cmp_rng_ctr.set_if_valid_index(i, rows[i].cmp_cmp_rng_ctr); + polys.cmp_diff.set_if_valid_index(i, rows[i].cmp_diff); polys.cmp_input_a.set_if_valid_index(i, rows[i].cmp_input_a); polys.cmp_input_b.set_if_valid_index(i, rows[i].cmp_input_b); polys.cmp_op_eq.set_if_valid_index(i, rows[i].cmp_op_eq); polys.cmp_op_eq_diff_inv.set_if_valid_index(i, rows[i].cmp_op_eq_diff_inv); polys.cmp_op_gt.set_if_valid_index(i, rows[i].cmp_op_gt); + polys.cmp_op_non_ff_gt.set_if_valid_index(i, rows[i].cmp_op_non_ff_gt); polys.cmp_p_a_borrow.set_if_valid_index(i, rows[i].cmp_p_a_borrow); polys.cmp_p_b_borrow.set_if_valid_index(i, rows[i].cmp_p_b_borrow); polys.cmp_p_sub_a_hi.set_if_valid_index(i, rows[i].cmp_p_sub_a_hi); @@ -254,6 +257,8 @@ AvmCircuitBuilder::ProverPolynomials AvmCircuitBuilder::compute_polynomials() co polys.main_bin_op_id.set_if_valid_index(i, rows[i].main_bin_op_id); polys.main_call_ptr.set_if_valid_index(i, rows[i].main_call_ptr); polys.main_da_gas_remaining.set_if_valid_index(i, rows[i].main_da_gas_remaining); + polys.main_da_gas_u16_r0.set_if_valid_index(i, rows[i].main_da_gas_u16_r0); + polys.main_da_gas_u16_r1.set_if_valid_index(i, rows[i].main_da_gas_u16_r1); polys.main_da_out_of_gas.set_if_valid_index(i, rows[i].main_da_out_of_gas); polys.main_dyn_da_gas_op_cost.set_if_valid_index(i, rows[i].main_dyn_da_gas_op_cost); polys.main_dyn_gas_multiplier.set_if_valid_index(i, rows[i].main_dyn_gas_multiplier); @@ -282,6 +287,8 @@ AvmCircuitBuilder::ProverPolynomials AvmCircuitBuilder::compute_polynomials() co polys.main_l1_to_l2_msg_exists_write_offset.set_if_valid_index( i, rows[i].main_l1_to_l2_msg_exists_write_offset); polys.main_l2_gas_remaining.set_if_valid_index(i, rows[i].main_l2_gas_remaining); + polys.main_l2_gas_u16_r0.set_if_valid_index(i, rows[i].main_l2_gas_u16_r0); + polys.main_l2_gas_u16_r1.set_if_valid_index(i, rows[i].main_l2_gas_u16_r1); polys.main_l2_out_of_gas.set_if_valid_index(i, rows[i].main_l2_out_of_gas); polys.main_mem_addr_a.set_if_valid_index(i, rows[i].main_mem_addr_a); polys.main_mem_addr_b.set_if_valid_index(i, rows[i].main_mem_addr_b); @@ -322,6 +329,7 @@ AvmCircuitBuilder::ProverPolynomials AvmCircuitBuilder::compute_polynomials() co polys.main_sel_op_cast.set_if_valid_index(i, rows[i].main_sel_op_cast); polys.main_sel_op_chain_id.set_if_valid_index(i, rows[i].main_sel_op_chain_id); polys.main_sel_op_dagasleft.set_if_valid_index(i, rows[i].main_sel_op_dagasleft); + polys.main_sel_op_debug_log.set_if_valid_index(i, rows[i].main_sel_op_debug_log); polys.main_sel_op_div.set_if_valid_index(i, rows[i].main_sel_op_div); polys.main_sel_op_ecadd.set_if_valid_index(i, rows[i].main_sel_op_ecadd); polys.main_sel_op_emit_l2_to_l1_msg.set_if_valid_index(i, rows[i].main_sel_op_emit_l2_to_l1_msg); @@ -755,6 +763,7 @@ AvmCircuitBuilder::ProverPolynomials AvmCircuitBuilder::compute_polynomials() co polys.range_check_clk.set_if_valid_index(i, rows[i].range_check_clk); polys.range_check_cmp_hi_bits_rng_chk.set_if_valid_index(i, rows[i].range_check_cmp_hi_bits_rng_chk); polys.range_check_cmp_lo_bits_rng_chk.set_if_valid_index(i, rows[i].range_check_cmp_lo_bits_rng_chk); + polys.range_check_cmp_non_ff_rng_chk.set_if_valid_index(i, rows[i].range_check_cmp_non_ff_rng_chk); polys.range_check_dyn_diff.set_if_valid_index(i, rows[i].range_check_dyn_diff); polys.range_check_dyn_rng_chk_bits.set_if_valid_index(i, rows[i].range_check_dyn_rng_chk_bits); polys.range_check_dyn_rng_chk_pow_2.set_if_valid_index(i, rows[i].range_check_dyn_rng_chk_pow_2); @@ -820,6 +829,10 @@ AvmCircuitBuilder::ProverPolynomials AvmCircuitBuilder::compute_polynomials() co polys.lookup_byte_lengths_counts.set_if_valid_index(i, rows[i].lookup_byte_lengths_counts); polys.lookup_byte_operations_counts.set_if_valid_index(i, rows[i].lookup_byte_operations_counts); polys.lookup_opcode_gas_counts.set_if_valid_index(i, rows[i].lookup_opcode_gas_counts); + polys.lookup_l2_gas_rng_chk_0_counts.set_if_valid_index(i, rows[i].lookup_l2_gas_rng_chk_0_counts); + polys.lookup_l2_gas_rng_chk_1_counts.set_if_valid_index(i, rows[i].lookup_l2_gas_rng_chk_1_counts); + polys.lookup_da_gas_rng_chk_0_counts.set_if_valid_index(i, rows[i].lookup_da_gas_rng_chk_0_counts); + polys.lookup_da_gas_rng_chk_1_counts.set_if_valid_index(i, rows[i].lookup_da_gas_rng_chk_1_counts); polys.kernel_output_lookup_counts.set_if_valid_index(i, rows[i].kernel_output_lookup_counts); polys.lookup_into_kernel_counts.set_if_valid_index(i, rows[i].lookup_into_kernel_counts); polys.lookup_cd_value_counts.set_if_valid_index(i, rows[i].lookup_cd_value_counts); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.cpp index 1374e8e69db..5d5c812deb0 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.cpp @@ -44,801 +44,817 @@ AvmFlavor::AllConstRefValues::AllConstRefValues( , alu_cmp_gadget_gt(il[36]) , alu_cmp_gadget_input_a(il[37]) , alu_cmp_gadget_input_b(il[38]) - , alu_cmp_gadget_result(il[39]) - , alu_cmp_gadget_sel(il[40]) - , alu_ff_tag(il[41]) - , alu_ia(il[42]) - , alu_ib(il[43]) - , alu_ic(il[44]) - , alu_in_tag(il[45]) - , alu_max_bits_sub_b_bits(il[46]) - , alu_max_bits_sub_b_pow(il[47]) - , alu_op_add(il[48]) - , alu_op_cast(il[49]) - , alu_op_div(il[50]) - , alu_op_eq(il[51]) - , alu_op_lt(il[52]) - , alu_op_lte(il[53]) - , alu_op_mul(il[54]) - , alu_op_not(il[55]) - , alu_op_shl(il[56]) - , alu_op_shr(il[57]) - , alu_op_sub(il[58]) - , alu_partial_prod_hi(il[59]) - , alu_partial_prod_lo(il[60]) - , alu_range_check_input_value(il[61]) - , alu_range_check_num_bits(il[62]) - , alu_range_check_sel(il[63]) - , alu_remainder(il[64]) - , alu_sel_alu(il[65]) - , alu_sel_cmp(il[66]) - , alu_sel_shift_which(il[67]) - , alu_u128_tag(il[68]) - , alu_u16_tag(il[69]) - , alu_u1_tag(il[70]) - , alu_u32_tag(il[71]) - , alu_u64_tag(il[72]) - , alu_u8_tag(il[73]) - , alu_zero_shift(il[74]) - , binary_acc_ia(il[75]) - , binary_acc_ib(il[76]) - , binary_acc_ic(il[77]) - , binary_clk(il[78]) - , binary_ia_bytes(il[79]) - , binary_ib_bytes(il[80]) - , binary_ic_bytes(il[81]) - , binary_in_tag(il[82]) - , binary_mem_tag_ctr(il[83]) - , binary_mem_tag_ctr_inv(il[84]) - , binary_op_id(il[85]) - , binary_sel_bin(il[86]) - , binary_start(il[87]) - , bytecode_arifact_hash(il[88]) - , bytecode_as_fields(il[89]) - , bytecode_bytes(il[90]) - , bytecode_bytes_pc(il[91]) - , bytecode_class_id(il[92]) - , bytecode_contract_address(il[93]) - , bytecode_decomposed(il[94]) - , bytecode_deployer_addr(il[95]) - , bytecode_end_latch(il[96]) - , bytecode_incoming_viewing_key_x(il[97]) - , bytecode_incoming_viewing_key_y(il[98]) - , bytecode_initialization_hash(il[99]) - , bytecode_length_remaining(il[100]) - , bytecode_nullifier_key_x(il[101]) - , bytecode_nullifier_key_y(il[102]) - , bytecode_outgoing_viewing_key_x(il[103]) - , bytecode_outgoing_viewing_key_y(il[104]) - , bytecode_private_fn_root(il[105]) - , bytecode_public_key_hash(il[106]) - , bytecode_running_hash(il[107]) - , bytecode_salt(il[108]) - , bytecode_tagging_key_x(il[109]) - , bytecode_tagging_key_y(il[110]) - , cmp_a_hi(il[111]) - , cmp_a_lo(il[112]) - , cmp_b_hi(il[113]) - , cmp_b_lo(il[114]) - , cmp_borrow(il[115]) - , cmp_clk(il[116]) - , cmp_cmp_rng_ctr(il[117]) - , cmp_input_a(il[118]) - , cmp_input_b(il[119]) - , cmp_op_eq(il[120]) - , cmp_op_eq_diff_inv(il[121]) - , cmp_op_gt(il[122]) - , cmp_p_a_borrow(il[123]) - , cmp_p_b_borrow(il[124]) - , cmp_p_sub_a_hi(il[125]) - , cmp_p_sub_a_lo(il[126]) - , cmp_p_sub_b_hi(il[127]) - , cmp_p_sub_b_lo(il[128]) - , cmp_range_chk_clk(il[129]) - , cmp_res_hi(il[130]) - , cmp_res_lo(il[131]) - , cmp_result(il[132]) - , cmp_sel_cmp(il[133]) - , cmp_sel_rng_chk(il[134]) - , cmp_shift_sel(il[135]) - , conversion_clk(il[136]) - , conversion_input(il[137]) - , conversion_num_limbs(il[138]) - , conversion_output_bits(il[139]) - , conversion_radix(il[140]) - , conversion_sel_to_radix_be(il[141]) - , keccakf1600_clk(il[142]) - , keccakf1600_input(il[143]) - , keccakf1600_output(il[144]) - , keccakf1600_sel_keccakf1600(il[145]) - , main_abs_da_rem_gas(il[146]) - , main_abs_l2_rem_gas(il[147]) - , main_alu_in_tag(il[148]) - , main_base_da_gas_op_cost(il[149]) - , main_base_l2_gas_op_cost(il[150]) - , main_bin_op_id(il[151]) - , main_call_ptr(il[152]) - , main_da_gas_remaining(il[153]) - , main_da_out_of_gas(il[154]) - , main_dyn_da_gas_op_cost(il[155]) - , main_dyn_gas_multiplier(il[156]) - , main_dyn_l2_gas_op_cost(il[157]) - , main_emit_l2_to_l1_msg_write_offset(il[158]) - , main_emit_note_hash_write_offset(il[159]) - , main_emit_nullifier_write_offset(il[160]) - , main_emit_unencrypted_log_write_offset(il[161]) - , main_ia(il[162]) - , main_ib(il[163]) - , main_ic(il[164]) - , main_id(il[165]) - , main_id_zero(il[166]) - , main_ind_addr_a(il[167]) - , main_ind_addr_b(il[168]) - , main_ind_addr_c(il[169]) - , main_ind_addr_d(il[170]) - , main_internal_return_ptr(il[171]) - , main_inv(il[172]) - , main_is_fake_row(il[173]) - , main_is_gas_accounted(il[174]) - , main_kernel_in_offset(il[175]) - , main_kernel_out_offset(il[176]) - , main_l1_to_l2_msg_exists_write_offset(il[177]) - , main_l2_gas_remaining(il[178]) - , main_l2_out_of_gas(il[179]) - , main_mem_addr_a(il[180]) - , main_mem_addr_b(il[181]) - , main_mem_addr_c(il[182]) - , main_mem_addr_d(il[183]) - , main_note_hash_exist_write_offset(il[184]) - , main_nullifier_exists_write_offset(il[185]) - , main_nullifier_non_exists_write_offset(il[186]) - , main_op_err(il[187]) - , main_opcode_val(il[188]) - , main_pc(il[189]) - , main_r_in_tag(il[190]) - , main_rwa(il[191]) - , main_rwb(il[192]) - , main_rwc(il[193]) - , main_rwd(il[194]) - , main_sel_alu(il[195]) - , main_sel_bin(il[196]) - , main_sel_calldata(il[197]) - , main_sel_execution_end(il[198]) - , main_sel_execution_row(il[199]) - , main_sel_kernel_inputs(il[200]) - , main_sel_kernel_out(il[201]) - , main_sel_mem_op_a(il[202]) - , main_sel_mem_op_b(il[203]) - , main_sel_mem_op_c(il[204]) - , main_sel_mem_op_d(il[205]) - , main_sel_mov_ia_to_ic(il[206]) - , main_sel_mov_ib_to_ic(il[207]) - , main_sel_op_add(il[208]) - , main_sel_op_address(il[209]) - , main_sel_op_and(il[210]) - , main_sel_op_block_number(il[211]) - , main_sel_op_calldata_copy(il[212]) - , main_sel_op_cast(il[213]) - , main_sel_op_chain_id(il[214]) - , main_sel_op_dagasleft(il[215]) - , main_sel_op_div(il[216]) - , main_sel_op_ecadd(il[217]) - , main_sel_op_emit_l2_to_l1_msg(il[218]) - , main_sel_op_emit_note_hash(il[219]) - , main_sel_op_emit_nullifier(il[220]) - , main_sel_op_emit_unencrypted_log(il[221]) - , main_sel_op_eq(il[222]) - , main_sel_op_external_call(il[223]) - , main_sel_op_external_return(il[224]) - , main_sel_op_external_revert(il[225]) - , main_sel_op_fdiv(il[226]) - , main_sel_op_fee_per_da_gas(il[227]) - , main_sel_op_fee_per_l2_gas(il[228]) - , main_sel_op_function_selector(il[229]) - , main_sel_op_get_contract_instance(il[230]) - , main_sel_op_internal_call(il[231]) - , main_sel_op_internal_return(il[232]) - , main_sel_op_is_static_call(il[233]) - , main_sel_op_jump(il[234]) - , main_sel_op_jumpi(il[235]) - , main_sel_op_keccak(il[236]) - , main_sel_op_l1_to_l2_msg_exists(il[237]) - , main_sel_op_l2gasleft(il[238]) - , main_sel_op_lt(il[239]) - , main_sel_op_lte(il[240]) - , main_sel_op_mov(il[241]) - , main_sel_op_msm(il[242]) - , main_sel_op_mul(il[243]) - , main_sel_op_not(il[244]) - , main_sel_op_note_hash_exists(il[245]) - , main_sel_op_nullifier_exists(il[246]) - , main_sel_op_or(il[247]) - , main_sel_op_poseidon2(il[248]) - , main_sel_op_radix_be(il[249]) - , main_sel_op_returndata_copy(il[250]) - , main_sel_op_returndata_size(il[251]) - , main_sel_op_sender(il[252]) - , main_sel_op_set(il[253]) - , main_sel_op_sha256(il[254]) - , main_sel_op_shl(il[255]) - , main_sel_op_shr(il[256]) - , main_sel_op_sload(il[257]) - , main_sel_op_sstore(il[258]) - , main_sel_op_static_call(il[259]) - , main_sel_op_sub(il[260]) - , main_sel_op_timestamp(il[261]) - , main_sel_op_transaction_fee(il[262]) - , main_sel_op_version(il[263]) - , main_sel_op_xor(il[264]) - , main_sel_q_kernel_lookup(il[265]) - , main_sel_q_kernel_output_lookup(il[266]) - , main_sel_resolve_ind_addr_a(il[267]) - , main_sel_resolve_ind_addr_b(il[268]) - , main_sel_resolve_ind_addr_c(il[269]) - , main_sel_resolve_ind_addr_d(il[270]) - , main_sel_returndata(il[271]) - , main_sel_rng_16(il[272]) - , main_sel_rng_8(il[273]) - , main_sel_slice_gadget(il[274]) - , main_side_effect_counter(il[275]) - , main_sload_write_offset(il[276]) - , main_space_id(il[277]) - , main_sstore_write_offset(il[278]) - , main_tag_err(il[279]) - , main_w_in_tag(il[280]) - , mem_addr(il[281]) - , mem_clk(il[282]) - , mem_diff(il[283]) - , mem_glob_addr(il[284]) - , mem_last(il[285]) - , mem_lastAccess(il[286]) - , mem_one_min_inv(il[287]) - , mem_r_in_tag(il[288]) - , mem_rw(il[289]) - , mem_sel_mem(il[290]) - , mem_sel_mov_ia_to_ic(il[291]) - , mem_sel_mov_ib_to_ic(il[292]) - , mem_sel_op_a(il[293]) - , mem_sel_op_b(il[294]) - , mem_sel_op_c(il[295]) - , mem_sel_op_d(il[296]) - , mem_sel_op_poseidon_read_a(il[297]) - , mem_sel_op_poseidon_read_b(il[298]) - , mem_sel_op_poseidon_read_c(il[299]) - , mem_sel_op_poseidon_read_d(il[300]) - , mem_sel_op_poseidon_write_a(il[301]) - , mem_sel_op_poseidon_write_b(il[302]) - , mem_sel_op_poseidon_write_c(il[303]) - , mem_sel_op_poseidon_write_d(il[304]) - , mem_sel_op_slice(il[305]) - , mem_sel_resolve_ind_addr_a(il[306]) - , mem_sel_resolve_ind_addr_b(il[307]) - , mem_sel_resolve_ind_addr_c(il[308]) - , mem_sel_resolve_ind_addr_d(il[309]) - , mem_sel_rng_chk(il[310]) - , mem_skip_check_tag(il[311]) - , mem_space_id(il[312]) - , mem_tag(il[313]) - , mem_tag_err(il[314]) - , mem_tsp(il[315]) - , mem_u16_r0(il[316]) - , mem_u16_r1(il[317]) - , mem_u8_r0(il[318]) - , mem_val(il[319]) - , mem_w_in_tag(il[320]) - , merkle_tree_clk(il[321]) - , merkle_tree_expected_tree_root(il[322]) - , merkle_tree_latch(il[323]) - , merkle_tree_leaf_index(il[324]) - , merkle_tree_leaf_index_is_even(il[325]) - , merkle_tree_leaf_value(il[326]) - , merkle_tree_left_hash(il[327]) - , merkle_tree_output_hash(il[328]) - , merkle_tree_path_len(il[329]) - , merkle_tree_path_len_inv(il[330]) - , merkle_tree_right_hash(il[331]) - , merkle_tree_sel_merkle_tree(il[332]) - , merkle_tree_sibling_value(il[333]) - , poseidon2_B_10_0(il[334]) - , poseidon2_B_10_1(il[335]) - , poseidon2_B_10_2(il[336]) - , poseidon2_B_10_3(il[337]) - , poseidon2_B_11_0(il[338]) - , poseidon2_B_11_1(il[339]) - , poseidon2_B_11_2(il[340]) - , poseidon2_B_11_3(il[341]) - , poseidon2_B_12_0(il[342]) - , poseidon2_B_12_1(il[343]) - , poseidon2_B_12_2(il[344]) - , poseidon2_B_12_3(il[345]) - , poseidon2_B_13_0(il[346]) - , poseidon2_B_13_1(il[347]) - , poseidon2_B_13_2(il[348]) - , poseidon2_B_13_3(il[349]) - , poseidon2_B_14_0(il[350]) - , poseidon2_B_14_1(il[351]) - , poseidon2_B_14_2(il[352]) - , poseidon2_B_14_3(il[353]) - , poseidon2_B_15_0(il[354]) - , poseidon2_B_15_1(il[355]) - , poseidon2_B_15_2(il[356]) - , poseidon2_B_15_3(il[357]) - , poseidon2_B_16_0(il[358]) - , poseidon2_B_16_1(il[359]) - , poseidon2_B_16_2(il[360]) - , poseidon2_B_16_3(il[361]) - , poseidon2_B_17_0(il[362]) - , poseidon2_B_17_1(il[363]) - , poseidon2_B_17_2(il[364]) - , poseidon2_B_17_3(il[365]) - , poseidon2_B_18_0(il[366]) - , poseidon2_B_18_1(il[367]) - , poseidon2_B_18_2(il[368]) - , poseidon2_B_18_3(il[369]) - , poseidon2_B_19_0(il[370]) - , poseidon2_B_19_1(il[371]) - , poseidon2_B_19_2(il[372]) - , poseidon2_B_19_3(il[373]) - , poseidon2_B_20_0(il[374]) - , poseidon2_B_20_1(il[375]) - , poseidon2_B_20_2(il[376]) - , poseidon2_B_20_3(il[377]) - , poseidon2_B_21_0(il[378]) - , poseidon2_B_21_1(il[379]) - , poseidon2_B_21_2(il[380]) - , poseidon2_B_21_3(il[381]) - , poseidon2_B_22_0(il[382]) - , poseidon2_B_22_1(il[383]) - , poseidon2_B_22_2(il[384]) - , poseidon2_B_22_3(il[385]) - , poseidon2_B_23_0(il[386]) - , poseidon2_B_23_1(il[387]) - , poseidon2_B_23_2(il[388]) - , poseidon2_B_23_3(il[389]) - , poseidon2_B_24_0(il[390]) - , poseidon2_B_24_1(il[391]) - , poseidon2_B_24_2(il[392]) - , poseidon2_B_24_3(il[393]) - , poseidon2_B_25_0(il[394]) - , poseidon2_B_25_1(il[395]) - , poseidon2_B_25_2(il[396]) - , poseidon2_B_25_3(il[397]) - , poseidon2_B_26_0(il[398]) - , poseidon2_B_26_1(il[399]) - , poseidon2_B_26_2(il[400]) - , poseidon2_B_26_3(il[401]) - , poseidon2_B_27_0(il[402]) - , poseidon2_B_27_1(il[403]) - , poseidon2_B_27_2(il[404]) - , poseidon2_B_27_3(il[405]) - , poseidon2_B_28_0(il[406]) - , poseidon2_B_28_1(il[407]) - , poseidon2_B_28_2(il[408]) - , poseidon2_B_28_3(il[409]) - , poseidon2_B_29_0(il[410]) - , poseidon2_B_29_1(il[411]) - , poseidon2_B_29_2(il[412]) - , poseidon2_B_29_3(il[413]) - , poseidon2_B_30_0(il[414]) - , poseidon2_B_30_1(il[415]) - , poseidon2_B_30_2(il[416]) - , poseidon2_B_30_3(il[417]) - , poseidon2_B_31_0(il[418]) - , poseidon2_B_31_1(il[419]) - , poseidon2_B_31_2(il[420]) - , poseidon2_B_31_3(il[421]) - , poseidon2_B_32_0(il[422]) - , poseidon2_B_32_1(il[423]) - , poseidon2_B_32_2(il[424]) - , poseidon2_B_32_3(il[425]) - , poseidon2_B_33_0(il[426]) - , poseidon2_B_33_1(il[427]) - , poseidon2_B_33_2(il[428]) - , poseidon2_B_33_3(il[429]) - , poseidon2_B_34_0(il[430]) - , poseidon2_B_34_1(il[431]) - , poseidon2_B_34_2(il[432]) - , poseidon2_B_34_3(il[433]) - , poseidon2_B_35_0(il[434]) - , poseidon2_B_35_1(il[435]) - , poseidon2_B_35_2(il[436]) - , poseidon2_B_35_3(il[437]) - , poseidon2_B_36_0(il[438]) - , poseidon2_B_36_1(il[439]) - , poseidon2_B_36_2(il[440]) - , poseidon2_B_36_3(il[441]) - , poseidon2_B_37_0(il[442]) - , poseidon2_B_37_1(il[443]) - , poseidon2_B_37_2(il[444]) - , poseidon2_B_37_3(il[445]) - , poseidon2_B_38_0(il[446]) - , poseidon2_B_38_1(il[447]) - , poseidon2_B_38_2(il[448]) - , poseidon2_B_38_3(il[449]) - , poseidon2_B_39_0(il[450]) - , poseidon2_B_39_1(il[451]) - , poseidon2_B_39_2(il[452]) - , poseidon2_B_39_3(il[453]) - , poseidon2_B_40_0(il[454]) - , poseidon2_B_40_1(il[455]) - , poseidon2_B_40_2(il[456]) - , poseidon2_B_40_3(il[457]) - , poseidon2_B_41_0(il[458]) - , poseidon2_B_41_1(il[459]) - , poseidon2_B_41_2(il[460]) - , poseidon2_B_41_3(il[461]) - , poseidon2_B_42_0(il[462]) - , poseidon2_B_42_1(il[463]) - , poseidon2_B_42_2(il[464]) - , poseidon2_B_42_3(il[465]) - , poseidon2_B_43_0(il[466]) - , poseidon2_B_43_1(il[467]) - , poseidon2_B_43_2(il[468]) - , poseidon2_B_43_3(il[469]) - , poseidon2_B_44_0(il[470]) - , poseidon2_B_44_1(il[471]) - , poseidon2_B_44_2(il[472]) - , poseidon2_B_44_3(il[473]) - , poseidon2_B_45_0(il[474]) - , poseidon2_B_45_1(il[475]) - , poseidon2_B_45_2(il[476]) - , poseidon2_B_45_3(il[477]) - , poseidon2_B_46_0(il[478]) - , poseidon2_B_46_1(il[479]) - , poseidon2_B_46_2(il[480]) - , poseidon2_B_46_3(il[481]) - , poseidon2_B_47_0(il[482]) - , poseidon2_B_47_1(il[483]) - , poseidon2_B_47_2(il[484]) - , poseidon2_B_47_3(il[485]) - , poseidon2_B_48_0(il[486]) - , poseidon2_B_48_1(il[487]) - , poseidon2_B_48_2(il[488]) - , poseidon2_B_48_3(il[489]) - , poseidon2_B_49_0(il[490]) - , poseidon2_B_49_1(il[491]) - , poseidon2_B_49_2(il[492]) - , poseidon2_B_49_3(il[493]) - , poseidon2_B_4_0(il[494]) - , poseidon2_B_4_1(il[495]) - , poseidon2_B_4_2(il[496]) - , poseidon2_B_4_3(il[497]) - , poseidon2_B_50_0(il[498]) - , poseidon2_B_50_1(il[499]) - , poseidon2_B_50_2(il[500]) - , poseidon2_B_50_3(il[501]) - , poseidon2_B_51_0(il[502]) - , poseidon2_B_51_1(il[503]) - , poseidon2_B_51_2(il[504]) - , poseidon2_B_51_3(il[505]) - , poseidon2_B_52_0(il[506]) - , poseidon2_B_52_1(il[507]) - , poseidon2_B_52_2(il[508]) - , poseidon2_B_52_3(il[509]) - , poseidon2_B_53_0(il[510]) - , poseidon2_B_53_1(il[511]) - , poseidon2_B_53_2(il[512]) - , poseidon2_B_53_3(il[513]) - , poseidon2_B_54_0(il[514]) - , poseidon2_B_54_1(il[515]) - , poseidon2_B_54_2(il[516]) - , poseidon2_B_54_3(il[517]) - , poseidon2_B_55_0(il[518]) - , poseidon2_B_55_1(il[519]) - , poseidon2_B_55_2(il[520]) - , poseidon2_B_55_3(il[521]) - , poseidon2_B_56_0(il[522]) - , poseidon2_B_56_1(il[523]) - , poseidon2_B_56_2(il[524]) - , poseidon2_B_56_3(il[525]) - , poseidon2_B_57_0(il[526]) - , poseidon2_B_57_1(il[527]) - , poseidon2_B_57_2(il[528]) - , poseidon2_B_57_3(il[529]) - , poseidon2_B_58_0(il[530]) - , poseidon2_B_58_1(il[531]) - , poseidon2_B_58_2(il[532]) - , poseidon2_B_58_3(il[533]) - , poseidon2_B_59_0(il[534]) - , poseidon2_B_59_1(il[535]) - , poseidon2_B_59_2(il[536]) - , poseidon2_B_59_3(il[537]) - , poseidon2_B_5_0(il[538]) - , poseidon2_B_5_1(il[539]) - , poseidon2_B_5_2(il[540]) - , poseidon2_B_5_3(il[541]) - , poseidon2_B_6_0(il[542]) - , poseidon2_B_6_1(il[543]) - , poseidon2_B_6_2(il[544]) - , poseidon2_B_6_3(il[545]) - , poseidon2_B_7_0(il[546]) - , poseidon2_B_7_1(il[547]) - , poseidon2_B_7_2(il[548]) - , poseidon2_B_7_3(il[549]) - , poseidon2_B_8_0(il[550]) - , poseidon2_B_8_1(il[551]) - , poseidon2_B_8_2(il[552]) - , poseidon2_B_8_3(il[553]) - , poseidon2_B_9_0(il[554]) - , poseidon2_B_9_1(il[555]) - , poseidon2_B_9_2(il[556]) - , poseidon2_B_9_3(il[557]) - , poseidon2_EXT_LAYER_4(il[558]) - , poseidon2_EXT_LAYER_5(il[559]) - , poseidon2_EXT_LAYER_6(il[560]) - , poseidon2_EXT_LAYER_7(il[561]) - , poseidon2_T_0_4(il[562]) - , poseidon2_T_0_5(il[563]) - , poseidon2_T_0_6(il[564]) - , poseidon2_T_0_7(il[565]) - , poseidon2_T_1_4(il[566]) - , poseidon2_T_1_5(il[567]) - , poseidon2_T_1_6(il[568]) - , poseidon2_T_1_7(il[569]) - , poseidon2_T_2_4(il[570]) - , poseidon2_T_2_5(il[571]) - , poseidon2_T_2_6(il[572]) - , poseidon2_T_2_7(il[573]) - , poseidon2_T_3_4(il[574]) - , poseidon2_T_3_5(il[575]) - , poseidon2_T_3_6(il[576]) - , poseidon2_T_3_7(il[577]) - , poseidon2_T_60_4(il[578]) - , poseidon2_T_60_5(il[579]) - , poseidon2_T_60_6(il[580]) - , poseidon2_T_60_7(il[581]) - , poseidon2_T_61_4(il[582]) - , poseidon2_T_61_5(il[583]) - , poseidon2_T_61_6(il[584]) - , poseidon2_T_61_7(il[585]) - , poseidon2_T_62_4(il[586]) - , poseidon2_T_62_5(il[587]) - , poseidon2_T_62_6(il[588]) - , poseidon2_T_62_7(il[589]) - , poseidon2_T_63_4(il[590]) - , poseidon2_T_63_5(il[591]) - , poseidon2_T_63_6(il[592]) - , poseidon2_T_63_7(il[593]) - , poseidon2_a_0(il[594]) - , poseidon2_a_1(il[595]) - , poseidon2_a_2(il[596]) - , poseidon2_a_3(il[597]) - , poseidon2_b_0(il[598]) - , poseidon2_b_1(il[599]) - , poseidon2_b_2(il[600]) - , poseidon2_b_3(il[601]) - , poseidon2_clk(il[602]) - , poseidon2_full_a_0(il[603]) - , poseidon2_full_a_1(il[604]) - , poseidon2_full_a_2(il[605]) - , poseidon2_full_a_3(il[606]) - , poseidon2_full_b_0(il[607]) - , poseidon2_full_b_1(il[608]) - , poseidon2_full_b_2(il[609]) - , poseidon2_full_b_3(il[610]) - , poseidon2_full_clk(il[611]) - , poseidon2_full_end_poseidon(il[612]) - , poseidon2_full_execute_poseidon_perm(il[613]) - , poseidon2_full_input_0(il[614]) - , poseidon2_full_input_1(il[615]) - , poseidon2_full_input_2(il[616]) - , poseidon2_full_input_len(il[617]) - , poseidon2_full_num_perm_rounds_rem(il[618]) - , poseidon2_full_num_perm_rounds_rem_inv(il[619]) - , poseidon2_full_output(il[620]) - , poseidon2_full_padding(il[621]) - , poseidon2_full_sel_merkle_tree(il[622]) - , poseidon2_full_sel_poseidon(il[623]) - , poseidon2_full_start_poseidon(il[624]) - , poseidon2_input_addr(il[625]) - , poseidon2_mem_addr_read_a(il[626]) - , poseidon2_mem_addr_read_b(il[627]) - , poseidon2_mem_addr_read_c(il[628]) - , poseidon2_mem_addr_read_d(il[629]) - , poseidon2_mem_addr_write_a(il[630]) - , poseidon2_mem_addr_write_b(il[631]) - , poseidon2_mem_addr_write_c(il[632]) - , poseidon2_mem_addr_write_d(il[633]) - , poseidon2_output_addr(il[634]) - , poseidon2_sel_poseidon_perm(il[635]) - , poseidon2_sel_poseidon_perm_immediate(il[636]) - , poseidon2_sel_poseidon_perm_mem_op(il[637]) - , poseidon2_space_id(il[638]) - , range_check_alu_rng_chk(il[639]) - , range_check_clk(il[640]) - , range_check_cmp_hi_bits_rng_chk(il[641]) - , range_check_cmp_lo_bits_rng_chk(il[642]) - , range_check_dyn_diff(il[643]) - , range_check_dyn_rng_chk_bits(il[644]) - , range_check_dyn_rng_chk_pow_2(il[645]) - , range_check_gas_da_rng_chk(il[646]) - , range_check_gas_l2_rng_chk(il[647]) - , range_check_is_lte_u112(il[648]) - , range_check_is_lte_u128(il[649]) - , range_check_is_lte_u16(il[650]) - , range_check_is_lte_u32(il[651]) - , range_check_is_lte_u48(il[652]) - , range_check_is_lte_u64(il[653]) - , range_check_is_lte_u80(il[654]) - , range_check_is_lte_u96(il[655]) - , range_check_rng_chk_bits(il[656]) - , range_check_sel_lookup_0(il[657]) - , range_check_sel_lookup_1(il[658]) - , range_check_sel_lookup_2(il[659]) - , range_check_sel_lookup_3(il[660]) - , range_check_sel_lookup_4(il[661]) - , range_check_sel_lookup_5(il[662]) - , range_check_sel_lookup_6(il[663]) - , range_check_sel_rng_chk(il[664]) - , range_check_u16_r0(il[665]) - , range_check_u16_r1(il[666]) - , range_check_u16_r2(il[667]) - , range_check_u16_r3(il[668]) - , range_check_u16_r4(il[669]) - , range_check_u16_r5(il[670]) - , range_check_u16_r6(il[671]) - , range_check_u16_r7(il[672]) - , range_check_value(il[673]) - , sha256_clk(il[674]) - , sha256_input(il[675]) - , sha256_output(il[676]) - , sha256_sel_sha256_compression(il[677]) - , sha256_state(il[678]) - , slice_addr(il[679]) - , slice_clk(il[680]) - , slice_cnt(il[681]) - , slice_col_offset(il[682]) - , slice_one_min_inv(il[683]) - , slice_sel_cd_cpy(il[684]) - , slice_sel_mem_active(il[685]) - , slice_sel_return(il[686]) - , slice_sel_start(il[687]) - , slice_space_id(il[688]) - , slice_val(il[689]) - , lookup_rng_chk_pow_2_counts(il[690]) - , lookup_rng_chk_diff_counts(il[691]) - , lookup_rng_chk_0_counts(il[692]) - , lookup_rng_chk_1_counts(il[693]) - , lookup_rng_chk_2_counts(il[694]) - , lookup_rng_chk_3_counts(il[695]) - , lookup_rng_chk_4_counts(il[696]) - , lookup_rng_chk_5_counts(il[697]) - , lookup_rng_chk_6_counts(il[698]) - , lookup_rng_chk_7_counts(il[699]) - , lookup_mem_rng_chk_0_counts(il[700]) - , lookup_mem_rng_chk_1_counts(il[701]) - , lookup_mem_rng_chk_2_counts(il[702]) - , lookup_pow_2_0_counts(il[703]) - , lookup_pow_2_1_counts(il[704]) - , lookup_byte_lengths_counts(il[705]) - , lookup_byte_operations_counts(il[706]) - , lookup_opcode_gas_counts(il[707]) - , kernel_output_lookup_counts(il[708]) - , lookup_into_kernel_counts(il[709]) - , lookup_cd_value_counts(il[710]) - , lookup_ret_value_counts(il[711]) - , incl_main_tag_err_counts(il[712]) - , incl_mem_tag_err_counts(il[713]) - , perm_rng_cmp_lo_inv(il[714]) - , perm_rng_cmp_hi_inv(il[715]) - , perm_rng_alu_inv(il[716]) - , perm_cmp_alu_inv(il[717]) - , perm_rng_gas_l2_inv(il[718]) - , perm_rng_gas_da_inv(il[719]) - , perm_l2_start_gas_inv(il[720]) - , perm_da_start_gas_inv(il[721]) - , perm_l2_end_gas_inv(il[722]) - , perm_da_end_gas_inv(il[723]) - , perm_pos_mem_read_a_inv(il[724]) - , perm_pos_mem_read_b_inv(il[725]) - , perm_pos_mem_read_c_inv(il[726]) - , perm_pos_mem_read_d_inv(il[727]) - , perm_pos_mem_write_a_inv(il[728]) - , perm_pos_mem_write_b_inv(il[729]) - , perm_pos_mem_write_c_inv(il[730]) - , perm_pos_mem_write_d_inv(il[731]) - , perm_pos2_fixed_pos2_perm_inv(il[732]) - , perm_slice_mem_inv(il[733]) - , perm_merkle_poseidon2_inv(il[734]) - , perm_main_alu_inv(il[735]) - , perm_main_bin_inv(il[736]) - , perm_main_conv_inv(il[737]) - , perm_main_sha256_inv(il[738]) - , perm_main_pos2_perm_inv(il[739]) - , perm_main_slice_inv(il[740]) - , perm_main_mem_a_inv(il[741]) - , perm_main_mem_b_inv(il[742]) - , perm_main_mem_c_inv(il[743]) - , perm_main_mem_d_inv(il[744]) - , perm_main_mem_ind_addr_a_inv(il[745]) - , perm_main_mem_ind_addr_b_inv(il[746]) - , perm_main_mem_ind_addr_c_inv(il[747]) - , perm_main_mem_ind_addr_d_inv(il[748]) - , lookup_rng_chk_pow_2_inv(il[749]) - , lookup_rng_chk_diff_inv(il[750]) - , lookup_rng_chk_0_inv(il[751]) - , lookup_rng_chk_1_inv(il[752]) - , lookup_rng_chk_2_inv(il[753]) - , lookup_rng_chk_3_inv(il[754]) - , lookup_rng_chk_4_inv(il[755]) - , lookup_rng_chk_5_inv(il[756]) - , lookup_rng_chk_6_inv(il[757]) - , lookup_rng_chk_7_inv(il[758]) - , lookup_mem_rng_chk_0_inv(il[759]) - , lookup_mem_rng_chk_1_inv(il[760]) - , lookup_mem_rng_chk_2_inv(il[761]) - , lookup_pow_2_0_inv(il[762]) - , lookup_pow_2_1_inv(il[763]) - , lookup_byte_lengths_inv(il[764]) - , lookup_byte_operations_inv(il[765]) - , lookup_opcode_gas_inv(il[766]) - , kernel_output_lookup_inv(il[767]) - , lookup_into_kernel_inv(il[768]) - , lookup_cd_value_inv(il[769]) - , lookup_ret_value_inv(il[770]) - , incl_main_tag_err_inv(il[771]) - , incl_mem_tag_err_inv(il[772]) - , binary_acc_ia_shift(il[773]) - , binary_acc_ib_shift(il[774]) - , binary_acc_ic_shift(il[775]) - , binary_mem_tag_ctr_shift(il[776]) - , binary_op_id_shift(il[777]) - , cmp_a_hi_shift(il[778]) - , cmp_a_lo_shift(il[779]) - , cmp_b_hi_shift(il[780]) - , cmp_b_lo_shift(il[781]) - , cmp_cmp_rng_ctr_shift(il[782]) - , cmp_op_gt_shift(il[783]) - , cmp_p_sub_a_hi_shift(il[784]) - , cmp_p_sub_a_lo_shift(il[785]) - , cmp_p_sub_b_hi_shift(il[786]) - , cmp_p_sub_b_lo_shift(il[787]) - , cmp_sel_rng_chk_shift(il[788]) - , main_da_gas_remaining_shift(il[789]) - , main_emit_l2_to_l1_msg_write_offset_shift(il[790]) - , main_emit_note_hash_write_offset_shift(il[791]) - , main_emit_nullifier_write_offset_shift(il[792]) - , main_emit_unencrypted_log_write_offset_shift(il[793]) - , main_internal_return_ptr_shift(il[794]) - , main_l1_to_l2_msg_exists_write_offset_shift(il[795]) - , main_l2_gas_remaining_shift(il[796]) - , main_note_hash_exist_write_offset_shift(il[797]) - , main_nullifier_exists_write_offset_shift(il[798]) - , main_nullifier_non_exists_write_offset_shift(il[799]) - , main_pc_shift(il[800]) - , main_sel_execution_end_shift(il[801]) - , main_sel_execution_row_shift(il[802]) - , main_sload_write_offset_shift(il[803]) - , main_sstore_write_offset_shift(il[804]) - , mem_glob_addr_shift(il[805]) - , mem_rw_shift(il[806]) - , mem_sel_mem_shift(il[807]) - , mem_tag_shift(il[808]) - , mem_tsp_shift(il[809]) - , mem_val_shift(il[810]) - , merkle_tree_leaf_index_shift(il[811]) - , merkle_tree_leaf_value_shift(il[812]) - , merkle_tree_path_len_shift(il[813]) - , poseidon2_full_a_0_shift(il[814]) - , poseidon2_full_a_1_shift(il[815]) - , poseidon2_full_a_2_shift(il[816]) - , poseidon2_full_a_3_shift(il[817]) - , poseidon2_full_execute_poseidon_perm_shift(il[818]) - , poseidon2_full_input_0_shift(il[819]) - , poseidon2_full_input_1_shift(il[820]) - , poseidon2_full_input_2_shift(il[821]) - , poseidon2_full_num_perm_rounds_rem_shift(il[822]) - , poseidon2_full_sel_poseidon_shift(il[823]) - , poseidon2_full_start_poseidon_shift(il[824]) - , slice_addr_shift(il[825]) - , slice_clk_shift(il[826]) - , slice_cnt_shift(il[827]) - , slice_col_offset_shift(il[828]) - , slice_sel_cd_cpy_shift(il[829]) - , slice_sel_mem_active_shift(il[830]) - , slice_sel_return_shift(il[831]) - , slice_sel_start_shift(il[832]) - , slice_space_id_shift(il[833]) + , alu_cmp_gadget_non_ff_gt(il[39]) + , alu_cmp_gadget_result(il[40]) + , alu_cmp_gadget_sel(il[41]) + , alu_ff_tag(il[42]) + , alu_ia(il[43]) + , alu_ib(il[44]) + , alu_ic(il[45]) + , alu_in_tag(il[46]) + , alu_max_bits_sub_b_bits(il[47]) + , alu_max_bits_sub_b_pow(il[48]) + , alu_op_add(il[49]) + , alu_op_cast(il[50]) + , alu_op_div(il[51]) + , alu_op_eq(il[52]) + , alu_op_lt(il[53]) + , alu_op_lte(il[54]) + , alu_op_mul(il[55]) + , alu_op_not(il[56]) + , alu_op_shl(il[57]) + , alu_op_shr(il[58]) + , alu_op_sub(il[59]) + , alu_partial_prod_hi(il[60]) + , alu_partial_prod_lo(il[61]) + , alu_range_check_input_value(il[62]) + , alu_range_check_num_bits(il[63]) + , alu_range_check_sel(il[64]) + , alu_remainder(il[65]) + , alu_sel_alu(il[66]) + , alu_sel_cmp(il[67]) + , alu_sel_shift_which(il[68]) + , alu_u128_tag(il[69]) + , alu_u16_tag(il[70]) + , alu_u1_tag(il[71]) + , alu_u32_tag(il[72]) + , alu_u64_tag(il[73]) + , alu_u8_tag(il[74]) + , alu_zero_shift(il[75]) + , binary_acc_ia(il[76]) + , binary_acc_ib(il[77]) + , binary_acc_ic(il[78]) + , binary_clk(il[79]) + , binary_ia_bytes(il[80]) + , binary_ib_bytes(il[81]) + , binary_ic_bytes(il[82]) + , binary_in_tag(il[83]) + , binary_mem_tag_ctr(il[84]) + , binary_mem_tag_ctr_inv(il[85]) + , binary_op_id(il[86]) + , binary_sel_bin(il[87]) + , binary_start(il[88]) + , bytecode_arifact_hash(il[89]) + , bytecode_as_fields(il[90]) + , bytecode_bytes(il[91]) + , bytecode_bytes_pc(il[92]) + , bytecode_class_id(il[93]) + , bytecode_contract_address(il[94]) + , bytecode_decomposed(il[95]) + , bytecode_deployer_addr(il[96]) + , bytecode_end_latch(il[97]) + , bytecode_incoming_viewing_key_x(il[98]) + , bytecode_incoming_viewing_key_y(il[99]) + , bytecode_initialization_hash(il[100]) + , bytecode_length_remaining(il[101]) + , bytecode_nullifier_key_x(il[102]) + , bytecode_nullifier_key_y(il[103]) + , bytecode_outgoing_viewing_key_x(il[104]) + , bytecode_outgoing_viewing_key_y(il[105]) + , bytecode_private_fn_root(il[106]) + , bytecode_public_key_hash(il[107]) + , bytecode_running_hash(il[108]) + , bytecode_salt(il[109]) + , bytecode_tagging_key_x(il[110]) + , bytecode_tagging_key_y(il[111]) + , cmp_a_hi(il[112]) + , cmp_a_lo(il[113]) + , cmp_b_hi(il[114]) + , cmp_b_lo(il[115]) + , cmp_borrow(il[116]) + , cmp_clk(il[117]) + , cmp_cmp_rng_ctr(il[118]) + , cmp_diff(il[119]) + , cmp_input_a(il[120]) + , cmp_input_b(il[121]) + , cmp_op_eq(il[122]) + , cmp_op_eq_diff_inv(il[123]) + , cmp_op_gt(il[124]) + , cmp_op_non_ff_gt(il[125]) + , cmp_p_a_borrow(il[126]) + , cmp_p_b_borrow(il[127]) + , cmp_p_sub_a_hi(il[128]) + , cmp_p_sub_a_lo(il[129]) + , cmp_p_sub_b_hi(il[130]) + , cmp_p_sub_b_lo(il[131]) + , cmp_range_chk_clk(il[132]) + , cmp_res_hi(il[133]) + , cmp_res_lo(il[134]) + , cmp_result(il[135]) + , cmp_sel_cmp(il[136]) + , cmp_sel_rng_chk(il[137]) + , cmp_shift_sel(il[138]) + , conversion_clk(il[139]) + , conversion_input(il[140]) + , conversion_num_limbs(il[141]) + , conversion_output_bits(il[142]) + , conversion_radix(il[143]) + , conversion_sel_to_radix_be(il[144]) + , keccakf1600_clk(il[145]) + , keccakf1600_input(il[146]) + , keccakf1600_output(il[147]) + , keccakf1600_sel_keccakf1600(il[148]) + , main_abs_da_rem_gas(il[149]) + , main_abs_l2_rem_gas(il[150]) + , main_alu_in_tag(il[151]) + , main_base_da_gas_op_cost(il[152]) + , main_base_l2_gas_op_cost(il[153]) + , main_bin_op_id(il[154]) + , main_call_ptr(il[155]) + , main_da_gas_remaining(il[156]) + , main_da_gas_u16_r0(il[157]) + , main_da_gas_u16_r1(il[158]) + , main_da_out_of_gas(il[159]) + , main_dyn_da_gas_op_cost(il[160]) + , main_dyn_gas_multiplier(il[161]) + , main_dyn_l2_gas_op_cost(il[162]) + , main_emit_l2_to_l1_msg_write_offset(il[163]) + , main_emit_note_hash_write_offset(il[164]) + , main_emit_nullifier_write_offset(il[165]) + , main_emit_unencrypted_log_write_offset(il[166]) + , main_ia(il[167]) + , main_ib(il[168]) + , main_ic(il[169]) + , main_id(il[170]) + , main_id_zero(il[171]) + , main_ind_addr_a(il[172]) + , main_ind_addr_b(il[173]) + , main_ind_addr_c(il[174]) + , main_ind_addr_d(il[175]) + , main_internal_return_ptr(il[176]) + , main_inv(il[177]) + , main_is_fake_row(il[178]) + , main_is_gas_accounted(il[179]) + , main_kernel_in_offset(il[180]) + , main_kernel_out_offset(il[181]) + , main_l1_to_l2_msg_exists_write_offset(il[182]) + , main_l2_gas_remaining(il[183]) + , main_l2_gas_u16_r0(il[184]) + , main_l2_gas_u16_r1(il[185]) + , main_l2_out_of_gas(il[186]) + , main_mem_addr_a(il[187]) + , main_mem_addr_b(il[188]) + , main_mem_addr_c(il[189]) + , main_mem_addr_d(il[190]) + , main_note_hash_exist_write_offset(il[191]) + , main_nullifier_exists_write_offset(il[192]) + , main_nullifier_non_exists_write_offset(il[193]) + , main_op_err(il[194]) + , main_opcode_val(il[195]) + , main_pc(il[196]) + , main_r_in_tag(il[197]) + , main_rwa(il[198]) + , main_rwb(il[199]) + , main_rwc(il[200]) + , main_rwd(il[201]) + , main_sel_alu(il[202]) + , main_sel_bin(il[203]) + , main_sel_calldata(il[204]) + , main_sel_execution_end(il[205]) + , main_sel_execution_row(il[206]) + , main_sel_kernel_inputs(il[207]) + , main_sel_kernel_out(il[208]) + , main_sel_mem_op_a(il[209]) + , main_sel_mem_op_b(il[210]) + , main_sel_mem_op_c(il[211]) + , main_sel_mem_op_d(il[212]) + , main_sel_mov_ia_to_ic(il[213]) + , main_sel_mov_ib_to_ic(il[214]) + , main_sel_op_add(il[215]) + , main_sel_op_address(il[216]) + , main_sel_op_and(il[217]) + , main_sel_op_block_number(il[218]) + , main_sel_op_calldata_copy(il[219]) + , main_sel_op_cast(il[220]) + , main_sel_op_chain_id(il[221]) + , main_sel_op_dagasleft(il[222]) + , main_sel_op_debug_log(il[223]) + , main_sel_op_div(il[224]) + , main_sel_op_ecadd(il[225]) + , main_sel_op_emit_l2_to_l1_msg(il[226]) + , main_sel_op_emit_note_hash(il[227]) + , main_sel_op_emit_nullifier(il[228]) + , main_sel_op_emit_unencrypted_log(il[229]) + , main_sel_op_eq(il[230]) + , main_sel_op_external_call(il[231]) + , main_sel_op_external_return(il[232]) + , main_sel_op_external_revert(il[233]) + , main_sel_op_fdiv(il[234]) + , main_sel_op_fee_per_da_gas(il[235]) + , main_sel_op_fee_per_l2_gas(il[236]) + , main_sel_op_function_selector(il[237]) + , main_sel_op_get_contract_instance(il[238]) + , main_sel_op_internal_call(il[239]) + , main_sel_op_internal_return(il[240]) + , main_sel_op_is_static_call(il[241]) + , main_sel_op_jump(il[242]) + , main_sel_op_jumpi(il[243]) + , main_sel_op_keccak(il[244]) + , main_sel_op_l1_to_l2_msg_exists(il[245]) + , main_sel_op_l2gasleft(il[246]) + , main_sel_op_lt(il[247]) + , main_sel_op_lte(il[248]) + , main_sel_op_mov(il[249]) + , main_sel_op_msm(il[250]) + , main_sel_op_mul(il[251]) + , main_sel_op_not(il[252]) + , main_sel_op_note_hash_exists(il[253]) + , main_sel_op_nullifier_exists(il[254]) + , main_sel_op_or(il[255]) + , main_sel_op_poseidon2(il[256]) + , main_sel_op_radix_be(il[257]) + , main_sel_op_returndata_copy(il[258]) + , main_sel_op_returndata_size(il[259]) + , main_sel_op_sender(il[260]) + , main_sel_op_set(il[261]) + , main_sel_op_sha256(il[262]) + , main_sel_op_shl(il[263]) + , main_sel_op_shr(il[264]) + , main_sel_op_sload(il[265]) + , main_sel_op_sstore(il[266]) + , main_sel_op_static_call(il[267]) + , main_sel_op_sub(il[268]) + , main_sel_op_timestamp(il[269]) + , main_sel_op_transaction_fee(il[270]) + , main_sel_op_version(il[271]) + , main_sel_op_xor(il[272]) + , main_sel_q_kernel_lookup(il[273]) + , main_sel_q_kernel_output_lookup(il[274]) + , main_sel_resolve_ind_addr_a(il[275]) + , main_sel_resolve_ind_addr_b(il[276]) + , main_sel_resolve_ind_addr_c(il[277]) + , main_sel_resolve_ind_addr_d(il[278]) + , main_sel_returndata(il[279]) + , main_sel_rng_16(il[280]) + , main_sel_rng_8(il[281]) + , main_sel_slice_gadget(il[282]) + , main_side_effect_counter(il[283]) + , main_sload_write_offset(il[284]) + , main_space_id(il[285]) + , main_sstore_write_offset(il[286]) + , main_tag_err(il[287]) + , main_w_in_tag(il[288]) + , mem_addr(il[289]) + , mem_clk(il[290]) + , mem_diff(il[291]) + , mem_glob_addr(il[292]) + , mem_last(il[293]) + , mem_lastAccess(il[294]) + , mem_one_min_inv(il[295]) + , mem_r_in_tag(il[296]) + , mem_rw(il[297]) + , mem_sel_mem(il[298]) + , mem_sel_mov_ia_to_ic(il[299]) + , mem_sel_mov_ib_to_ic(il[300]) + , mem_sel_op_a(il[301]) + , mem_sel_op_b(il[302]) + , mem_sel_op_c(il[303]) + , mem_sel_op_d(il[304]) + , mem_sel_op_poseidon_read_a(il[305]) + , mem_sel_op_poseidon_read_b(il[306]) + , mem_sel_op_poseidon_read_c(il[307]) + , mem_sel_op_poseidon_read_d(il[308]) + , mem_sel_op_poseidon_write_a(il[309]) + , mem_sel_op_poseidon_write_b(il[310]) + , mem_sel_op_poseidon_write_c(il[311]) + , mem_sel_op_poseidon_write_d(il[312]) + , mem_sel_op_slice(il[313]) + , mem_sel_resolve_ind_addr_a(il[314]) + , mem_sel_resolve_ind_addr_b(il[315]) + , mem_sel_resolve_ind_addr_c(il[316]) + , mem_sel_resolve_ind_addr_d(il[317]) + , mem_sel_rng_chk(il[318]) + , mem_skip_check_tag(il[319]) + , mem_space_id(il[320]) + , mem_tag(il[321]) + , mem_tag_err(il[322]) + , mem_tsp(il[323]) + , mem_u16_r0(il[324]) + , mem_u16_r1(il[325]) + , mem_u8_r0(il[326]) + , mem_val(il[327]) + , mem_w_in_tag(il[328]) + , merkle_tree_clk(il[329]) + , merkle_tree_expected_tree_root(il[330]) + , merkle_tree_latch(il[331]) + , merkle_tree_leaf_index(il[332]) + , merkle_tree_leaf_index_is_even(il[333]) + , merkle_tree_leaf_value(il[334]) + , merkle_tree_left_hash(il[335]) + , merkle_tree_output_hash(il[336]) + , merkle_tree_path_len(il[337]) + , merkle_tree_path_len_inv(il[338]) + , merkle_tree_right_hash(il[339]) + , merkle_tree_sel_merkle_tree(il[340]) + , merkle_tree_sibling_value(il[341]) + , poseidon2_B_10_0(il[342]) + , poseidon2_B_10_1(il[343]) + , poseidon2_B_10_2(il[344]) + , poseidon2_B_10_3(il[345]) + , poseidon2_B_11_0(il[346]) + , poseidon2_B_11_1(il[347]) + , poseidon2_B_11_2(il[348]) + , poseidon2_B_11_3(il[349]) + , poseidon2_B_12_0(il[350]) + , poseidon2_B_12_1(il[351]) + , poseidon2_B_12_2(il[352]) + , poseidon2_B_12_3(il[353]) + , poseidon2_B_13_0(il[354]) + , poseidon2_B_13_1(il[355]) + , poseidon2_B_13_2(il[356]) + , poseidon2_B_13_3(il[357]) + , poseidon2_B_14_0(il[358]) + , poseidon2_B_14_1(il[359]) + , poseidon2_B_14_2(il[360]) + , poseidon2_B_14_3(il[361]) + , poseidon2_B_15_0(il[362]) + , poseidon2_B_15_1(il[363]) + , poseidon2_B_15_2(il[364]) + , poseidon2_B_15_3(il[365]) + , poseidon2_B_16_0(il[366]) + , poseidon2_B_16_1(il[367]) + , poseidon2_B_16_2(il[368]) + , poseidon2_B_16_3(il[369]) + , poseidon2_B_17_0(il[370]) + , poseidon2_B_17_1(il[371]) + , poseidon2_B_17_2(il[372]) + , poseidon2_B_17_3(il[373]) + , poseidon2_B_18_0(il[374]) + , poseidon2_B_18_1(il[375]) + , poseidon2_B_18_2(il[376]) + , poseidon2_B_18_3(il[377]) + , poseidon2_B_19_0(il[378]) + , poseidon2_B_19_1(il[379]) + , poseidon2_B_19_2(il[380]) + , poseidon2_B_19_3(il[381]) + , poseidon2_B_20_0(il[382]) + , poseidon2_B_20_1(il[383]) + , poseidon2_B_20_2(il[384]) + , poseidon2_B_20_3(il[385]) + , poseidon2_B_21_0(il[386]) + , poseidon2_B_21_1(il[387]) + , poseidon2_B_21_2(il[388]) + , poseidon2_B_21_3(il[389]) + , poseidon2_B_22_0(il[390]) + , poseidon2_B_22_1(il[391]) + , poseidon2_B_22_2(il[392]) + , poseidon2_B_22_3(il[393]) + , poseidon2_B_23_0(il[394]) + , poseidon2_B_23_1(il[395]) + , poseidon2_B_23_2(il[396]) + , poseidon2_B_23_3(il[397]) + , poseidon2_B_24_0(il[398]) + , poseidon2_B_24_1(il[399]) + , poseidon2_B_24_2(il[400]) + , poseidon2_B_24_3(il[401]) + , poseidon2_B_25_0(il[402]) + , poseidon2_B_25_1(il[403]) + , poseidon2_B_25_2(il[404]) + , poseidon2_B_25_3(il[405]) + , poseidon2_B_26_0(il[406]) + , poseidon2_B_26_1(il[407]) + , poseidon2_B_26_2(il[408]) + , poseidon2_B_26_3(il[409]) + , poseidon2_B_27_0(il[410]) + , poseidon2_B_27_1(il[411]) + , poseidon2_B_27_2(il[412]) + , poseidon2_B_27_3(il[413]) + , poseidon2_B_28_0(il[414]) + , poseidon2_B_28_1(il[415]) + , poseidon2_B_28_2(il[416]) + , poseidon2_B_28_3(il[417]) + , poseidon2_B_29_0(il[418]) + , poseidon2_B_29_1(il[419]) + , poseidon2_B_29_2(il[420]) + , poseidon2_B_29_3(il[421]) + , poseidon2_B_30_0(il[422]) + , poseidon2_B_30_1(il[423]) + , poseidon2_B_30_2(il[424]) + , poseidon2_B_30_3(il[425]) + , poseidon2_B_31_0(il[426]) + , poseidon2_B_31_1(il[427]) + , poseidon2_B_31_2(il[428]) + , poseidon2_B_31_3(il[429]) + , poseidon2_B_32_0(il[430]) + , poseidon2_B_32_1(il[431]) + , poseidon2_B_32_2(il[432]) + , poseidon2_B_32_3(il[433]) + , poseidon2_B_33_0(il[434]) + , poseidon2_B_33_1(il[435]) + , poseidon2_B_33_2(il[436]) + , poseidon2_B_33_3(il[437]) + , poseidon2_B_34_0(il[438]) + , poseidon2_B_34_1(il[439]) + , poseidon2_B_34_2(il[440]) + , poseidon2_B_34_3(il[441]) + , poseidon2_B_35_0(il[442]) + , poseidon2_B_35_1(il[443]) + , poseidon2_B_35_2(il[444]) + , poseidon2_B_35_3(il[445]) + , poseidon2_B_36_0(il[446]) + , poseidon2_B_36_1(il[447]) + , poseidon2_B_36_2(il[448]) + , poseidon2_B_36_3(il[449]) + , poseidon2_B_37_0(il[450]) + , poseidon2_B_37_1(il[451]) + , poseidon2_B_37_2(il[452]) + , poseidon2_B_37_3(il[453]) + , poseidon2_B_38_0(il[454]) + , poseidon2_B_38_1(il[455]) + , poseidon2_B_38_2(il[456]) + , poseidon2_B_38_3(il[457]) + , poseidon2_B_39_0(il[458]) + , poseidon2_B_39_1(il[459]) + , poseidon2_B_39_2(il[460]) + , poseidon2_B_39_3(il[461]) + , poseidon2_B_40_0(il[462]) + , poseidon2_B_40_1(il[463]) + , poseidon2_B_40_2(il[464]) + , poseidon2_B_40_3(il[465]) + , poseidon2_B_41_0(il[466]) + , poseidon2_B_41_1(il[467]) + , poseidon2_B_41_2(il[468]) + , poseidon2_B_41_3(il[469]) + , poseidon2_B_42_0(il[470]) + , poseidon2_B_42_1(il[471]) + , poseidon2_B_42_2(il[472]) + , poseidon2_B_42_3(il[473]) + , poseidon2_B_43_0(il[474]) + , poseidon2_B_43_1(il[475]) + , poseidon2_B_43_2(il[476]) + , poseidon2_B_43_3(il[477]) + , poseidon2_B_44_0(il[478]) + , poseidon2_B_44_1(il[479]) + , poseidon2_B_44_2(il[480]) + , poseidon2_B_44_3(il[481]) + , poseidon2_B_45_0(il[482]) + , poseidon2_B_45_1(il[483]) + , poseidon2_B_45_2(il[484]) + , poseidon2_B_45_3(il[485]) + , poseidon2_B_46_0(il[486]) + , poseidon2_B_46_1(il[487]) + , poseidon2_B_46_2(il[488]) + , poseidon2_B_46_3(il[489]) + , poseidon2_B_47_0(il[490]) + , poseidon2_B_47_1(il[491]) + , poseidon2_B_47_2(il[492]) + , poseidon2_B_47_3(il[493]) + , poseidon2_B_48_0(il[494]) + , poseidon2_B_48_1(il[495]) + , poseidon2_B_48_2(il[496]) + , poseidon2_B_48_3(il[497]) + , poseidon2_B_49_0(il[498]) + , poseidon2_B_49_1(il[499]) + , poseidon2_B_49_2(il[500]) + , poseidon2_B_49_3(il[501]) + , poseidon2_B_4_0(il[502]) + , poseidon2_B_4_1(il[503]) + , poseidon2_B_4_2(il[504]) + , poseidon2_B_4_3(il[505]) + , poseidon2_B_50_0(il[506]) + , poseidon2_B_50_1(il[507]) + , poseidon2_B_50_2(il[508]) + , poseidon2_B_50_3(il[509]) + , poseidon2_B_51_0(il[510]) + , poseidon2_B_51_1(il[511]) + , poseidon2_B_51_2(il[512]) + , poseidon2_B_51_3(il[513]) + , poseidon2_B_52_0(il[514]) + , poseidon2_B_52_1(il[515]) + , poseidon2_B_52_2(il[516]) + , poseidon2_B_52_3(il[517]) + , poseidon2_B_53_0(il[518]) + , poseidon2_B_53_1(il[519]) + , poseidon2_B_53_2(il[520]) + , poseidon2_B_53_3(il[521]) + , poseidon2_B_54_0(il[522]) + , poseidon2_B_54_1(il[523]) + , poseidon2_B_54_2(il[524]) + , poseidon2_B_54_3(il[525]) + , poseidon2_B_55_0(il[526]) + , poseidon2_B_55_1(il[527]) + , poseidon2_B_55_2(il[528]) + , poseidon2_B_55_3(il[529]) + , poseidon2_B_56_0(il[530]) + , poseidon2_B_56_1(il[531]) + , poseidon2_B_56_2(il[532]) + , poseidon2_B_56_3(il[533]) + , poseidon2_B_57_0(il[534]) + , poseidon2_B_57_1(il[535]) + , poseidon2_B_57_2(il[536]) + , poseidon2_B_57_3(il[537]) + , poseidon2_B_58_0(il[538]) + , poseidon2_B_58_1(il[539]) + , poseidon2_B_58_2(il[540]) + , poseidon2_B_58_3(il[541]) + , poseidon2_B_59_0(il[542]) + , poseidon2_B_59_1(il[543]) + , poseidon2_B_59_2(il[544]) + , poseidon2_B_59_3(il[545]) + , poseidon2_B_5_0(il[546]) + , poseidon2_B_5_1(il[547]) + , poseidon2_B_5_2(il[548]) + , poseidon2_B_5_3(il[549]) + , poseidon2_B_6_0(il[550]) + , poseidon2_B_6_1(il[551]) + , poseidon2_B_6_2(il[552]) + , poseidon2_B_6_3(il[553]) + , poseidon2_B_7_0(il[554]) + , poseidon2_B_7_1(il[555]) + , poseidon2_B_7_2(il[556]) + , poseidon2_B_7_3(il[557]) + , poseidon2_B_8_0(il[558]) + , poseidon2_B_8_1(il[559]) + , poseidon2_B_8_2(il[560]) + , poseidon2_B_8_3(il[561]) + , poseidon2_B_9_0(il[562]) + , poseidon2_B_9_1(il[563]) + , poseidon2_B_9_2(il[564]) + , poseidon2_B_9_3(il[565]) + , poseidon2_EXT_LAYER_4(il[566]) + , poseidon2_EXT_LAYER_5(il[567]) + , poseidon2_EXT_LAYER_6(il[568]) + , poseidon2_EXT_LAYER_7(il[569]) + , poseidon2_T_0_4(il[570]) + , poseidon2_T_0_5(il[571]) + , poseidon2_T_0_6(il[572]) + , poseidon2_T_0_7(il[573]) + , poseidon2_T_1_4(il[574]) + , poseidon2_T_1_5(il[575]) + , poseidon2_T_1_6(il[576]) + , poseidon2_T_1_7(il[577]) + , poseidon2_T_2_4(il[578]) + , poseidon2_T_2_5(il[579]) + , poseidon2_T_2_6(il[580]) + , poseidon2_T_2_7(il[581]) + , poseidon2_T_3_4(il[582]) + , poseidon2_T_3_5(il[583]) + , poseidon2_T_3_6(il[584]) + , poseidon2_T_3_7(il[585]) + , poseidon2_T_60_4(il[586]) + , poseidon2_T_60_5(il[587]) + , poseidon2_T_60_6(il[588]) + , poseidon2_T_60_7(il[589]) + , poseidon2_T_61_4(il[590]) + , poseidon2_T_61_5(il[591]) + , poseidon2_T_61_6(il[592]) + , poseidon2_T_61_7(il[593]) + , poseidon2_T_62_4(il[594]) + , poseidon2_T_62_5(il[595]) + , poseidon2_T_62_6(il[596]) + , poseidon2_T_62_7(il[597]) + , poseidon2_T_63_4(il[598]) + , poseidon2_T_63_5(il[599]) + , poseidon2_T_63_6(il[600]) + , poseidon2_T_63_7(il[601]) + , poseidon2_a_0(il[602]) + , poseidon2_a_1(il[603]) + , poseidon2_a_2(il[604]) + , poseidon2_a_3(il[605]) + , poseidon2_b_0(il[606]) + , poseidon2_b_1(il[607]) + , poseidon2_b_2(il[608]) + , poseidon2_b_3(il[609]) + , poseidon2_clk(il[610]) + , poseidon2_full_a_0(il[611]) + , poseidon2_full_a_1(il[612]) + , poseidon2_full_a_2(il[613]) + , poseidon2_full_a_3(il[614]) + , poseidon2_full_b_0(il[615]) + , poseidon2_full_b_1(il[616]) + , poseidon2_full_b_2(il[617]) + , poseidon2_full_b_3(il[618]) + , poseidon2_full_clk(il[619]) + , poseidon2_full_end_poseidon(il[620]) + , poseidon2_full_execute_poseidon_perm(il[621]) + , poseidon2_full_input_0(il[622]) + , poseidon2_full_input_1(il[623]) + , poseidon2_full_input_2(il[624]) + , poseidon2_full_input_len(il[625]) + , poseidon2_full_num_perm_rounds_rem(il[626]) + , poseidon2_full_num_perm_rounds_rem_inv(il[627]) + , poseidon2_full_output(il[628]) + , poseidon2_full_padding(il[629]) + , poseidon2_full_sel_merkle_tree(il[630]) + , poseidon2_full_sel_poseidon(il[631]) + , poseidon2_full_start_poseidon(il[632]) + , poseidon2_input_addr(il[633]) + , poseidon2_mem_addr_read_a(il[634]) + , poseidon2_mem_addr_read_b(il[635]) + , poseidon2_mem_addr_read_c(il[636]) + , poseidon2_mem_addr_read_d(il[637]) + , poseidon2_mem_addr_write_a(il[638]) + , poseidon2_mem_addr_write_b(il[639]) + , poseidon2_mem_addr_write_c(il[640]) + , poseidon2_mem_addr_write_d(il[641]) + , poseidon2_output_addr(il[642]) + , poseidon2_sel_poseidon_perm(il[643]) + , poseidon2_sel_poseidon_perm_immediate(il[644]) + , poseidon2_sel_poseidon_perm_mem_op(il[645]) + , poseidon2_space_id(il[646]) + , range_check_alu_rng_chk(il[647]) + , range_check_clk(il[648]) + , range_check_cmp_hi_bits_rng_chk(il[649]) + , range_check_cmp_lo_bits_rng_chk(il[650]) + , range_check_cmp_non_ff_rng_chk(il[651]) + , range_check_dyn_diff(il[652]) + , range_check_dyn_rng_chk_bits(il[653]) + , range_check_dyn_rng_chk_pow_2(il[654]) + , range_check_gas_da_rng_chk(il[655]) + , range_check_gas_l2_rng_chk(il[656]) + , range_check_is_lte_u112(il[657]) + , range_check_is_lte_u128(il[658]) + , range_check_is_lte_u16(il[659]) + , range_check_is_lte_u32(il[660]) + , range_check_is_lte_u48(il[661]) + , range_check_is_lte_u64(il[662]) + , range_check_is_lte_u80(il[663]) + , range_check_is_lte_u96(il[664]) + , range_check_rng_chk_bits(il[665]) + , range_check_sel_lookup_0(il[666]) + , range_check_sel_lookup_1(il[667]) + , range_check_sel_lookup_2(il[668]) + , range_check_sel_lookup_3(il[669]) + , range_check_sel_lookup_4(il[670]) + , range_check_sel_lookup_5(il[671]) + , range_check_sel_lookup_6(il[672]) + , range_check_sel_rng_chk(il[673]) + , range_check_u16_r0(il[674]) + , range_check_u16_r1(il[675]) + , range_check_u16_r2(il[676]) + , range_check_u16_r3(il[677]) + , range_check_u16_r4(il[678]) + , range_check_u16_r5(il[679]) + , range_check_u16_r6(il[680]) + , range_check_u16_r7(il[681]) + , range_check_value(il[682]) + , sha256_clk(il[683]) + , sha256_input(il[684]) + , sha256_output(il[685]) + , sha256_sel_sha256_compression(il[686]) + , sha256_state(il[687]) + , slice_addr(il[688]) + , slice_clk(il[689]) + , slice_cnt(il[690]) + , slice_col_offset(il[691]) + , slice_one_min_inv(il[692]) + , slice_sel_cd_cpy(il[693]) + , slice_sel_mem_active(il[694]) + , slice_sel_return(il[695]) + , slice_sel_start(il[696]) + , slice_space_id(il[697]) + , slice_val(il[698]) + , lookup_rng_chk_pow_2_counts(il[699]) + , lookup_rng_chk_diff_counts(il[700]) + , lookup_rng_chk_0_counts(il[701]) + , lookup_rng_chk_1_counts(il[702]) + , lookup_rng_chk_2_counts(il[703]) + , lookup_rng_chk_3_counts(il[704]) + , lookup_rng_chk_4_counts(il[705]) + , lookup_rng_chk_5_counts(il[706]) + , lookup_rng_chk_6_counts(il[707]) + , lookup_rng_chk_7_counts(il[708]) + , lookup_mem_rng_chk_0_counts(il[709]) + , lookup_mem_rng_chk_1_counts(il[710]) + , lookup_mem_rng_chk_2_counts(il[711]) + , lookup_pow_2_0_counts(il[712]) + , lookup_pow_2_1_counts(il[713]) + , lookup_byte_lengths_counts(il[714]) + , lookup_byte_operations_counts(il[715]) + , lookup_opcode_gas_counts(il[716]) + , lookup_l2_gas_rng_chk_0_counts(il[717]) + , lookup_l2_gas_rng_chk_1_counts(il[718]) + , lookup_da_gas_rng_chk_0_counts(il[719]) + , lookup_da_gas_rng_chk_1_counts(il[720]) + , kernel_output_lookup_counts(il[721]) + , lookup_into_kernel_counts(il[722]) + , lookup_cd_value_counts(il[723]) + , lookup_ret_value_counts(il[724]) + , incl_main_tag_err_counts(il[725]) + , incl_mem_tag_err_counts(il[726]) + , perm_rng_non_ff_cmp_inv(il[727]) + , perm_rng_cmp_lo_inv(il[728]) + , perm_rng_cmp_hi_inv(il[729]) + , perm_rng_alu_inv(il[730]) + , perm_cmp_alu_inv(il[731]) + , perm_l2_start_gas_inv(il[732]) + , perm_da_start_gas_inv(il[733]) + , perm_l2_end_gas_inv(il[734]) + , perm_da_end_gas_inv(il[735]) + , perm_pos_mem_read_a_inv(il[736]) + , perm_pos_mem_read_b_inv(il[737]) + , perm_pos_mem_read_c_inv(il[738]) + , perm_pos_mem_read_d_inv(il[739]) + , perm_pos_mem_write_a_inv(il[740]) + , perm_pos_mem_write_b_inv(il[741]) + , perm_pos_mem_write_c_inv(il[742]) + , perm_pos_mem_write_d_inv(il[743]) + , perm_pos2_fixed_pos2_perm_inv(il[744]) + , perm_slice_mem_inv(il[745]) + , perm_merkle_poseidon2_inv(il[746]) + , perm_main_alu_inv(il[747]) + , perm_main_bin_inv(il[748]) + , perm_main_conv_inv(il[749]) + , perm_main_sha256_inv(il[750]) + , perm_main_pos2_perm_inv(il[751]) + , perm_main_slice_inv(il[752]) + , perm_main_mem_a_inv(il[753]) + , perm_main_mem_b_inv(il[754]) + , perm_main_mem_c_inv(il[755]) + , perm_main_mem_d_inv(il[756]) + , perm_main_mem_ind_addr_a_inv(il[757]) + , perm_main_mem_ind_addr_b_inv(il[758]) + , perm_main_mem_ind_addr_c_inv(il[759]) + , perm_main_mem_ind_addr_d_inv(il[760]) + , lookup_rng_chk_pow_2_inv(il[761]) + , lookup_rng_chk_diff_inv(il[762]) + , lookup_rng_chk_0_inv(il[763]) + , lookup_rng_chk_1_inv(il[764]) + , lookup_rng_chk_2_inv(il[765]) + , lookup_rng_chk_3_inv(il[766]) + , lookup_rng_chk_4_inv(il[767]) + , lookup_rng_chk_5_inv(il[768]) + , lookup_rng_chk_6_inv(il[769]) + , lookup_rng_chk_7_inv(il[770]) + , lookup_mem_rng_chk_0_inv(il[771]) + , lookup_mem_rng_chk_1_inv(il[772]) + , lookup_mem_rng_chk_2_inv(il[773]) + , lookup_pow_2_0_inv(il[774]) + , lookup_pow_2_1_inv(il[775]) + , lookup_byte_lengths_inv(il[776]) + , lookup_byte_operations_inv(il[777]) + , lookup_opcode_gas_inv(il[778]) + , lookup_l2_gas_rng_chk_0_inv(il[779]) + , lookup_l2_gas_rng_chk_1_inv(il[780]) + , lookup_da_gas_rng_chk_0_inv(il[781]) + , lookup_da_gas_rng_chk_1_inv(il[782]) + , kernel_output_lookup_inv(il[783]) + , lookup_into_kernel_inv(il[784]) + , lookup_cd_value_inv(il[785]) + , lookup_ret_value_inv(il[786]) + , incl_main_tag_err_inv(il[787]) + , incl_mem_tag_err_inv(il[788]) + , binary_acc_ia_shift(il[789]) + , binary_acc_ib_shift(il[790]) + , binary_acc_ic_shift(il[791]) + , binary_mem_tag_ctr_shift(il[792]) + , binary_op_id_shift(il[793]) + , cmp_a_hi_shift(il[794]) + , cmp_a_lo_shift(il[795]) + , cmp_b_hi_shift(il[796]) + , cmp_b_lo_shift(il[797]) + , cmp_cmp_rng_ctr_shift(il[798]) + , cmp_op_gt_shift(il[799]) + , cmp_p_sub_a_hi_shift(il[800]) + , cmp_p_sub_a_lo_shift(il[801]) + , cmp_p_sub_b_hi_shift(il[802]) + , cmp_p_sub_b_lo_shift(il[803]) + , cmp_sel_rng_chk_shift(il[804]) + , main_da_gas_remaining_shift(il[805]) + , main_emit_l2_to_l1_msg_write_offset_shift(il[806]) + , main_emit_note_hash_write_offset_shift(il[807]) + , main_emit_nullifier_write_offset_shift(il[808]) + , main_emit_unencrypted_log_write_offset_shift(il[809]) + , main_internal_return_ptr_shift(il[810]) + , main_l1_to_l2_msg_exists_write_offset_shift(il[811]) + , main_l2_gas_remaining_shift(il[812]) + , main_note_hash_exist_write_offset_shift(il[813]) + , main_nullifier_exists_write_offset_shift(il[814]) + , main_nullifier_non_exists_write_offset_shift(il[815]) + , main_pc_shift(il[816]) + , main_sel_execution_end_shift(il[817]) + , main_sel_execution_row_shift(il[818]) + , main_sload_write_offset_shift(il[819]) + , main_sstore_write_offset_shift(il[820]) + , mem_glob_addr_shift(il[821]) + , mem_rw_shift(il[822]) + , mem_sel_mem_shift(il[823]) + , mem_tag_shift(il[824]) + , mem_tsp_shift(il[825]) + , mem_val_shift(il[826]) + , merkle_tree_leaf_index_shift(il[827]) + , merkle_tree_leaf_value_shift(il[828]) + , merkle_tree_path_len_shift(il[829]) + , poseidon2_full_a_0_shift(il[830]) + , poseidon2_full_a_1_shift(il[831]) + , poseidon2_full_a_2_shift(il[832]) + , poseidon2_full_a_3_shift(il[833]) + , poseidon2_full_execute_poseidon_perm_shift(il[834]) + , poseidon2_full_input_0_shift(il[835]) + , poseidon2_full_input_1_shift(il[836]) + , poseidon2_full_input_2_shift(il[837]) + , poseidon2_full_num_perm_rounds_rem_shift(il[838]) + , poseidon2_full_sel_poseidon_shift(il[839]) + , poseidon2_full_start_poseidon_shift(il[840]) + , slice_addr_shift(il[841]) + , slice_clk_shift(il[842]) + , slice_cnt_shift(il[843]) + , slice_col_offset_shift(il[844]) + , slice_sel_cd_cpy_shift(il[845]) + , slice_sel_mem_active_shift(il[846]) + , slice_sel_return_shift(il[847]) + , slice_sel_start_shift(il[848]) + , slice_space_id_shift(il[849]) {} AvmFlavor::ProverPolynomials::ProverPolynomials(ProvingKey& proving_key) @@ -894,6 +910,7 @@ AvmFlavor::AllConstRefValues AvmFlavor::ProverPolynomials::get_row(size_t row_id alu_cmp_gadget_gt[row_idx], alu_cmp_gadget_input_a[row_idx], alu_cmp_gadget_input_b[row_idx], + alu_cmp_gadget_non_ff_gt[row_idx], alu_cmp_gadget_result[row_idx], alu_cmp_gadget_sel[row_idx], alu_ff_tag[row_idx], @@ -973,11 +990,13 @@ AvmFlavor::AllConstRefValues AvmFlavor::ProverPolynomials::get_row(size_t row_id cmp_borrow[row_idx], cmp_clk[row_idx], cmp_cmp_rng_ctr[row_idx], + cmp_diff[row_idx], cmp_input_a[row_idx], cmp_input_b[row_idx], cmp_op_eq[row_idx], cmp_op_eq_diff_inv[row_idx], cmp_op_gt[row_idx], + cmp_op_non_ff_gt[row_idx], cmp_p_a_borrow[row_idx], cmp_p_b_borrow[row_idx], cmp_p_sub_a_hi[row_idx], @@ -1009,6 +1028,8 @@ AvmFlavor::AllConstRefValues AvmFlavor::ProverPolynomials::get_row(size_t row_id main_bin_op_id[row_idx], main_call_ptr[row_idx], main_da_gas_remaining[row_idx], + main_da_gas_u16_r0[row_idx], + main_da_gas_u16_r1[row_idx], main_da_out_of_gas[row_idx], main_dyn_da_gas_op_cost[row_idx], main_dyn_gas_multiplier[row_idx], @@ -1034,6 +1055,8 @@ AvmFlavor::AllConstRefValues AvmFlavor::ProverPolynomials::get_row(size_t row_id main_kernel_out_offset[row_idx], main_l1_to_l2_msg_exists_write_offset[row_idx], main_l2_gas_remaining[row_idx], + main_l2_gas_u16_r0[row_idx], + main_l2_gas_u16_r1[row_idx], main_l2_out_of_gas[row_idx], main_mem_addr_a[row_idx], main_mem_addr_b[row_idx], @@ -1071,6 +1094,7 @@ AvmFlavor::AllConstRefValues AvmFlavor::ProverPolynomials::get_row(size_t row_id main_sel_op_cast[row_idx], main_sel_op_chain_id[row_idx], main_sel_op_dagasleft[row_idx], + main_sel_op_debug_log[row_idx], main_sel_op_div[row_idx], main_sel_op_ecadd[row_idx], main_sel_op_emit_l2_to_l1_msg[row_idx], @@ -1498,6 +1522,7 @@ AvmFlavor::AllConstRefValues AvmFlavor::ProverPolynomials::get_row(size_t row_id range_check_clk[row_idx], range_check_cmp_hi_bits_rng_chk[row_idx], range_check_cmp_lo_bits_rng_chk[row_idx], + range_check_cmp_non_ff_rng_chk[row_idx], range_check_dyn_diff[row_idx], range_check_dyn_rng_chk_bits[row_idx], range_check_dyn_rng_chk_pow_2[row_idx], @@ -1563,18 +1588,21 @@ AvmFlavor::AllConstRefValues AvmFlavor::ProverPolynomials::get_row(size_t row_id lookup_byte_lengths_counts[row_idx], lookup_byte_operations_counts[row_idx], lookup_opcode_gas_counts[row_idx], + lookup_l2_gas_rng_chk_0_counts[row_idx], + lookup_l2_gas_rng_chk_1_counts[row_idx], + lookup_da_gas_rng_chk_0_counts[row_idx], + lookup_da_gas_rng_chk_1_counts[row_idx], kernel_output_lookup_counts[row_idx], lookup_into_kernel_counts[row_idx], lookup_cd_value_counts[row_idx], lookup_ret_value_counts[row_idx], incl_main_tag_err_counts[row_idx], incl_mem_tag_err_counts[row_idx], + perm_rng_non_ff_cmp_inv[row_idx], perm_rng_cmp_lo_inv[row_idx], perm_rng_cmp_hi_inv[row_idx], perm_rng_alu_inv[row_idx], perm_cmp_alu_inv[row_idx], - perm_rng_gas_l2_inv[row_idx], - perm_rng_gas_da_inv[row_idx], perm_l2_start_gas_inv[row_idx], perm_da_start_gas_inv[row_idx], perm_l2_end_gas_inv[row_idx], @@ -1622,6 +1650,10 @@ AvmFlavor::AllConstRefValues AvmFlavor::ProverPolynomials::get_row(size_t row_id lookup_byte_lengths_inv[row_idx], lookup_byte_operations_inv[row_idx], lookup_opcode_gas_inv[row_idx], + lookup_l2_gas_rng_chk_0_inv[row_idx], + lookup_l2_gas_rng_chk_1_inv[row_idx], + lookup_da_gas_rng_chk_0_inv[row_idx], + lookup_da_gas_rng_chk_1_inv[row_idx], kernel_output_lookup_inv[row_idx], lookup_into_kernel_inv[row_idx], lookup_cd_value_inv[row_idx], @@ -1732,6 +1764,7 @@ AvmFlavor::CommitmentLabels::CommitmentLabels() Base::alu_cmp_gadget_gt = "ALU_CMP_GADGET_GT"; Base::alu_cmp_gadget_input_a = "ALU_CMP_GADGET_INPUT_A"; Base::alu_cmp_gadget_input_b = "ALU_CMP_GADGET_INPUT_B"; + Base::alu_cmp_gadget_non_ff_gt = "ALU_CMP_GADGET_NON_FF_GT"; Base::alu_cmp_gadget_result = "ALU_CMP_GADGET_RESULT"; Base::alu_cmp_gadget_sel = "ALU_CMP_GADGET_SEL"; Base::alu_ff_tag = "ALU_FF_TAG"; @@ -1811,11 +1844,13 @@ AvmFlavor::CommitmentLabels::CommitmentLabels() Base::cmp_borrow = "CMP_BORROW"; Base::cmp_clk = "CMP_CLK"; Base::cmp_cmp_rng_ctr = "CMP_CMP_RNG_CTR"; + Base::cmp_diff = "CMP_DIFF"; Base::cmp_input_a = "CMP_INPUT_A"; Base::cmp_input_b = "CMP_INPUT_B"; Base::cmp_op_eq = "CMP_OP_EQ"; Base::cmp_op_eq_diff_inv = "CMP_OP_EQ_DIFF_INV"; Base::cmp_op_gt = "CMP_OP_GT"; + Base::cmp_op_non_ff_gt = "CMP_OP_NON_FF_GT"; Base::cmp_p_a_borrow = "CMP_P_A_BORROW"; Base::cmp_p_b_borrow = "CMP_P_B_BORROW"; Base::cmp_p_sub_a_hi = "CMP_P_SUB_A_HI"; @@ -1847,6 +1882,8 @@ AvmFlavor::CommitmentLabels::CommitmentLabels() Base::main_bin_op_id = "MAIN_BIN_OP_ID"; Base::main_call_ptr = "MAIN_CALL_PTR"; Base::main_da_gas_remaining = "MAIN_DA_GAS_REMAINING"; + Base::main_da_gas_u16_r0 = "MAIN_DA_GAS_U16_R0"; + Base::main_da_gas_u16_r1 = "MAIN_DA_GAS_U16_R1"; Base::main_da_out_of_gas = "MAIN_DA_OUT_OF_GAS"; Base::main_dyn_da_gas_op_cost = "MAIN_DYN_DA_GAS_OP_COST"; Base::main_dyn_gas_multiplier = "MAIN_DYN_GAS_MULTIPLIER"; @@ -1872,6 +1909,8 @@ AvmFlavor::CommitmentLabels::CommitmentLabels() Base::main_kernel_out_offset = "MAIN_KERNEL_OUT_OFFSET"; Base::main_l1_to_l2_msg_exists_write_offset = "MAIN_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET"; Base::main_l2_gas_remaining = "MAIN_L2_GAS_REMAINING"; + Base::main_l2_gas_u16_r0 = "MAIN_L2_GAS_U16_R0"; + Base::main_l2_gas_u16_r1 = "MAIN_L2_GAS_U16_R1"; Base::main_l2_out_of_gas = "MAIN_L2_OUT_OF_GAS"; Base::main_mem_addr_a = "MAIN_MEM_ADDR_A"; Base::main_mem_addr_b = "MAIN_MEM_ADDR_B"; @@ -1909,6 +1948,7 @@ AvmFlavor::CommitmentLabels::CommitmentLabels() Base::main_sel_op_cast = "MAIN_SEL_OP_CAST"; Base::main_sel_op_chain_id = "MAIN_SEL_OP_CHAIN_ID"; Base::main_sel_op_dagasleft = "MAIN_SEL_OP_DAGASLEFT"; + Base::main_sel_op_debug_log = "MAIN_SEL_OP_DEBUG_LOG"; Base::main_sel_op_div = "MAIN_SEL_OP_DIV"; Base::main_sel_op_ecadd = "MAIN_SEL_OP_ECADD"; Base::main_sel_op_emit_l2_to_l1_msg = "MAIN_SEL_OP_EMIT_L2_TO_L1_MSG"; @@ -2336,6 +2376,7 @@ AvmFlavor::CommitmentLabels::CommitmentLabels() Base::range_check_clk = "RANGE_CHECK_CLK"; Base::range_check_cmp_hi_bits_rng_chk = "RANGE_CHECK_CMP_HI_BITS_RNG_CHK"; Base::range_check_cmp_lo_bits_rng_chk = "RANGE_CHECK_CMP_LO_BITS_RNG_CHK"; + Base::range_check_cmp_non_ff_rng_chk = "RANGE_CHECK_CMP_NON_FF_RNG_CHK"; Base::range_check_dyn_diff = "RANGE_CHECK_DYN_DIFF"; Base::range_check_dyn_rng_chk_bits = "RANGE_CHECK_DYN_RNG_CHK_BITS"; Base::range_check_dyn_rng_chk_pow_2 = "RANGE_CHECK_DYN_RNG_CHK_POW_2"; @@ -2383,12 +2424,11 @@ AvmFlavor::CommitmentLabels::CommitmentLabels() Base::slice_sel_start = "SLICE_SEL_START"; Base::slice_space_id = "SLICE_SPACE_ID"; Base::slice_val = "SLICE_VAL"; + Base::perm_rng_non_ff_cmp_inv = "PERM_RNG_NON_FF_CMP_INV"; Base::perm_rng_cmp_lo_inv = "PERM_RNG_CMP_LO_INV"; Base::perm_rng_cmp_hi_inv = "PERM_RNG_CMP_HI_INV"; Base::perm_rng_alu_inv = "PERM_RNG_ALU_INV"; Base::perm_cmp_alu_inv = "PERM_CMP_ALU_INV"; - Base::perm_rng_gas_l2_inv = "PERM_RNG_GAS_L2_INV"; - Base::perm_rng_gas_da_inv = "PERM_RNG_GAS_DA_INV"; Base::perm_l2_start_gas_inv = "PERM_L2_START_GAS_INV"; Base::perm_da_start_gas_inv = "PERM_DA_START_GAS_INV"; Base::perm_l2_end_gas_inv = "PERM_L2_END_GAS_INV"; @@ -2436,6 +2476,10 @@ AvmFlavor::CommitmentLabels::CommitmentLabels() Base::lookup_byte_lengths_inv = "LOOKUP_BYTE_LENGTHS_INV"; Base::lookup_byte_operations_inv = "LOOKUP_BYTE_OPERATIONS_INV"; Base::lookup_opcode_gas_inv = "LOOKUP_OPCODE_GAS_INV"; + Base::lookup_l2_gas_rng_chk_0_inv = "LOOKUP_L2_GAS_RNG_CHK_0_INV"; + Base::lookup_l2_gas_rng_chk_1_inv = "LOOKUP_L2_GAS_RNG_CHK_1_INV"; + Base::lookup_da_gas_rng_chk_0_inv = "LOOKUP_DA_GAS_RNG_CHK_0_INV"; + Base::lookup_da_gas_rng_chk_1_inv = "LOOKUP_DA_GAS_RNG_CHK_1_INV"; Base::kernel_output_lookup_inv = "KERNEL_OUTPUT_LOOKUP_INV"; Base::lookup_into_kernel_inv = "LOOKUP_INTO_KERNEL_INV"; Base::lookup_cd_value_inv = "LOOKUP_CD_VALUE_INV"; @@ -2460,6 +2504,10 @@ AvmFlavor::CommitmentLabels::CommitmentLabels() Base::lookup_byte_lengths_counts = "LOOKUP_BYTE_LENGTHS_COUNTS"; Base::lookup_byte_operations_counts = "LOOKUP_BYTE_OPERATIONS_COUNTS"; Base::lookup_opcode_gas_counts = "LOOKUP_OPCODE_GAS_COUNTS"; + Base::lookup_l2_gas_rng_chk_0_counts = "LOOKUP_L2_GAS_RNG_CHK_0_COUNTS"; + Base::lookup_l2_gas_rng_chk_1_counts = "LOOKUP_L2_GAS_RNG_CHK_1_COUNTS"; + Base::lookup_da_gas_rng_chk_0_counts = "LOOKUP_DA_GAS_RNG_CHK_0_COUNTS"; + Base::lookup_da_gas_rng_chk_1_counts = "LOOKUP_DA_GAS_RNG_CHK_1_COUNTS"; Base::kernel_output_lookup_counts = "KERNEL_OUTPUT_LOOKUP_COUNTS"; Base::lookup_into_kernel_counts = "LOOKUP_INTO_KERNEL_COUNTS"; Base::lookup_cd_value_counts = "LOOKUP_CD_VALUE_COUNTS"; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp index 76fe2dd31f2..103f23375d9 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp @@ -40,7 +40,11 @@ #include "barretenberg/vm/avm/generated/relations/lookup_byte_lengths.hpp" #include "barretenberg/vm/avm/generated/relations/lookup_byte_operations.hpp" #include "barretenberg/vm/avm/generated/relations/lookup_cd_value.hpp" +#include "barretenberg/vm/avm/generated/relations/lookup_da_gas_rng_chk_0.hpp" +#include "barretenberg/vm/avm/generated/relations/lookup_da_gas_rng_chk_1.hpp" #include "barretenberg/vm/avm/generated/relations/lookup_into_kernel.hpp" +#include "barretenberg/vm/avm/generated/relations/lookup_l2_gas_rng_chk_0.hpp" +#include "barretenberg/vm/avm/generated/relations/lookup_l2_gas_rng_chk_1.hpp" #include "barretenberg/vm/avm/generated/relations/lookup_mem_rng_chk_0.hpp" #include "barretenberg/vm/avm/generated/relations/lookup_mem_rng_chk_1.hpp" #include "barretenberg/vm/avm/generated/relations/lookup_mem_rng_chk_2.hpp" @@ -90,8 +94,7 @@ #include "barretenberg/vm/avm/generated/relations/perm_rng_alu.hpp" #include "barretenberg/vm/avm/generated/relations/perm_rng_cmp_hi.hpp" #include "barretenberg/vm/avm/generated/relations/perm_rng_cmp_lo.hpp" -#include "barretenberg/vm/avm/generated/relations/perm_rng_gas_da.hpp" -#include "barretenberg/vm/avm/generated/relations/perm_rng_gas_l2.hpp" +#include "barretenberg/vm/avm/generated/relations/perm_rng_non_ff_cmp.hpp" #include "barretenberg/vm/avm/generated/relations/perm_slice_mem.hpp" // Metaprogramming to concatenate tuple types. @@ -100,8 +103,8 @@ template using tuple_cat_t = decltype(std::tuple_cat(std:: // The entities that will be used in the flavor. // clang-format off #define PRECOMPUTED_ENTITIES byte_lookup_sel_bin, byte_lookup_table_byte_lengths, byte_lookup_table_in_tags, byte_lookup_table_input_a, byte_lookup_table_input_b, byte_lookup_table_op_id, byte_lookup_table_output, gas_base_da_gas_fixed_table, gas_base_l2_gas_fixed_table, gas_dyn_da_gas_fixed_table, gas_dyn_l2_gas_fixed_table, gas_sel_gas_cost, main_clk, main_sel_da_end_gas_kernel_input, main_sel_da_start_gas_kernel_input, main_sel_first, main_sel_l2_end_gas_kernel_input, main_sel_l2_start_gas_kernel_input, main_sel_start_exec, main_zeroes, powers_power_of_2 -#define WIRE_ENTITIES main_kernel_inputs, main_kernel_value_out, main_kernel_side_effect_out, main_kernel_metadata_out, main_calldata, main_returndata, alu_a_hi, alu_a_lo, alu_b_hi, alu_b_lo, alu_b_pow, alu_c_hi, alu_c_lo, alu_cf, alu_clk, alu_cmp_gadget_gt, alu_cmp_gadget_input_a, alu_cmp_gadget_input_b, alu_cmp_gadget_result, alu_cmp_gadget_sel, alu_ff_tag, alu_ia, alu_ib, alu_ic, alu_in_tag, alu_max_bits_sub_b_bits, alu_max_bits_sub_b_pow, alu_op_add, alu_op_cast, alu_op_div, alu_op_eq, alu_op_lt, alu_op_lte, alu_op_mul, alu_op_not, alu_op_shl, alu_op_shr, alu_op_sub, alu_partial_prod_hi, alu_partial_prod_lo, alu_range_check_input_value, alu_range_check_num_bits, alu_range_check_sel, alu_remainder, alu_sel_alu, alu_sel_cmp, alu_sel_shift_which, alu_u128_tag, alu_u16_tag, alu_u1_tag, alu_u32_tag, alu_u64_tag, alu_u8_tag, alu_zero_shift, binary_acc_ia, binary_acc_ib, binary_acc_ic, binary_clk, binary_ia_bytes, binary_ib_bytes, binary_ic_bytes, binary_in_tag, binary_mem_tag_ctr, binary_mem_tag_ctr_inv, binary_op_id, binary_sel_bin, binary_start, bytecode_arifact_hash, bytecode_as_fields, bytecode_bytes, bytecode_bytes_pc, bytecode_class_id, bytecode_contract_address, bytecode_decomposed, bytecode_deployer_addr, bytecode_end_latch, bytecode_incoming_viewing_key_x, bytecode_incoming_viewing_key_y, bytecode_initialization_hash, bytecode_length_remaining, bytecode_nullifier_key_x, bytecode_nullifier_key_y, bytecode_outgoing_viewing_key_x, bytecode_outgoing_viewing_key_y, bytecode_private_fn_root, bytecode_public_key_hash, bytecode_running_hash, bytecode_salt, bytecode_tagging_key_x, bytecode_tagging_key_y, cmp_a_hi, cmp_a_lo, cmp_b_hi, cmp_b_lo, cmp_borrow, cmp_clk, cmp_cmp_rng_ctr, cmp_input_a, cmp_input_b, cmp_op_eq, cmp_op_eq_diff_inv, cmp_op_gt, cmp_p_a_borrow, cmp_p_b_borrow, cmp_p_sub_a_hi, cmp_p_sub_a_lo, cmp_p_sub_b_hi, cmp_p_sub_b_lo, cmp_range_chk_clk, cmp_res_hi, cmp_res_lo, cmp_result, cmp_sel_cmp, cmp_sel_rng_chk, cmp_shift_sel, conversion_clk, conversion_input, conversion_num_limbs, conversion_output_bits, conversion_radix, conversion_sel_to_radix_be, keccakf1600_clk, keccakf1600_input, keccakf1600_output, keccakf1600_sel_keccakf1600, main_abs_da_rem_gas, main_abs_l2_rem_gas, main_alu_in_tag, main_base_da_gas_op_cost, main_base_l2_gas_op_cost, main_bin_op_id, main_call_ptr, main_da_gas_remaining, main_da_out_of_gas, main_dyn_da_gas_op_cost, main_dyn_gas_multiplier, main_dyn_l2_gas_op_cost, main_emit_l2_to_l1_msg_write_offset, main_emit_note_hash_write_offset, main_emit_nullifier_write_offset, main_emit_unencrypted_log_write_offset, main_ia, main_ib, main_ic, main_id, main_id_zero, main_ind_addr_a, main_ind_addr_b, main_ind_addr_c, main_ind_addr_d, main_internal_return_ptr, main_inv, main_is_fake_row, main_is_gas_accounted, main_kernel_in_offset, main_kernel_out_offset, main_l1_to_l2_msg_exists_write_offset, main_l2_gas_remaining, main_l2_out_of_gas, main_mem_addr_a, main_mem_addr_b, main_mem_addr_c, main_mem_addr_d, main_note_hash_exist_write_offset, main_nullifier_exists_write_offset, main_nullifier_non_exists_write_offset, main_op_err, main_opcode_val, main_pc, main_r_in_tag, main_rwa, main_rwb, main_rwc, main_rwd, main_sel_alu, main_sel_bin, main_sel_calldata, main_sel_execution_end, main_sel_execution_row, main_sel_kernel_inputs, main_sel_kernel_out, main_sel_mem_op_a, main_sel_mem_op_b, main_sel_mem_op_c, main_sel_mem_op_d, main_sel_mov_ia_to_ic, main_sel_mov_ib_to_ic, main_sel_op_add, main_sel_op_address, main_sel_op_and, main_sel_op_block_number, main_sel_op_calldata_copy, main_sel_op_cast, main_sel_op_chain_id, main_sel_op_dagasleft, main_sel_op_div, main_sel_op_ecadd, main_sel_op_emit_l2_to_l1_msg, main_sel_op_emit_note_hash, main_sel_op_emit_nullifier, main_sel_op_emit_unencrypted_log, main_sel_op_eq, main_sel_op_external_call, main_sel_op_external_return, main_sel_op_external_revert, main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_internal_call, main_sel_op_internal_return, main_sel_op_is_static_call, main_sel_op_jump, main_sel_op_jumpi, main_sel_op_keccak, main_sel_op_l1_to_l2_msg_exists, main_sel_op_l2gasleft, main_sel_op_lt, main_sel_op_lte, main_sel_op_mov, main_sel_op_msm, main_sel_op_mul, main_sel_op_not, main_sel_op_note_hash_exists, main_sel_op_nullifier_exists, main_sel_op_or, main_sel_op_poseidon2, main_sel_op_radix_be, main_sel_op_returndata_copy, main_sel_op_returndata_size, main_sel_op_sender, main_sel_op_set, main_sel_op_sha256, main_sel_op_shl, main_sel_op_shr, main_sel_op_sload, main_sel_op_sstore, main_sel_op_static_call, main_sel_op_sub, main_sel_op_timestamp, main_sel_op_transaction_fee, main_sel_op_version, main_sel_op_xor, main_sel_q_kernel_lookup, main_sel_q_kernel_output_lookup, main_sel_resolve_ind_addr_a, main_sel_resolve_ind_addr_b, main_sel_resolve_ind_addr_c, main_sel_resolve_ind_addr_d, main_sel_returndata, main_sel_rng_16, main_sel_rng_8, main_sel_slice_gadget, main_side_effect_counter, main_sload_write_offset, main_space_id, main_sstore_write_offset, main_tag_err, main_w_in_tag, mem_addr, mem_clk, mem_diff, mem_glob_addr, mem_last, mem_lastAccess, mem_one_min_inv, mem_r_in_tag, mem_rw, mem_sel_mem, mem_sel_mov_ia_to_ic, mem_sel_mov_ib_to_ic, mem_sel_op_a, mem_sel_op_b, mem_sel_op_c, mem_sel_op_d, mem_sel_op_poseidon_read_a, mem_sel_op_poseidon_read_b, mem_sel_op_poseidon_read_c, mem_sel_op_poseidon_read_d, mem_sel_op_poseidon_write_a, mem_sel_op_poseidon_write_b, mem_sel_op_poseidon_write_c, mem_sel_op_poseidon_write_d, mem_sel_op_slice, mem_sel_resolve_ind_addr_a, mem_sel_resolve_ind_addr_b, mem_sel_resolve_ind_addr_c, mem_sel_resolve_ind_addr_d, mem_sel_rng_chk, mem_skip_check_tag, mem_space_id, mem_tag, mem_tag_err, mem_tsp, mem_u16_r0, mem_u16_r1, mem_u8_r0, mem_val, mem_w_in_tag, merkle_tree_clk, merkle_tree_expected_tree_root, merkle_tree_latch, merkle_tree_leaf_index, merkle_tree_leaf_index_is_even, merkle_tree_leaf_value, merkle_tree_left_hash, merkle_tree_output_hash, merkle_tree_path_len, merkle_tree_path_len_inv, merkle_tree_right_hash, merkle_tree_sel_merkle_tree, merkle_tree_sibling_value, poseidon2_B_10_0, poseidon2_B_10_1, poseidon2_B_10_2, poseidon2_B_10_3, poseidon2_B_11_0, poseidon2_B_11_1, poseidon2_B_11_2, poseidon2_B_11_3, poseidon2_B_12_0, poseidon2_B_12_1, poseidon2_B_12_2, poseidon2_B_12_3, poseidon2_B_13_0, poseidon2_B_13_1, poseidon2_B_13_2, poseidon2_B_13_3, poseidon2_B_14_0, poseidon2_B_14_1, poseidon2_B_14_2, poseidon2_B_14_3, poseidon2_B_15_0, poseidon2_B_15_1, poseidon2_B_15_2, poseidon2_B_15_3, poseidon2_B_16_0, poseidon2_B_16_1, poseidon2_B_16_2, poseidon2_B_16_3, poseidon2_B_17_0, poseidon2_B_17_1, poseidon2_B_17_2, poseidon2_B_17_3, poseidon2_B_18_0, poseidon2_B_18_1, poseidon2_B_18_2, poseidon2_B_18_3, poseidon2_B_19_0, poseidon2_B_19_1, poseidon2_B_19_2, poseidon2_B_19_3, poseidon2_B_20_0, poseidon2_B_20_1, poseidon2_B_20_2, poseidon2_B_20_3, poseidon2_B_21_0, poseidon2_B_21_1, poseidon2_B_21_2, poseidon2_B_21_3, poseidon2_B_22_0, poseidon2_B_22_1, poseidon2_B_22_2, poseidon2_B_22_3, poseidon2_B_23_0, poseidon2_B_23_1, poseidon2_B_23_2, poseidon2_B_23_3, poseidon2_B_24_0, poseidon2_B_24_1, poseidon2_B_24_2, poseidon2_B_24_3, poseidon2_B_25_0, poseidon2_B_25_1, poseidon2_B_25_2, poseidon2_B_25_3, poseidon2_B_26_0, poseidon2_B_26_1, poseidon2_B_26_2, poseidon2_B_26_3, poseidon2_B_27_0, poseidon2_B_27_1, poseidon2_B_27_2, poseidon2_B_27_3, poseidon2_B_28_0, poseidon2_B_28_1, poseidon2_B_28_2, poseidon2_B_28_3, poseidon2_B_29_0, poseidon2_B_29_1, poseidon2_B_29_2, poseidon2_B_29_3, poseidon2_B_30_0, poseidon2_B_30_1, poseidon2_B_30_2, poseidon2_B_30_3, poseidon2_B_31_0, poseidon2_B_31_1, poseidon2_B_31_2, poseidon2_B_31_3, poseidon2_B_32_0, poseidon2_B_32_1, poseidon2_B_32_2, poseidon2_B_32_3, poseidon2_B_33_0, poseidon2_B_33_1, poseidon2_B_33_2, poseidon2_B_33_3, poseidon2_B_34_0, poseidon2_B_34_1, poseidon2_B_34_2, poseidon2_B_34_3, poseidon2_B_35_0, poseidon2_B_35_1, poseidon2_B_35_2, poseidon2_B_35_3, poseidon2_B_36_0, poseidon2_B_36_1, poseidon2_B_36_2, poseidon2_B_36_3, poseidon2_B_37_0, poseidon2_B_37_1, poseidon2_B_37_2, poseidon2_B_37_3, poseidon2_B_38_0, poseidon2_B_38_1, poseidon2_B_38_2, poseidon2_B_38_3, poseidon2_B_39_0, poseidon2_B_39_1, poseidon2_B_39_2, poseidon2_B_39_3, poseidon2_B_40_0, poseidon2_B_40_1, poseidon2_B_40_2, poseidon2_B_40_3, poseidon2_B_41_0, poseidon2_B_41_1, poseidon2_B_41_2, poseidon2_B_41_3, poseidon2_B_42_0, poseidon2_B_42_1, poseidon2_B_42_2, poseidon2_B_42_3, poseidon2_B_43_0, poseidon2_B_43_1, poseidon2_B_43_2, poseidon2_B_43_3, poseidon2_B_44_0, poseidon2_B_44_1, poseidon2_B_44_2, poseidon2_B_44_3, poseidon2_B_45_0, poseidon2_B_45_1, poseidon2_B_45_2, poseidon2_B_45_3, poseidon2_B_46_0, poseidon2_B_46_1, poseidon2_B_46_2, poseidon2_B_46_3, poseidon2_B_47_0, poseidon2_B_47_1, poseidon2_B_47_2, poseidon2_B_47_3, poseidon2_B_48_0, poseidon2_B_48_1, poseidon2_B_48_2, poseidon2_B_48_3, poseidon2_B_49_0, poseidon2_B_49_1, poseidon2_B_49_2, poseidon2_B_49_3, poseidon2_B_4_0, poseidon2_B_4_1, poseidon2_B_4_2, poseidon2_B_4_3, poseidon2_B_50_0, poseidon2_B_50_1, poseidon2_B_50_2, poseidon2_B_50_3, poseidon2_B_51_0, poseidon2_B_51_1, poseidon2_B_51_2, poseidon2_B_51_3, poseidon2_B_52_0, poseidon2_B_52_1, poseidon2_B_52_2, poseidon2_B_52_3, poseidon2_B_53_0, poseidon2_B_53_1, poseidon2_B_53_2, poseidon2_B_53_3, poseidon2_B_54_0, poseidon2_B_54_1, poseidon2_B_54_2, poseidon2_B_54_3, poseidon2_B_55_0, poseidon2_B_55_1, poseidon2_B_55_2, poseidon2_B_55_3, poseidon2_B_56_0, poseidon2_B_56_1, poseidon2_B_56_2, poseidon2_B_56_3, poseidon2_B_57_0, poseidon2_B_57_1, poseidon2_B_57_2, poseidon2_B_57_3, poseidon2_B_58_0, poseidon2_B_58_1, poseidon2_B_58_2, poseidon2_B_58_3, poseidon2_B_59_0, poseidon2_B_59_1, poseidon2_B_59_2, poseidon2_B_59_3, poseidon2_B_5_0, poseidon2_B_5_1, poseidon2_B_5_2, poseidon2_B_5_3, poseidon2_B_6_0, poseidon2_B_6_1, poseidon2_B_6_2, poseidon2_B_6_3, poseidon2_B_7_0, poseidon2_B_7_1, poseidon2_B_7_2, poseidon2_B_7_3, poseidon2_B_8_0, poseidon2_B_8_1, poseidon2_B_8_2, poseidon2_B_8_3, poseidon2_B_9_0, poseidon2_B_9_1, poseidon2_B_9_2, poseidon2_B_9_3, poseidon2_EXT_LAYER_4, poseidon2_EXT_LAYER_5, poseidon2_EXT_LAYER_6, poseidon2_EXT_LAYER_7, poseidon2_T_0_4, poseidon2_T_0_5, poseidon2_T_0_6, poseidon2_T_0_7, poseidon2_T_1_4, poseidon2_T_1_5, poseidon2_T_1_6, poseidon2_T_1_7, poseidon2_T_2_4, poseidon2_T_2_5, poseidon2_T_2_6, poseidon2_T_2_7, poseidon2_T_3_4, poseidon2_T_3_5, poseidon2_T_3_6, poseidon2_T_3_7, poseidon2_T_60_4, poseidon2_T_60_5, poseidon2_T_60_6, poseidon2_T_60_7, poseidon2_T_61_4, poseidon2_T_61_5, poseidon2_T_61_6, poseidon2_T_61_7, poseidon2_T_62_4, poseidon2_T_62_5, poseidon2_T_62_6, poseidon2_T_62_7, poseidon2_T_63_4, poseidon2_T_63_5, poseidon2_T_63_6, poseidon2_T_63_7, poseidon2_a_0, poseidon2_a_1, poseidon2_a_2, poseidon2_a_3, poseidon2_b_0, poseidon2_b_1, poseidon2_b_2, poseidon2_b_3, poseidon2_clk, poseidon2_full_a_0, poseidon2_full_a_1, poseidon2_full_a_2, poseidon2_full_a_3, poseidon2_full_b_0, poseidon2_full_b_1, poseidon2_full_b_2, poseidon2_full_b_3, poseidon2_full_clk, poseidon2_full_end_poseidon, poseidon2_full_execute_poseidon_perm, poseidon2_full_input_0, poseidon2_full_input_1, poseidon2_full_input_2, poseidon2_full_input_len, poseidon2_full_num_perm_rounds_rem, poseidon2_full_num_perm_rounds_rem_inv, poseidon2_full_output, poseidon2_full_padding, poseidon2_full_sel_merkle_tree, poseidon2_full_sel_poseidon, poseidon2_full_start_poseidon, poseidon2_input_addr, poseidon2_mem_addr_read_a, poseidon2_mem_addr_read_b, poseidon2_mem_addr_read_c, poseidon2_mem_addr_read_d, poseidon2_mem_addr_write_a, poseidon2_mem_addr_write_b, poseidon2_mem_addr_write_c, poseidon2_mem_addr_write_d, poseidon2_output_addr, poseidon2_sel_poseidon_perm, poseidon2_sel_poseidon_perm_immediate, poseidon2_sel_poseidon_perm_mem_op, poseidon2_space_id, range_check_alu_rng_chk, range_check_clk, range_check_cmp_hi_bits_rng_chk, range_check_cmp_lo_bits_rng_chk, range_check_dyn_diff, range_check_dyn_rng_chk_bits, range_check_dyn_rng_chk_pow_2, range_check_gas_da_rng_chk, range_check_gas_l2_rng_chk, range_check_is_lte_u112, range_check_is_lte_u128, range_check_is_lte_u16, range_check_is_lte_u32, range_check_is_lte_u48, range_check_is_lte_u64, range_check_is_lte_u80, range_check_is_lte_u96, range_check_rng_chk_bits, range_check_sel_lookup_0, range_check_sel_lookup_1, range_check_sel_lookup_2, range_check_sel_lookup_3, range_check_sel_lookup_4, range_check_sel_lookup_5, range_check_sel_lookup_6, range_check_sel_rng_chk, range_check_u16_r0, range_check_u16_r1, range_check_u16_r2, range_check_u16_r3, range_check_u16_r4, range_check_u16_r5, range_check_u16_r6, range_check_u16_r7, range_check_value, sha256_clk, sha256_input, sha256_output, sha256_sel_sha256_compression, sha256_state, slice_addr, slice_clk, slice_cnt, slice_col_offset, slice_one_min_inv, slice_sel_cd_cpy, slice_sel_mem_active, slice_sel_return, slice_sel_start, slice_space_id, slice_val, lookup_rng_chk_pow_2_counts, lookup_rng_chk_diff_counts, lookup_rng_chk_0_counts, lookup_rng_chk_1_counts, lookup_rng_chk_2_counts, lookup_rng_chk_3_counts, lookup_rng_chk_4_counts, lookup_rng_chk_5_counts, lookup_rng_chk_6_counts, lookup_rng_chk_7_counts, lookup_mem_rng_chk_0_counts, lookup_mem_rng_chk_1_counts, lookup_mem_rng_chk_2_counts, lookup_pow_2_0_counts, lookup_pow_2_1_counts, lookup_byte_lengths_counts, lookup_byte_operations_counts, lookup_opcode_gas_counts, kernel_output_lookup_counts, lookup_into_kernel_counts, lookup_cd_value_counts, lookup_ret_value_counts, incl_main_tag_err_counts, incl_mem_tag_err_counts -#define DERIVED_WITNESS_ENTITIES perm_rng_cmp_lo_inv, perm_rng_cmp_hi_inv, perm_rng_alu_inv, perm_cmp_alu_inv, perm_rng_gas_l2_inv, perm_rng_gas_da_inv, perm_l2_start_gas_inv, perm_da_start_gas_inv, perm_l2_end_gas_inv, perm_da_end_gas_inv, perm_pos_mem_read_a_inv, perm_pos_mem_read_b_inv, perm_pos_mem_read_c_inv, perm_pos_mem_read_d_inv, perm_pos_mem_write_a_inv, perm_pos_mem_write_b_inv, perm_pos_mem_write_c_inv, perm_pos_mem_write_d_inv, perm_pos2_fixed_pos2_perm_inv, perm_slice_mem_inv, perm_merkle_poseidon2_inv, perm_main_alu_inv, perm_main_bin_inv, perm_main_conv_inv, perm_main_sha256_inv, perm_main_pos2_perm_inv, perm_main_slice_inv, perm_main_mem_a_inv, perm_main_mem_b_inv, perm_main_mem_c_inv, perm_main_mem_d_inv, perm_main_mem_ind_addr_a_inv, perm_main_mem_ind_addr_b_inv, perm_main_mem_ind_addr_c_inv, perm_main_mem_ind_addr_d_inv, lookup_rng_chk_pow_2_inv, lookup_rng_chk_diff_inv, lookup_rng_chk_0_inv, lookup_rng_chk_1_inv, lookup_rng_chk_2_inv, lookup_rng_chk_3_inv, lookup_rng_chk_4_inv, lookup_rng_chk_5_inv, lookup_rng_chk_6_inv, lookup_rng_chk_7_inv, lookup_mem_rng_chk_0_inv, lookup_mem_rng_chk_1_inv, lookup_mem_rng_chk_2_inv, lookup_pow_2_0_inv, lookup_pow_2_1_inv, lookup_byte_lengths_inv, lookup_byte_operations_inv, lookup_opcode_gas_inv, kernel_output_lookup_inv, lookup_into_kernel_inv, lookup_cd_value_inv, lookup_ret_value_inv, incl_main_tag_err_inv, incl_mem_tag_err_inv +#define WIRE_ENTITIES main_kernel_inputs, main_kernel_value_out, main_kernel_side_effect_out, main_kernel_metadata_out, main_calldata, main_returndata, alu_a_hi, alu_a_lo, alu_b_hi, alu_b_lo, alu_b_pow, alu_c_hi, alu_c_lo, alu_cf, alu_clk, alu_cmp_gadget_gt, alu_cmp_gadget_input_a, alu_cmp_gadget_input_b, alu_cmp_gadget_non_ff_gt, alu_cmp_gadget_result, alu_cmp_gadget_sel, alu_ff_tag, alu_ia, alu_ib, alu_ic, alu_in_tag, alu_max_bits_sub_b_bits, alu_max_bits_sub_b_pow, alu_op_add, alu_op_cast, alu_op_div, alu_op_eq, alu_op_lt, alu_op_lte, alu_op_mul, alu_op_not, alu_op_shl, alu_op_shr, alu_op_sub, alu_partial_prod_hi, alu_partial_prod_lo, alu_range_check_input_value, alu_range_check_num_bits, alu_range_check_sel, alu_remainder, alu_sel_alu, alu_sel_cmp, alu_sel_shift_which, alu_u128_tag, alu_u16_tag, alu_u1_tag, alu_u32_tag, alu_u64_tag, alu_u8_tag, alu_zero_shift, binary_acc_ia, binary_acc_ib, binary_acc_ic, binary_clk, binary_ia_bytes, binary_ib_bytes, binary_ic_bytes, binary_in_tag, binary_mem_tag_ctr, binary_mem_tag_ctr_inv, binary_op_id, binary_sel_bin, binary_start, bytecode_arifact_hash, bytecode_as_fields, bytecode_bytes, bytecode_bytes_pc, bytecode_class_id, bytecode_contract_address, bytecode_decomposed, bytecode_deployer_addr, bytecode_end_latch, bytecode_incoming_viewing_key_x, bytecode_incoming_viewing_key_y, bytecode_initialization_hash, bytecode_length_remaining, bytecode_nullifier_key_x, bytecode_nullifier_key_y, bytecode_outgoing_viewing_key_x, bytecode_outgoing_viewing_key_y, bytecode_private_fn_root, bytecode_public_key_hash, bytecode_running_hash, bytecode_salt, bytecode_tagging_key_x, bytecode_tagging_key_y, cmp_a_hi, cmp_a_lo, cmp_b_hi, cmp_b_lo, cmp_borrow, cmp_clk, cmp_cmp_rng_ctr, cmp_diff, cmp_input_a, cmp_input_b, cmp_op_eq, cmp_op_eq_diff_inv, cmp_op_gt, cmp_op_non_ff_gt, cmp_p_a_borrow, cmp_p_b_borrow, cmp_p_sub_a_hi, cmp_p_sub_a_lo, cmp_p_sub_b_hi, cmp_p_sub_b_lo, cmp_range_chk_clk, cmp_res_hi, cmp_res_lo, cmp_result, cmp_sel_cmp, cmp_sel_rng_chk, cmp_shift_sel, conversion_clk, conversion_input, conversion_num_limbs, conversion_output_bits, conversion_radix, conversion_sel_to_radix_be, keccakf1600_clk, keccakf1600_input, keccakf1600_output, keccakf1600_sel_keccakf1600, main_abs_da_rem_gas, main_abs_l2_rem_gas, main_alu_in_tag, main_base_da_gas_op_cost, main_base_l2_gas_op_cost, main_bin_op_id, main_call_ptr, main_da_gas_remaining, main_da_gas_u16_r0, main_da_gas_u16_r1, main_da_out_of_gas, main_dyn_da_gas_op_cost, main_dyn_gas_multiplier, main_dyn_l2_gas_op_cost, main_emit_l2_to_l1_msg_write_offset, main_emit_note_hash_write_offset, main_emit_nullifier_write_offset, main_emit_unencrypted_log_write_offset, main_ia, main_ib, main_ic, main_id, main_id_zero, main_ind_addr_a, main_ind_addr_b, main_ind_addr_c, main_ind_addr_d, main_internal_return_ptr, main_inv, main_is_fake_row, main_is_gas_accounted, main_kernel_in_offset, main_kernel_out_offset, main_l1_to_l2_msg_exists_write_offset, main_l2_gas_remaining, main_l2_gas_u16_r0, main_l2_gas_u16_r1, main_l2_out_of_gas, main_mem_addr_a, main_mem_addr_b, main_mem_addr_c, main_mem_addr_d, main_note_hash_exist_write_offset, main_nullifier_exists_write_offset, main_nullifier_non_exists_write_offset, main_op_err, main_opcode_val, main_pc, main_r_in_tag, main_rwa, main_rwb, main_rwc, main_rwd, main_sel_alu, main_sel_bin, main_sel_calldata, main_sel_execution_end, main_sel_execution_row, main_sel_kernel_inputs, main_sel_kernel_out, main_sel_mem_op_a, main_sel_mem_op_b, main_sel_mem_op_c, main_sel_mem_op_d, main_sel_mov_ia_to_ic, main_sel_mov_ib_to_ic, main_sel_op_add, main_sel_op_address, main_sel_op_and, main_sel_op_block_number, main_sel_op_calldata_copy, main_sel_op_cast, main_sel_op_chain_id, main_sel_op_dagasleft, main_sel_op_debug_log, main_sel_op_div, main_sel_op_ecadd, main_sel_op_emit_l2_to_l1_msg, main_sel_op_emit_note_hash, main_sel_op_emit_nullifier, main_sel_op_emit_unencrypted_log, main_sel_op_eq, main_sel_op_external_call, main_sel_op_external_return, main_sel_op_external_revert, main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_internal_call, main_sel_op_internal_return, main_sel_op_is_static_call, main_sel_op_jump, main_sel_op_jumpi, main_sel_op_keccak, main_sel_op_l1_to_l2_msg_exists, main_sel_op_l2gasleft, main_sel_op_lt, main_sel_op_lte, main_sel_op_mov, main_sel_op_msm, main_sel_op_mul, main_sel_op_not, main_sel_op_note_hash_exists, main_sel_op_nullifier_exists, main_sel_op_or, main_sel_op_poseidon2, main_sel_op_radix_be, main_sel_op_returndata_copy, main_sel_op_returndata_size, main_sel_op_sender, main_sel_op_set, main_sel_op_sha256, main_sel_op_shl, main_sel_op_shr, main_sel_op_sload, main_sel_op_sstore, main_sel_op_static_call, main_sel_op_sub, main_sel_op_timestamp, main_sel_op_transaction_fee, main_sel_op_version, main_sel_op_xor, main_sel_q_kernel_lookup, main_sel_q_kernel_output_lookup, main_sel_resolve_ind_addr_a, main_sel_resolve_ind_addr_b, main_sel_resolve_ind_addr_c, main_sel_resolve_ind_addr_d, main_sel_returndata, main_sel_rng_16, main_sel_rng_8, main_sel_slice_gadget, main_side_effect_counter, main_sload_write_offset, main_space_id, main_sstore_write_offset, main_tag_err, main_w_in_tag, mem_addr, mem_clk, mem_diff, mem_glob_addr, mem_last, mem_lastAccess, mem_one_min_inv, mem_r_in_tag, mem_rw, mem_sel_mem, mem_sel_mov_ia_to_ic, mem_sel_mov_ib_to_ic, mem_sel_op_a, mem_sel_op_b, mem_sel_op_c, mem_sel_op_d, mem_sel_op_poseidon_read_a, mem_sel_op_poseidon_read_b, mem_sel_op_poseidon_read_c, mem_sel_op_poseidon_read_d, mem_sel_op_poseidon_write_a, mem_sel_op_poseidon_write_b, mem_sel_op_poseidon_write_c, mem_sel_op_poseidon_write_d, mem_sel_op_slice, mem_sel_resolve_ind_addr_a, mem_sel_resolve_ind_addr_b, mem_sel_resolve_ind_addr_c, mem_sel_resolve_ind_addr_d, mem_sel_rng_chk, mem_skip_check_tag, mem_space_id, mem_tag, mem_tag_err, mem_tsp, mem_u16_r0, mem_u16_r1, mem_u8_r0, mem_val, mem_w_in_tag, merkle_tree_clk, merkle_tree_expected_tree_root, merkle_tree_latch, merkle_tree_leaf_index, merkle_tree_leaf_index_is_even, merkle_tree_leaf_value, merkle_tree_left_hash, merkle_tree_output_hash, merkle_tree_path_len, merkle_tree_path_len_inv, merkle_tree_right_hash, merkle_tree_sel_merkle_tree, merkle_tree_sibling_value, poseidon2_B_10_0, poseidon2_B_10_1, poseidon2_B_10_2, poseidon2_B_10_3, poseidon2_B_11_0, poseidon2_B_11_1, poseidon2_B_11_2, poseidon2_B_11_3, poseidon2_B_12_0, poseidon2_B_12_1, poseidon2_B_12_2, poseidon2_B_12_3, poseidon2_B_13_0, poseidon2_B_13_1, poseidon2_B_13_2, poseidon2_B_13_3, poseidon2_B_14_0, poseidon2_B_14_1, poseidon2_B_14_2, poseidon2_B_14_3, poseidon2_B_15_0, poseidon2_B_15_1, poseidon2_B_15_2, poseidon2_B_15_3, poseidon2_B_16_0, poseidon2_B_16_1, poseidon2_B_16_2, poseidon2_B_16_3, poseidon2_B_17_0, poseidon2_B_17_1, poseidon2_B_17_2, poseidon2_B_17_3, poseidon2_B_18_0, poseidon2_B_18_1, poseidon2_B_18_2, poseidon2_B_18_3, poseidon2_B_19_0, poseidon2_B_19_1, poseidon2_B_19_2, poseidon2_B_19_3, poseidon2_B_20_0, poseidon2_B_20_1, poseidon2_B_20_2, poseidon2_B_20_3, poseidon2_B_21_0, poseidon2_B_21_1, poseidon2_B_21_2, poseidon2_B_21_3, poseidon2_B_22_0, poseidon2_B_22_1, poseidon2_B_22_2, poseidon2_B_22_3, poseidon2_B_23_0, poseidon2_B_23_1, poseidon2_B_23_2, poseidon2_B_23_3, poseidon2_B_24_0, poseidon2_B_24_1, poseidon2_B_24_2, poseidon2_B_24_3, poseidon2_B_25_0, poseidon2_B_25_1, poseidon2_B_25_2, poseidon2_B_25_3, poseidon2_B_26_0, poseidon2_B_26_1, poseidon2_B_26_2, poseidon2_B_26_3, poseidon2_B_27_0, poseidon2_B_27_1, poseidon2_B_27_2, poseidon2_B_27_3, poseidon2_B_28_0, poseidon2_B_28_1, poseidon2_B_28_2, poseidon2_B_28_3, poseidon2_B_29_0, poseidon2_B_29_1, poseidon2_B_29_2, poseidon2_B_29_3, poseidon2_B_30_0, poseidon2_B_30_1, poseidon2_B_30_2, poseidon2_B_30_3, poseidon2_B_31_0, poseidon2_B_31_1, poseidon2_B_31_2, poseidon2_B_31_3, poseidon2_B_32_0, poseidon2_B_32_1, poseidon2_B_32_2, poseidon2_B_32_3, poseidon2_B_33_0, poseidon2_B_33_1, poseidon2_B_33_2, poseidon2_B_33_3, poseidon2_B_34_0, poseidon2_B_34_1, poseidon2_B_34_2, poseidon2_B_34_3, poseidon2_B_35_0, poseidon2_B_35_1, poseidon2_B_35_2, poseidon2_B_35_3, poseidon2_B_36_0, poseidon2_B_36_1, poseidon2_B_36_2, poseidon2_B_36_3, poseidon2_B_37_0, poseidon2_B_37_1, poseidon2_B_37_2, poseidon2_B_37_3, poseidon2_B_38_0, poseidon2_B_38_1, poseidon2_B_38_2, poseidon2_B_38_3, poseidon2_B_39_0, poseidon2_B_39_1, poseidon2_B_39_2, poseidon2_B_39_3, poseidon2_B_40_0, poseidon2_B_40_1, poseidon2_B_40_2, poseidon2_B_40_3, poseidon2_B_41_0, poseidon2_B_41_1, poseidon2_B_41_2, poseidon2_B_41_3, poseidon2_B_42_0, poseidon2_B_42_1, poseidon2_B_42_2, poseidon2_B_42_3, poseidon2_B_43_0, poseidon2_B_43_1, poseidon2_B_43_2, poseidon2_B_43_3, poseidon2_B_44_0, poseidon2_B_44_1, poseidon2_B_44_2, poseidon2_B_44_3, poseidon2_B_45_0, poseidon2_B_45_1, poseidon2_B_45_2, poseidon2_B_45_3, poseidon2_B_46_0, poseidon2_B_46_1, poseidon2_B_46_2, poseidon2_B_46_3, poseidon2_B_47_0, poseidon2_B_47_1, poseidon2_B_47_2, poseidon2_B_47_3, poseidon2_B_48_0, poseidon2_B_48_1, poseidon2_B_48_2, poseidon2_B_48_3, poseidon2_B_49_0, poseidon2_B_49_1, poseidon2_B_49_2, poseidon2_B_49_3, poseidon2_B_4_0, poseidon2_B_4_1, poseidon2_B_4_2, poseidon2_B_4_3, poseidon2_B_50_0, poseidon2_B_50_1, poseidon2_B_50_2, poseidon2_B_50_3, poseidon2_B_51_0, poseidon2_B_51_1, poseidon2_B_51_2, poseidon2_B_51_3, poseidon2_B_52_0, poseidon2_B_52_1, poseidon2_B_52_2, poseidon2_B_52_3, poseidon2_B_53_0, poseidon2_B_53_1, poseidon2_B_53_2, poseidon2_B_53_3, poseidon2_B_54_0, poseidon2_B_54_1, poseidon2_B_54_2, poseidon2_B_54_3, poseidon2_B_55_0, poseidon2_B_55_1, poseidon2_B_55_2, poseidon2_B_55_3, poseidon2_B_56_0, poseidon2_B_56_1, poseidon2_B_56_2, poseidon2_B_56_3, poseidon2_B_57_0, poseidon2_B_57_1, poseidon2_B_57_2, poseidon2_B_57_3, poseidon2_B_58_0, poseidon2_B_58_1, poseidon2_B_58_2, poseidon2_B_58_3, poseidon2_B_59_0, poseidon2_B_59_1, poseidon2_B_59_2, poseidon2_B_59_3, poseidon2_B_5_0, poseidon2_B_5_1, poseidon2_B_5_2, poseidon2_B_5_3, poseidon2_B_6_0, poseidon2_B_6_1, poseidon2_B_6_2, poseidon2_B_6_3, poseidon2_B_7_0, poseidon2_B_7_1, poseidon2_B_7_2, poseidon2_B_7_3, poseidon2_B_8_0, poseidon2_B_8_1, poseidon2_B_8_2, poseidon2_B_8_3, poseidon2_B_9_0, poseidon2_B_9_1, poseidon2_B_9_2, poseidon2_B_9_3, poseidon2_EXT_LAYER_4, poseidon2_EXT_LAYER_5, poseidon2_EXT_LAYER_6, poseidon2_EXT_LAYER_7, poseidon2_T_0_4, poseidon2_T_0_5, poseidon2_T_0_6, poseidon2_T_0_7, poseidon2_T_1_4, poseidon2_T_1_5, poseidon2_T_1_6, poseidon2_T_1_7, poseidon2_T_2_4, poseidon2_T_2_5, poseidon2_T_2_6, poseidon2_T_2_7, poseidon2_T_3_4, poseidon2_T_3_5, poseidon2_T_3_6, poseidon2_T_3_7, poseidon2_T_60_4, poseidon2_T_60_5, poseidon2_T_60_6, poseidon2_T_60_7, poseidon2_T_61_4, poseidon2_T_61_5, poseidon2_T_61_6, poseidon2_T_61_7, poseidon2_T_62_4, poseidon2_T_62_5, poseidon2_T_62_6, poseidon2_T_62_7, poseidon2_T_63_4, poseidon2_T_63_5, poseidon2_T_63_6, poseidon2_T_63_7, poseidon2_a_0, poseidon2_a_1, poseidon2_a_2, poseidon2_a_3, poseidon2_b_0, poseidon2_b_1, poseidon2_b_2, poseidon2_b_3, poseidon2_clk, poseidon2_full_a_0, poseidon2_full_a_1, poseidon2_full_a_2, poseidon2_full_a_3, poseidon2_full_b_0, poseidon2_full_b_1, poseidon2_full_b_2, poseidon2_full_b_3, poseidon2_full_clk, poseidon2_full_end_poseidon, poseidon2_full_execute_poseidon_perm, poseidon2_full_input_0, poseidon2_full_input_1, poseidon2_full_input_2, poseidon2_full_input_len, poseidon2_full_num_perm_rounds_rem, poseidon2_full_num_perm_rounds_rem_inv, poseidon2_full_output, poseidon2_full_padding, poseidon2_full_sel_merkle_tree, poseidon2_full_sel_poseidon, poseidon2_full_start_poseidon, poseidon2_input_addr, poseidon2_mem_addr_read_a, poseidon2_mem_addr_read_b, poseidon2_mem_addr_read_c, poseidon2_mem_addr_read_d, poseidon2_mem_addr_write_a, poseidon2_mem_addr_write_b, poseidon2_mem_addr_write_c, poseidon2_mem_addr_write_d, poseidon2_output_addr, poseidon2_sel_poseidon_perm, poseidon2_sel_poseidon_perm_immediate, poseidon2_sel_poseidon_perm_mem_op, poseidon2_space_id, range_check_alu_rng_chk, range_check_clk, range_check_cmp_hi_bits_rng_chk, range_check_cmp_lo_bits_rng_chk, range_check_cmp_non_ff_rng_chk, range_check_dyn_diff, range_check_dyn_rng_chk_bits, range_check_dyn_rng_chk_pow_2, range_check_gas_da_rng_chk, range_check_gas_l2_rng_chk, range_check_is_lte_u112, range_check_is_lte_u128, range_check_is_lte_u16, range_check_is_lte_u32, range_check_is_lte_u48, range_check_is_lte_u64, range_check_is_lte_u80, range_check_is_lte_u96, range_check_rng_chk_bits, range_check_sel_lookup_0, range_check_sel_lookup_1, range_check_sel_lookup_2, range_check_sel_lookup_3, range_check_sel_lookup_4, range_check_sel_lookup_5, range_check_sel_lookup_6, range_check_sel_rng_chk, range_check_u16_r0, range_check_u16_r1, range_check_u16_r2, range_check_u16_r3, range_check_u16_r4, range_check_u16_r5, range_check_u16_r6, range_check_u16_r7, range_check_value, sha256_clk, sha256_input, sha256_output, sha256_sel_sha256_compression, sha256_state, slice_addr, slice_clk, slice_cnt, slice_col_offset, slice_one_min_inv, slice_sel_cd_cpy, slice_sel_mem_active, slice_sel_return, slice_sel_start, slice_space_id, slice_val, lookup_rng_chk_pow_2_counts, lookup_rng_chk_diff_counts, lookup_rng_chk_0_counts, lookup_rng_chk_1_counts, lookup_rng_chk_2_counts, lookup_rng_chk_3_counts, lookup_rng_chk_4_counts, lookup_rng_chk_5_counts, lookup_rng_chk_6_counts, lookup_rng_chk_7_counts, lookup_mem_rng_chk_0_counts, lookup_mem_rng_chk_1_counts, lookup_mem_rng_chk_2_counts, lookup_pow_2_0_counts, lookup_pow_2_1_counts, lookup_byte_lengths_counts, lookup_byte_operations_counts, lookup_opcode_gas_counts, lookup_l2_gas_rng_chk_0_counts, lookup_l2_gas_rng_chk_1_counts, lookup_da_gas_rng_chk_0_counts, lookup_da_gas_rng_chk_1_counts, kernel_output_lookup_counts, lookup_into_kernel_counts, lookup_cd_value_counts, lookup_ret_value_counts, incl_main_tag_err_counts, incl_mem_tag_err_counts +#define DERIVED_WITNESS_ENTITIES perm_rng_non_ff_cmp_inv, perm_rng_cmp_lo_inv, perm_rng_cmp_hi_inv, perm_rng_alu_inv, perm_cmp_alu_inv, perm_l2_start_gas_inv, perm_da_start_gas_inv, perm_l2_end_gas_inv, perm_da_end_gas_inv, perm_pos_mem_read_a_inv, perm_pos_mem_read_b_inv, perm_pos_mem_read_c_inv, perm_pos_mem_read_d_inv, perm_pos_mem_write_a_inv, perm_pos_mem_write_b_inv, perm_pos_mem_write_c_inv, perm_pos_mem_write_d_inv, perm_pos2_fixed_pos2_perm_inv, perm_slice_mem_inv, perm_merkle_poseidon2_inv, perm_main_alu_inv, perm_main_bin_inv, perm_main_conv_inv, perm_main_sha256_inv, perm_main_pos2_perm_inv, perm_main_slice_inv, perm_main_mem_a_inv, perm_main_mem_b_inv, perm_main_mem_c_inv, perm_main_mem_d_inv, perm_main_mem_ind_addr_a_inv, perm_main_mem_ind_addr_b_inv, perm_main_mem_ind_addr_c_inv, perm_main_mem_ind_addr_d_inv, lookup_rng_chk_pow_2_inv, lookup_rng_chk_diff_inv, lookup_rng_chk_0_inv, lookup_rng_chk_1_inv, lookup_rng_chk_2_inv, lookup_rng_chk_3_inv, lookup_rng_chk_4_inv, lookup_rng_chk_5_inv, lookup_rng_chk_6_inv, lookup_rng_chk_7_inv, lookup_mem_rng_chk_0_inv, lookup_mem_rng_chk_1_inv, lookup_mem_rng_chk_2_inv, lookup_pow_2_0_inv, lookup_pow_2_1_inv, lookup_byte_lengths_inv, lookup_byte_operations_inv, lookup_opcode_gas_inv, lookup_l2_gas_rng_chk_0_inv, lookup_l2_gas_rng_chk_1_inv, lookup_da_gas_rng_chk_0_inv, lookup_da_gas_rng_chk_1_inv, kernel_output_lookup_inv, lookup_into_kernel_inv, lookup_cd_value_inv, lookup_ret_value_inv, incl_main_tag_err_inv, incl_mem_tag_err_inv #define SHIFTED_ENTITIES binary_acc_ia_shift, binary_acc_ib_shift, binary_acc_ic_shift, binary_mem_tag_ctr_shift, binary_op_id_shift, cmp_a_hi_shift, cmp_a_lo_shift, cmp_b_hi_shift, cmp_b_lo_shift, cmp_cmp_rng_ctr_shift, cmp_op_gt_shift, cmp_p_sub_a_hi_shift, cmp_p_sub_a_lo_shift, cmp_p_sub_b_hi_shift, cmp_p_sub_b_lo_shift, cmp_sel_rng_chk_shift, main_da_gas_remaining_shift, main_emit_l2_to_l1_msg_write_offset_shift, main_emit_note_hash_write_offset_shift, main_emit_nullifier_write_offset_shift, main_emit_unencrypted_log_write_offset_shift, main_internal_return_ptr_shift, main_l1_to_l2_msg_exists_write_offset_shift, main_l2_gas_remaining_shift, main_note_hash_exist_write_offset_shift, main_nullifier_exists_write_offset_shift, main_nullifier_non_exists_write_offset_shift, main_pc_shift, main_sel_execution_end_shift, main_sel_execution_row_shift, main_sload_write_offset_shift, main_sstore_write_offset_shift, mem_glob_addr_shift, mem_rw_shift, mem_sel_mem_shift, mem_tag_shift, mem_tsp_shift, mem_val_shift, merkle_tree_leaf_index_shift, merkle_tree_leaf_value_shift, merkle_tree_path_len_shift, poseidon2_full_a_0_shift, poseidon2_full_a_1_shift, poseidon2_full_a_2_shift, poseidon2_full_a_3_shift, poseidon2_full_execute_poseidon_perm_shift, poseidon2_full_input_0_shift, poseidon2_full_input_1_shift, poseidon2_full_input_2_shift, poseidon2_full_num_perm_rounds_rem_shift, poseidon2_full_sel_poseidon_shift, poseidon2_full_start_poseidon_shift, slice_addr_shift, slice_clk_shift, slice_cnt_shift, slice_col_offset_shift, slice_sel_cd_cpy_shift, slice_sel_mem_active_shift, slice_sel_return_shift, slice_sel_start_shift, slice_space_id_shift #define TO_BE_SHIFTED(e) e.binary_acc_ia, e.binary_acc_ib, e.binary_acc_ic, e.binary_mem_tag_ctr, e.binary_op_id, e.cmp_a_hi, e.cmp_a_lo, e.cmp_b_hi, e.cmp_b_lo, e.cmp_cmp_rng_ctr, e.cmp_op_gt, e.cmp_p_sub_a_hi, e.cmp_p_sub_a_lo, e.cmp_p_sub_b_hi, e.cmp_p_sub_b_lo, e.cmp_sel_rng_chk, e.main_da_gas_remaining, e.main_emit_l2_to_l1_msg_write_offset, e.main_emit_note_hash_write_offset, e.main_emit_nullifier_write_offset, e.main_emit_unencrypted_log_write_offset, e.main_internal_return_ptr, e.main_l1_to_l2_msg_exists_write_offset, e.main_l2_gas_remaining, e.main_note_hash_exist_write_offset, e.main_nullifier_exists_write_offset, e.main_nullifier_non_exists_write_offset, e.main_pc, e.main_sel_execution_end, e.main_sel_execution_row, e.main_sload_write_offset, e.main_sstore_write_offset, e.mem_glob_addr, e.mem_rw, e.mem_sel_mem, e.mem_tag, e.mem_tsp, e.mem_val, e.merkle_tree_leaf_index, e.merkle_tree_leaf_value, e.merkle_tree_path_len, e.poseidon2_full_a_0, e.poseidon2_full_a_1, e.poseidon2_full_a_2, e.poseidon2_full_a_3, e.poseidon2_full_execute_poseidon_perm, e.poseidon2_full_input_0, e.poseidon2_full_input_1, e.poseidon2_full_input_2, e.poseidon2_full_num_perm_rounds_rem, e.poseidon2_full_sel_poseidon, e.poseidon2_full_start_poseidon, e.slice_addr, e.slice_clk, e.slice_cnt, e.slice_col_offset, e.slice_sel_cd_cpy, e.slice_sel_mem_active, e.slice_sel_return, e.slice_sel_start, e.slice_space_id #define ALL_ENTITIES PRECOMPUTED_ENTITIES, WIRE_ENTITIES, DERIVED_WITNESS_ENTITIES, SHIFTED_ENTITIES @@ -129,12 +132,12 @@ class AvmFlavor { static constexpr bool HasZK = false; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 21; - static constexpr size_t NUM_WITNESS_ENTITIES = 752; + static constexpr size_t NUM_WITNESS_ENTITIES = 768; static constexpr size_t NUM_SHIFTED_ENTITIES = 61; static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES; // We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for // the unshifted and one for the shifted - static constexpr size_t NUM_ALL_ENTITIES = 834; + static constexpr size_t NUM_ALL_ENTITIES = 850; // The total number of witnesses including shifts and derived entities. static constexpr size_t NUM_ALL_WITNESS_ENTITIES = NUM_WITNESS_ENTITIES + NUM_SHIFTED_ENTITIES; @@ -171,7 +174,11 @@ class AvmFlavor { lookup_byte_lengths_relation, lookup_byte_operations_relation, lookup_cd_value_relation, + lookup_da_gas_rng_chk_0_relation, + lookup_da_gas_rng_chk_1_relation, lookup_into_kernel_relation, + lookup_l2_gas_rng_chk_0_relation, + lookup_l2_gas_rng_chk_1_relation, lookup_mem_rng_chk_0_relation, lookup_mem_rng_chk_1_relation, lookup_mem_rng_chk_2_relation, @@ -221,8 +228,7 @@ class AvmFlavor { perm_rng_alu_relation, perm_rng_cmp_hi_relation, perm_rng_cmp_lo_relation, - perm_rng_gas_da_relation, - perm_rng_gas_l2_relation, + perm_rng_non_ff_cmp_relation, perm_slice_mem_relation>; using LookupRelations = LookupRelations_; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.cpp index 867d8cc66bc..c38c8e849b0 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.cpp @@ -58,6 +58,7 @@ template std::vector AvmFullRow::names() "alu_cmp_gadget_gt", "alu_cmp_gadget_input_a", "alu_cmp_gadget_input_b", + "alu_cmp_gadget_non_ff_gt", "alu_cmp_gadget_result", "alu_cmp_gadget_sel", "alu_ff_tag", @@ -137,11 +138,13 @@ template std::vector AvmFullRow::names() "cmp_borrow", "cmp_clk", "cmp_cmp_rng_ctr", + "cmp_diff", "cmp_input_a", "cmp_input_b", "cmp_op_eq", "cmp_op_eq_diff_inv", "cmp_op_gt", + "cmp_op_non_ff_gt", "cmp_p_a_borrow", "cmp_p_b_borrow", "cmp_p_sub_a_hi", @@ -173,6 +176,8 @@ template std::vector AvmFullRow::names() "main_bin_op_id", "main_call_ptr", "main_da_gas_remaining", + "main_da_gas_u16_r0", + "main_da_gas_u16_r1", "main_da_out_of_gas", "main_dyn_da_gas_op_cost", "main_dyn_gas_multiplier", @@ -198,6 +203,8 @@ template std::vector AvmFullRow::names() "main_kernel_out_offset", "main_l1_to_l2_msg_exists_write_offset", "main_l2_gas_remaining", + "main_l2_gas_u16_r0", + "main_l2_gas_u16_r1", "main_l2_out_of_gas", "main_mem_addr_a", "main_mem_addr_b", @@ -235,6 +242,7 @@ template std::vector AvmFullRow::names() "main_sel_op_cast", "main_sel_op_chain_id", "main_sel_op_dagasleft", + "main_sel_op_debug_log", "main_sel_op_div", "main_sel_op_ecadd", "main_sel_op_emit_l2_to_l1_msg", @@ -662,6 +670,7 @@ template std::vector AvmFullRow::names() "range_check_clk", "range_check_cmp_hi_bits_rng_chk", "range_check_cmp_lo_bits_rng_chk", + "range_check_cmp_non_ff_rng_chk", "range_check_dyn_diff", "range_check_dyn_rng_chk_bits", "range_check_dyn_rng_chk_pow_2", @@ -709,12 +718,11 @@ template std::vector AvmFullRow::names() "slice_sel_start", "slice_space_id", "slice_val", + "perm_rng_non_ff_cmp_inv", "perm_rng_cmp_lo_inv", "perm_rng_cmp_hi_inv", "perm_rng_alu_inv", "perm_cmp_alu_inv", - "perm_rng_gas_l2_inv", - "perm_rng_gas_da_inv", "perm_l2_start_gas_inv", "perm_da_start_gas_inv", "perm_l2_end_gas_inv", @@ -762,6 +770,10 @@ template std::vector AvmFullRow::names() "lookup_byte_lengths_inv", "lookup_byte_operations_inv", "lookup_opcode_gas_inv", + "lookup_l2_gas_rng_chk_0_inv", + "lookup_l2_gas_rng_chk_1_inv", + "lookup_da_gas_rng_chk_0_inv", + "lookup_da_gas_rng_chk_1_inv", "kernel_output_lookup_inv", "lookup_into_kernel_inv", "lookup_cd_value_inv", @@ -786,6 +798,10 @@ template std::vector AvmFullRow::names() "lookup_byte_lengths_counts", "lookup_byte_operations_counts", "lookup_opcode_gas_counts", + "lookup_l2_gas_rng_chk_0_counts", + "lookup_l2_gas_rng_chk_1_counts", + "lookup_da_gas_rng_chk_0_counts", + "lookup_da_gas_rng_chk_1_counts", "kernel_output_lookup_counts", "lookup_into_kernel_counts", "lookup_cd_value_counts", @@ -836,6 +852,7 @@ template RefVector AvmFullRow::as_vector() const alu_cmp_gadget_gt, alu_cmp_gadget_input_a, alu_cmp_gadget_input_b, + alu_cmp_gadget_non_ff_gt, alu_cmp_gadget_result, alu_cmp_gadget_sel, alu_ff_tag, @@ -915,11 +932,13 @@ template RefVector AvmFullRow::as_vector() const cmp_borrow, cmp_clk, cmp_cmp_rng_ctr, + cmp_diff, cmp_input_a, cmp_input_b, cmp_op_eq, cmp_op_eq_diff_inv, cmp_op_gt, + cmp_op_non_ff_gt, cmp_p_a_borrow, cmp_p_b_borrow, cmp_p_sub_a_hi, @@ -951,6 +970,8 @@ template RefVector AvmFullRow::as_vector() const main_bin_op_id, main_call_ptr, main_da_gas_remaining, + main_da_gas_u16_r0, + main_da_gas_u16_r1, main_da_out_of_gas, main_dyn_da_gas_op_cost, main_dyn_gas_multiplier, @@ -976,6 +997,8 @@ template RefVector AvmFullRow::as_vector() const main_kernel_out_offset, main_l1_to_l2_msg_exists_write_offset, main_l2_gas_remaining, + main_l2_gas_u16_r0, + main_l2_gas_u16_r1, main_l2_out_of_gas, main_mem_addr_a, main_mem_addr_b, @@ -1013,6 +1036,7 @@ template RefVector AvmFullRow::as_vector() const main_sel_op_cast, main_sel_op_chain_id, main_sel_op_dagasleft, + main_sel_op_debug_log, main_sel_op_div, main_sel_op_ecadd, main_sel_op_emit_l2_to_l1_msg, @@ -1440,6 +1464,7 @@ template RefVector AvmFullRow::as_vector() const range_check_clk, range_check_cmp_hi_bits_rng_chk, range_check_cmp_lo_bits_rng_chk, + range_check_cmp_non_ff_rng_chk, range_check_dyn_diff, range_check_dyn_rng_chk_bits, range_check_dyn_rng_chk_pow_2, @@ -1487,12 +1512,11 @@ template RefVector AvmFullRow::as_vector() const slice_sel_start, slice_space_id, slice_val, + perm_rng_non_ff_cmp_inv, perm_rng_cmp_lo_inv, perm_rng_cmp_hi_inv, perm_rng_alu_inv, perm_cmp_alu_inv, - perm_rng_gas_l2_inv, - perm_rng_gas_da_inv, perm_l2_start_gas_inv, perm_da_start_gas_inv, perm_l2_end_gas_inv, @@ -1540,6 +1564,10 @@ template RefVector AvmFullRow::as_vector() const lookup_byte_lengths_inv, lookup_byte_operations_inv, lookup_opcode_gas_inv, + lookup_l2_gas_rng_chk_0_inv, + lookup_l2_gas_rng_chk_1_inv, + lookup_da_gas_rng_chk_0_inv, + lookup_da_gas_rng_chk_1_inv, kernel_output_lookup_inv, lookup_into_kernel_inv, lookup_cd_value_inv, @@ -1564,6 +1592,10 @@ template RefVector AvmFullRow::as_vector() const lookup_byte_lengths_counts, lookup_byte_operations_counts, lookup_opcode_gas_counts, + lookup_l2_gas_rng_chk_0_counts, + lookup_l2_gas_rng_chk_1_counts, + lookup_da_gas_rng_chk_0_counts, + lookup_da_gas_rng_chk_1_counts, kernel_output_lookup_counts, lookup_into_kernel_counts, lookup_cd_value_counts, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.hpp index d4a73c4983f..028645e90be 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/full_row.hpp @@ -49,6 +49,7 @@ template struct AvmFullRow { FF alu_cmp_gadget_gt{}; FF alu_cmp_gadget_input_a{}; FF alu_cmp_gadget_input_b{}; + FF alu_cmp_gadget_non_ff_gt{}; FF alu_cmp_gadget_result{}; FF alu_cmp_gadget_sel{}; FF alu_ff_tag{}; @@ -128,11 +129,13 @@ template struct AvmFullRow { FF cmp_borrow{}; FF cmp_clk{}; FF cmp_cmp_rng_ctr{}; + FF cmp_diff{}; FF cmp_input_a{}; FF cmp_input_b{}; FF cmp_op_eq{}; FF cmp_op_eq_diff_inv{}; FF cmp_op_gt{}; + FF cmp_op_non_ff_gt{}; FF cmp_p_a_borrow{}; FF cmp_p_b_borrow{}; FF cmp_p_sub_a_hi{}; @@ -164,6 +167,8 @@ template struct AvmFullRow { FF main_bin_op_id{}; FF main_call_ptr{}; FF main_da_gas_remaining{}; + FF main_da_gas_u16_r0{}; + FF main_da_gas_u16_r1{}; FF main_da_out_of_gas{}; FF main_dyn_da_gas_op_cost{}; FF main_dyn_gas_multiplier{}; @@ -189,6 +194,8 @@ template struct AvmFullRow { FF main_kernel_out_offset{}; FF main_l1_to_l2_msg_exists_write_offset{}; FF main_l2_gas_remaining{}; + FF main_l2_gas_u16_r0{}; + FF main_l2_gas_u16_r1{}; FF main_l2_out_of_gas{}; FF main_mem_addr_a{}; FF main_mem_addr_b{}; @@ -226,6 +233,7 @@ template struct AvmFullRow { FF main_sel_op_cast{}; FF main_sel_op_chain_id{}; FF main_sel_op_dagasleft{}; + FF main_sel_op_debug_log{}; FF main_sel_op_div{}; FF main_sel_op_ecadd{}; FF main_sel_op_emit_l2_to_l1_msg{}; @@ -653,6 +661,7 @@ template struct AvmFullRow { FF range_check_clk{}; FF range_check_cmp_hi_bits_rng_chk{}; FF range_check_cmp_lo_bits_rng_chk{}; + FF range_check_cmp_non_ff_rng_chk{}; FF range_check_dyn_diff{}; FF range_check_dyn_rng_chk_bits{}; FF range_check_dyn_rng_chk_pow_2{}; @@ -700,12 +709,11 @@ template struct AvmFullRow { FF slice_sel_start{}; FF slice_space_id{}; FF slice_val{}; + FF perm_rng_non_ff_cmp_inv{}; FF perm_rng_cmp_lo_inv{}; FF perm_rng_cmp_hi_inv{}; FF perm_rng_alu_inv{}; FF perm_cmp_alu_inv{}; - FF perm_rng_gas_l2_inv{}; - FF perm_rng_gas_da_inv{}; FF perm_l2_start_gas_inv{}; FF perm_da_start_gas_inv{}; FF perm_l2_end_gas_inv{}; @@ -753,6 +761,10 @@ template struct AvmFullRow { FF lookup_byte_lengths_inv{}; FF lookup_byte_operations_inv{}; FF lookup_opcode_gas_inv{}; + FF lookup_l2_gas_rng_chk_0_inv{}; + FF lookup_l2_gas_rng_chk_1_inv{}; + FF lookup_da_gas_rng_chk_0_inv{}; + FF lookup_da_gas_rng_chk_1_inv{}; FF kernel_output_lookup_inv{}; FF lookup_into_kernel_inv{}; FF lookup_cd_value_inv{}; @@ -777,6 +789,10 @@ template struct AvmFullRow { FF lookup_byte_lengths_counts{}; FF lookup_byte_operations_counts{}; FF lookup_opcode_gas_counts{}; + FF lookup_l2_gas_rng_chk_0_counts{}; + FF lookup_l2_gas_rng_chk_1_counts{}; + FF lookup_da_gas_rng_chk_0_counts{}; + FF lookup_da_gas_rng_chk_1_counts{}; FF kernel_output_lookup_counts{}; FF lookup_into_kernel_counts{}; FF lookup_cd_value_counts{}; @@ -787,7 +803,7 @@ template struct AvmFullRow { RefVector as_vector() const; static std::vector names(); - static constexpr size_t SIZE = 773; + static constexpr size_t SIZE = 789; }; template std::ostream& operator<<(std::ostream& os, AvmFullRow const& row); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/alu.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/alu.hpp index abc0a44ddb7..bde7a1f816a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/alu.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/alu.hpp @@ -10,10 +10,10 @@ template class aluImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 4, 4, - 2, 2, 3, 3, 4, 4, 5, 5, 5, 4, 7, 3, 3, - 3, 5, 5, 4, 7, 4, 3, 3, 3, 2, 3, 3, 3, - 4, 3, 3, 3, 3, 3, 4, 4, 4, 5 }; + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 4, 4, + 3, 3, 2, 3, 3, 4, 4, 5, 5, 5, 4, 7, 3, + 3, 3, 5, 5, 4, 7, 4, 3, 3, 3, 2, 3, 3, + 3, 4, 3, 3, 3, 3, 3, 4, 4, 4, 5 }; template void static accumulate(ContainerOverSubrelations& evals, @@ -28,6 +28,9 @@ template class aluImpl { const auto constants_MEM_TAG_U32 = FF(4); const auto constants_MEM_TAG_U64 = FF(5); const auto constants_MEM_TAG_U128 = FF(6); + const auto alu_CMP_GADGET_GT = + ((((new_term.alu_op_lt + new_term.alu_op_lte) + new_term.alu_op_div) + new_term.alu_op_shr) + + new_term.alu_op_shl); const auto alu_MAX_BITS = ((((((new_term.alu_u1_tag * FF(1)) + (new_term.alu_u8_tag * FF(8))) + (new_term.alu_u16_tag * FF(16))) + (new_term.alu_u32_tag * FF(32))) + @@ -175,242 +178,247 @@ template class aluImpl { } { using Accumulator = typename std::tuple_element_t<13, ContainerOverSubrelations>; - auto tmp = (new_term.alu_cmp_gadget_gt - - ((((new_term.alu_op_lt + new_term.alu_op_lte) + new_term.alu_op_div) + new_term.alu_op_shr) + - new_term.alu_op_shl)); + auto tmp = (new_term.alu_cmp_gadget_gt - (alu_CMP_GADGET_GT * new_term.alu_ff_tag)); tmp *= scaling_factor; std::get<13>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<14, ContainerOverSubrelations>; - auto tmp = (new_term.alu_cmp_gadget_sel - (new_term.alu_cmp_gadget_gt + new_term.alu_op_eq)); + auto tmp = (new_term.alu_cmp_gadget_non_ff_gt - (alu_CMP_GADGET_GT * (FF(1) - new_term.alu_ff_tag))); tmp *= scaling_factor; std::get<14>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<15, ContainerOverSubrelations>; - auto tmp = (((new_term.alu_a_lo * new_term.alu_b_hi) + (new_term.alu_b_lo * new_term.alu_a_hi)) - - (new_term.alu_partial_prod_lo + (alu_LIMB_BITS_POW * new_term.alu_partial_prod_hi))); + auto tmp = (new_term.alu_cmp_gadget_sel - + ((new_term.alu_cmp_gadget_gt + new_term.alu_op_eq) + new_term.alu_cmp_gadget_non_ff_gt)); tmp *= scaling_factor; std::get<15>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<16, ContainerOverSubrelations>; - auto tmp = (new_term.alu_cf * (FF(1) - new_term.alu_cf)); + auto tmp = (((new_term.alu_a_lo * new_term.alu_b_hi) + (new_term.alu_b_lo * new_term.alu_a_hi)) - + (new_term.alu_partial_prod_lo + (alu_LIMB_BITS_POW * new_term.alu_partial_prod_hi))); tmp *= scaling_factor; std::get<16>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<17, ContainerOverSubrelations>; - auto tmp = (new_term.alu_op_add * ((alu_RESULT - new_term.alu_ic) - (new_term.alu_cf * alu_MAX_BITS_POW))); + auto tmp = (new_term.alu_cf * (FF(1) - new_term.alu_cf)); tmp *= scaling_factor; std::get<17>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<18, ContainerOverSubrelations>; - auto tmp = (new_term.alu_op_sub * ((alu_RESULT - new_term.alu_ic) + (new_term.alu_cf * alu_MAX_BITS_POW))); + auto tmp = (new_term.alu_op_add * ((alu_RESULT - new_term.alu_ic) - (new_term.alu_cf * alu_MAX_BITS_POW))); tmp *= scaling_factor; std::get<18>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<19, ContainerOverSubrelations>; - auto tmp = - ((new_term.alu_ff_tag * new_term.alu_op_mul) * ((new_term.alu_ia * new_term.alu_ib) - new_term.alu_ic)); + auto tmp = (new_term.alu_op_sub * ((alu_RESULT - new_term.alu_ic) + (new_term.alu_cf * alu_MAX_BITS_POW))); tmp *= scaling_factor; std::get<19>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<20, ContainerOverSubrelations>; - auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_mul) * - ((new_term.alu_ia - new_term.alu_a_lo) - (alu_LIMB_BITS_POW * new_term.alu_a_hi))); + auto tmp = + ((new_term.alu_ff_tag * new_term.alu_op_mul) * ((new_term.alu_ia * new_term.alu_ib) - new_term.alu_ic)); tmp *= scaling_factor; std::get<20>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<21, ContainerOverSubrelations>; auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_mul) * - ((new_term.alu_ib - new_term.alu_b_lo) - (alu_LIMB_BITS_POW * new_term.alu_b_hi))); + ((new_term.alu_ia - new_term.alu_a_lo) - (alu_LIMB_BITS_POW * new_term.alu_a_hi))); tmp *= scaling_factor; std::get<21>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<22, ContainerOverSubrelations>; - auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_mul) * (new_term.alu_ic - new_term.alu_c_lo)); + auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_mul) * + ((new_term.alu_ib - new_term.alu_b_lo) - (alu_LIMB_BITS_POW * new_term.alu_b_hi))); tmp *= scaling_factor; std::get<22>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<23, ContainerOverSubrelations>; - auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_mul) * - (alu_PRODUCT - (new_term.alu_c_lo + (alu_MAX_BITS_POW * new_term.alu_c_hi)))); + auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_mul) * (new_term.alu_ic - new_term.alu_c_lo)); tmp *= scaling_factor; std::get<23>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<24, ContainerOverSubrelations>; - auto tmp = (new_term.alu_op_div * (new_term.alu_cmp_gadget_input_a - new_term.alu_ib)); + auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_mul) * + (alu_PRODUCT - (new_term.alu_c_lo + (alu_MAX_BITS_POW * new_term.alu_c_hi)))); tmp *= scaling_factor; std::get<24>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<25, ContainerOverSubrelations>; - auto tmp = (new_term.alu_op_div * (new_term.alu_cmp_gadget_input_b - new_term.alu_remainder)); + auto tmp = (new_term.alu_op_div * (new_term.alu_cmp_gadget_input_a - new_term.alu_ib)); tmp *= scaling_factor; std::get<25>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<26, ContainerOverSubrelations>; - auto tmp = (new_term.alu_op_div * (new_term.alu_cmp_gadget_result - FF(1))); + auto tmp = (new_term.alu_op_div * (new_term.alu_cmp_gadget_input_b - new_term.alu_remainder)); tmp *= scaling_factor; std::get<26>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<27, ContainerOverSubrelations>; - auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_div) * - ((new_term.alu_ib - new_term.alu_a_lo) - (alu_LIMB_BITS_POW * new_term.alu_a_hi))); + auto tmp = (new_term.alu_op_div * (new_term.alu_cmp_gadget_result - FF(1))); tmp *= scaling_factor; std::get<27>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<28, ContainerOverSubrelations>; auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_div) * - ((new_term.alu_ic - new_term.alu_b_lo) - (alu_LIMB_BITS_POW * new_term.alu_b_hi))); + ((new_term.alu_ib - new_term.alu_a_lo) - (alu_LIMB_BITS_POW * new_term.alu_a_hi))); tmp *= scaling_factor; std::get<28>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<29, ContainerOverSubrelations>; - auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_div) * (new_term.alu_ia - new_term.alu_c_lo)); + auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_div) * + ((new_term.alu_ic - new_term.alu_b_lo) - (alu_LIMB_BITS_POW * new_term.alu_b_hi))); tmp *= scaling_factor; std::get<29>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<30, ContainerOverSubrelations>; - auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_div) * - (alu_PRODUCT - - ((new_term.alu_c_lo - new_term.alu_remainder) + (alu_MAX_BITS_POW * new_term.alu_c_hi)))); + auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_div) * (new_term.alu_ia - new_term.alu_c_lo)); tmp *= scaling_factor; std::get<30>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<31, ContainerOverSubrelations>; - auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_not) * - ((new_term.alu_ia + new_term.alu_ic) - alu_UINT_MAX)); + auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_div) * + (alu_PRODUCT - + ((new_term.alu_c_lo - new_term.alu_remainder) + (alu_MAX_BITS_POW * new_term.alu_c_hi)))); tmp *= scaling_factor; std::get<31>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<32, ContainerOverSubrelations>; - auto tmp = (new_term.alu_op_eq * (new_term.alu_ia - new_term.alu_cmp_gadget_input_a)); + auto tmp = (((FF(1) - new_term.alu_ff_tag) * new_term.alu_op_not) * + ((new_term.alu_ia + new_term.alu_ic) - alu_UINT_MAX)); tmp *= scaling_factor; std::get<32>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<33, ContainerOverSubrelations>; - auto tmp = (new_term.alu_op_eq * (new_term.alu_ib - new_term.alu_cmp_gadget_input_b)); + auto tmp = (new_term.alu_op_eq * (new_term.alu_ia - new_term.alu_cmp_gadget_input_a)); tmp *= scaling_factor; std::get<33>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<34, ContainerOverSubrelations>; - auto tmp = (new_term.alu_op_eq * (new_term.alu_ic - new_term.alu_cmp_gadget_result)); + auto tmp = (new_term.alu_op_eq * (new_term.alu_ib - new_term.alu_cmp_gadget_input_b)); tmp *= scaling_factor; std::get<34>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<35, ContainerOverSubrelations>; - auto tmp = (new_term.alu_sel_cmp - (new_term.alu_op_lt + new_term.alu_op_lte)); + auto tmp = (new_term.alu_op_eq * (new_term.alu_ic - new_term.alu_cmp_gadget_result)); tmp *= scaling_factor; std::get<35>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<36, ContainerOverSubrelations>; - auto tmp = ((new_term.alu_op_lt * (new_term.alu_ib - new_term.alu_cmp_gadget_input_a)) + - (new_term.alu_op_lte * (new_term.alu_ia - new_term.alu_cmp_gadget_input_a))); + auto tmp = (new_term.alu_sel_cmp - (new_term.alu_op_lt + new_term.alu_op_lte)); tmp *= scaling_factor; std::get<36>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<37, ContainerOverSubrelations>; - auto tmp = ((new_term.alu_op_lt * (new_term.alu_ia - new_term.alu_cmp_gadget_input_b)) + - (new_term.alu_op_lte * (new_term.alu_ib - new_term.alu_cmp_gadget_input_b))); + auto tmp = ((new_term.alu_op_lt * (new_term.alu_ib - new_term.alu_cmp_gadget_input_a)) + + (new_term.alu_op_lte * (new_term.alu_ia - new_term.alu_cmp_gadget_input_a))); tmp *= scaling_factor; std::get<37>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<38, ContainerOverSubrelations>; - auto tmp = ((new_term.alu_op_lte * ((FF(1) - new_term.alu_cmp_gadget_result) - new_term.alu_ic)) + - (new_term.alu_op_lt * (new_term.alu_cmp_gadget_result - new_term.alu_ic))); + auto tmp = ((new_term.alu_op_lt * (new_term.alu_ia - new_term.alu_cmp_gadget_input_b)) + + (new_term.alu_op_lte * (new_term.alu_ib - new_term.alu_cmp_gadget_input_b))); tmp *= scaling_factor; std::get<38>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<39, ContainerOverSubrelations>; - auto tmp = (new_term.alu_op_cast * - ((new_term.alu_ia - new_term.alu_a_lo) - (alu_MAX_BITS_POW * new_term.alu_a_hi))); + auto tmp = ((new_term.alu_op_lte * ((FF(1) - new_term.alu_cmp_gadget_result) - new_term.alu_ic)) + + (new_term.alu_op_lt * (new_term.alu_cmp_gadget_result - new_term.alu_ic))); tmp *= scaling_factor; std::get<39>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<40, ContainerOverSubrelations>; - auto tmp = (new_term.alu_op_cast * (new_term.alu_ic - new_term.alu_a_lo)); + auto tmp = (new_term.alu_op_cast * + ((new_term.alu_ia - new_term.alu_a_lo) - (alu_MAX_BITS_POW * new_term.alu_a_hi))); tmp *= scaling_factor; std::get<40>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<41, ContainerOverSubrelations>; - auto tmp = - ((new_term.alu_op_shl + new_term.alu_op_shr) * (new_term.alu_cmp_gadget_input_a - new_term.alu_ib)); + auto tmp = (new_term.alu_op_cast * (new_term.alu_ic - new_term.alu_a_lo)); tmp *= scaling_factor; std::get<41>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<42, ContainerOverSubrelations>; - auto tmp = ((new_term.alu_op_shl + new_term.alu_op_shr) * - (new_term.alu_cmp_gadget_input_b - (alu_MAX_BITS - FF(1)))); + auto tmp = + ((new_term.alu_op_shl + new_term.alu_op_shr) * (new_term.alu_cmp_gadget_input_a - new_term.alu_ib)); tmp *= scaling_factor; std::get<42>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<43, ContainerOverSubrelations>; auto tmp = ((new_term.alu_op_shl + new_term.alu_op_shr) * - (new_term.alu_zero_shift - new_term.alu_cmp_gadget_result)); + (new_term.alu_cmp_gadget_input_b - (alu_MAX_BITS - FF(1)))); tmp *= scaling_factor; std::get<43>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<44, ContainerOverSubrelations>; - auto tmp = - (new_term.alu_sel_shift_which - ((new_term.alu_op_shr + new_term.alu_op_shl) * alu_NON_TRIVIAL_SHIFT)); + auto tmp = ((new_term.alu_op_shl + new_term.alu_op_shr) * + (new_term.alu_zero_shift - new_term.alu_cmp_gadget_result)); tmp *= scaling_factor; std::get<44>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<45, ContainerOverSubrelations>; - auto tmp = (new_term.alu_op_shr * - ((new_term.alu_ia - new_term.alu_a_lo) - (new_term.alu_b_pow * new_term.alu_a_hi))); + auto tmp = + (new_term.alu_sel_shift_which - ((new_term.alu_op_shr + new_term.alu_op_shl) * alu_NON_TRIVIAL_SHIFT)); tmp *= scaling_factor; std::get<45>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<46, ContainerOverSubrelations>; - auto tmp = (new_term.alu_op_shr * (new_term.alu_ic - (new_term.alu_a_hi * alu_NON_TRIVIAL_SHIFT))); + auto tmp = (new_term.alu_op_shr * + ((new_term.alu_ia - new_term.alu_a_lo) - (new_term.alu_b_pow * new_term.alu_a_hi))); tmp *= scaling_factor; std::get<46>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<47, ContainerOverSubrelations>; - auto tmp = (new_term.alu_op_shl * ((new_term.alu_ia - new_term.alu_a_lo) - - (new_term.alu_max_bits_sub_b_pow * new_term.alu_a_hi))); + auto tmp = (new_term.alu_op_shr * (new_term.alu_ic - (new_term.alu_a_hi * alu_NON_TRIVIAL_SHIFT))); tmp *= scaling_factor; std::get<47>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<48, ContainerOverSubrelations>; + auto tmp = (new_term.alu_op_shl * ((new_term.alu_ia - new_term.alu_a_lo) - + (new_term.alu_max_bits_sub_b_pow * new_term.alu_a_hi))); + tmp *= scaling_factor; + std::get<48>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<49, ContainerOverSubrelations>; auto tmp = (new_term.alu_op_shl * (new_term.alu_ic - ((new_term.alu_a_lo * new_term.alu_b_pow) * alu_NON_TRIVIAL_SHIFT))); tmp *= scaling_factor; - std::get<48>(evals) += typename Accumulator::View(tmp); + std::get<49>(evals) += typename Accumulator::View(tmp); } } }; @@ -422,13 +430,13 @@ template class alu : public Relation> { static std::string get_subrelation_label(size_t index) { switch (index) { - case 19: + case 20: return "ALU_MULTIPLICATION_FF"; - case 23: + case 24: return "ALU_PROD_MUL"; - case 30: - return "DIVISION_RELATION"; case 31: + return "DIVISION_RELATION"; + case 32: return "ALU_OP_NOT"; } return std::to_string(index); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/cmp.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/cmp.hpp index ba42e4f4bfb..51748bd9661 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/cmp.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/cmp.hpp @@ -10,8 +10,8 @@ template class cmpImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 2, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, - 3, 2, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3 }; + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 4, 2, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 5, + 5, 3, 2, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3 }; template void static accumulate(ContainerOverSubrelations& evals, @@ -19,6 +19,8 @@ template class cmpImpl { [[maybe_unused]] const RelationParameters&, [[maybe_unused]] const FF& scaling_factor) { + const auto cmp_A_GT_B = ((new_term.cmp_input_a - new_term.cmp_input_b) - FF(1)); + const auto cmp_B_GTE_A = (new_term.cmp_input_b - new_term.cmp_input_a); const auto cmp_DIFF = (new_term.cmp_input_a - new_term.cmp_input_b); const auto cmp_POW_128 = FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }); const auto cmp_P_LO = FF(uint256_t{ 4891460686036598784UL, 2896914383306846353UL, 0UL, 0UL }); @@ -39,176 +41,183 @@ template class cmpImpl { } { using Accumulator = typename std::tuple_element_t<1, ContainerOverSubrelations>; - auto tmp = (new_term.cmp_sel_cmp - (new_term.cmp_op_eq + new_term.cmp_op_gt)); + auto tmp = (new_term.cmp_op_non_ff_gt * ((new_term.cmp_diff - (cmp_A_GT_B * new_term.cmp_result)) - + (cmp_B_GTE_A * (FF(1) - new_term.cmp_result)))); tmp *= scaling_factor; std::get<1>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<2, ContainerOverSubrelations>; - auto tmp = (new_term.cmp_result * (FF(1) - new_term.cmp_result)); + auto tmp = (new_term.cmp_sel_cmp - ((new_term.cmp_op_eq + new_term.cmp_op_gt) + new_term.cmp_op_non_ff_gt)); tmp *= scaling_factor; std::get<2>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<3, ContainerOverSubrelations>; - auto tmp = - (new_term.cmp_op_eq * (((cmp_DIFF * ((new_term.cmp_result * (FF(1) - new_term.cmp_op_eq_diff_inv)) + - new_term.cmp_op_eq_diff_inv)) - - FF(1)) + - new_term.cmp_result)); + auto tmp = (new_term.cmp_result * (FF(1) - new_term.cmp_result)); tmp *= scaling_factor; std::get<3>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<4, ContainerOverSubrelations>; auto tmp = - (new_term.cmp_op_gt * (new_term.cmp_input_a - (new_term.cmp_a_lo + (cmp_POW_128 * new_term.cmp_a_hi)))); + (new_term.cmp_op_eq * (((cmp_DIFF * ((new_term.cmp_result * (FF(1) - new_term.cmp_op_eq_diff_inv)) + + new_term.cmp_op_eq_diff_inv)) - + FF(1)) + + new_term.cmp_result)); tmp *= scaling_factor; std::get<4>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<5, ContainerOverSubrelations>; auto tmp = - (new_term.cmp_op_gt * (new_term.cmp_input_b - (new_term.cmp_b_lo + (cmp_POW_128 * new_term.cmp_b_hi)))); + (new_term.cmp_op_gt * (new_term.cmp_input_a - (new_term.cmp_a_lo + (cmp_POW_128 * new_term.cmp_a_hi)))); tmp *= scaling_factor; std::get<5>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<6, ContainerOverSubrelations>; - auto tmp = (new_term.cmp_p_a_borrow * (FF(1) - new_term.cmp_p_a_borrow)); + auto tmp = + (new_term.cmp_op_gt * (new_term.cmp_input_b - (new_term.cmp_b_lo + (cmp_POW_128 * new_term.cmp_b_hi)))); tmp *= scaling_factor; std::get<6>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<7, ContainerOverSubrelations>; - auto tmp = (new_term.cmp_op_gt * (new_term.cmp_p_sub_a_lo - ((cmp_P_LO - new_term.cmp_a_lo) + - (new_term.cmp_p_a_borrow * cmp_POW_128)))); + auto tmp = (new_term.cmp_p_a_borrow * (FF(1) - new_term.cmp_p_a_borrow)); tmp *= scaling_factor; std::get<7>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<8, ContainerOverSubrelations>; - auto tmp = (new_term.cmp_op_gt * - (new_term.cmp_p_sub_a_hi - ((cmp_P_HI - new_term.cmp_a_hi) - new_term.cmp_p_a_borrow))); + auto tmp = (new_term.cmp_op_gt * (new_term.cmp_p_sub_a_lo - ((cmp_P_LO - new_term.cmp_a_lo) + + (new_term.cmp_p_a_borrow * cmp_POW_128)))); tmp *= scaling_factor; std::get<8>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<9, ContainerOverSubrelations>; - auto tmp = (new_term.cmp_p_b_borrow * (FF(1) - new_term.cmp_p_b_borrow)); + auto tmp = (new_term.cmp_op_gt * + (new_term.cmp_p_sub_a_hi - ((cmp_P_HI - new_term.cmp_a_hi) - new_term.cmp_p_a_borrow))); tmp *= scaling_factor; std::get<9>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<10, ContainerOverSubrelations>; - auto tmp = (new_term.cmp_op_gt * (new_term.cmp_p_sub_b_lo - ((cmp_P_LO - new_term.cmp_b_lo) + - (new_term.cmp_p_b_borrow * cmp_POW_128)))); + auto tmp = (new_term.cmp_p_b_borrow * (FF(1) - new_term.cmp_p_b_borrow)); tmp *= scaling_factor; std::get<10>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<11, ContainerOverSubrelations>; - auto tmp = (new_term.cmp_op_gt * - (new_term.cmp_p_sub_b_hi - ((cmp_P_HI - new_term.cmp_b_hi) - new_term.cmp_p_b_borrow))); + auto tmp = (new_term.cmp_op_gt * (new_term.cmp_p_sub_b_lo - ((cmp_P_LO - new_term.cmp_b_lo) + + (new_term.cmp_p_b_borrow * cmp_POW_128)))); tmp *= scaling_factor; std::get<11>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<12, ContainerOverSubrelations>; - auto tmp = (new_term.cmp_op_gt * (new_term.cmp_res_lo - - ((cmp_A_SUB_B_LO * cmp_IS_GT) + (cmp_B_SUB_A_LO * (FF(1) - cmp_IS_GT))))); + auto tmp = (new_term.cmp_op_gt * + (new_term.cmp_p_sub_b_hi - ((cmp_P_HI - new_term.cmp_b_hi) - new_term.cmp_p_b_borrow))); tmp *= scaling_factor; std::get<12>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<13, ContainerOverSubrelations>; - auto tmp = (new_term.cmp_op_gt * (new_term.cmp_res_hi - - ((cmp_A_SUB_B_HI * cmp_IS_GT) + (cmp_B_SUB_A_HI * (FF(1) - cmp_IS_GT))))); + auto tmp = (new_term.cmp_op_gt * (new_term.cmp_res_lo - + ((cmp_A_SUB_B_LO * cmp_IS_GT) + (cmp_B_SUB_A_LO * (FF(1) - cmp_IS_GT))))); tmp *= scaling_factor; std::get<13>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<14, ContainerOverSubrelations>; - auto tmp = (new_term.cmp_sel_rng_chk * (FF(1) - new_term.cmp_sel_rng_chk)); + auto tmp = (new_term.cmp_op_gt * (new_term.cmp_res_hi - + ((cmp_A_SUB_B_HI * cmp_IS_GT) + (cmp_B_SUB_A_HI * (FF(1) - cmp_IS_GT))))); tmp *= scaling_factor; std::get<14>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<15, ContainerOverSubrelations>; - auto tmp = (new_term.cmp_sel_rng_chk_shift - (new_term.cmp_shift_sel + new_term.cmp_op_gt_shift)); + auto tmp = (new_term.cmp_sel_rng_chk * (FF(1) - new_term.cmp_sel_rng_chk)); tmp *= scaling_factor; std::get<15>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<16, ContainerOverSubrelations>; - auto tmp = - (((new_term.cmp_cmp_rng_ctr_shift - new_term.cmp_cmp_rng_ctr) + FF(1)) * new_term.cmp_cmp_rng_ctr); + auto tmp = (new_term.cmp_sel_rng_chk_shift - (new_term.cmp_shift_sel + new_term.cmp_op_gt_shift)); tmp *= scaling_factor; std::get<16>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<17, ContainerOverSubrelations>; - auto tmp = (new_term.cmp_op_gt * (new_term.cmp_cmp_rng_ctr - FF(4))); + auto tmp = + (((new_term.cmp_cmp_rng_ctr_shift - new_term.cmp_cmp_rng_ctr) + FF(1)) * new_term.cmp_cmp_rng_ctr); tmp *= scaling_factor; std::get<17>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<18, ContainerOverSubrelations>; - auto tmp = ((new_term.cmp_cmp_rng_ctr * - (((FF(1) - new_term.cmp_shift_sel) * (FF(1) - new_term.cmp_op_eq_diff_inv)) + - new_term.cmp_op_eq_diff_inv)) - - new_term.cmp_shift_sel); + auto tmp = (new_term.cmp_op_gt * (new_term.cmp_cmp_rng_ctr - FF(4))); tmp *= scaling_factor; std::get<18>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<19, ContainerOverSubrelations>; - auto tmp = ((new_term.cmp_a_lo_shift - new_term.cmp_b_lo) * new_term.cmp_shift_sel); + auto tmp = ((new_term.cmp_cmp_rng_ctr * + (((FF(1) - new_term.cmp_shift_sel) * (FF(1) - new_term.cmp_op_eq_diff_inv)) + + new_term.cmp_op_eq_diff_inv)) - + new_term.cmp_shift_sel); tmp *= scaling_factor; std::get<19>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<20, ContainerOverSubrelations>; - auto tmp = ((new_term.cmp_a_hi_shift - new_term.cmp_b_hi) * new_term.cmp_shift_sel); + auto tmp = ((new_term.cmp_a_lo_shift - new_term.cmp_b_lo) * new_term.cmp_shift_sel); tmp *= scaling_factor; std::get<20>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<21, ContainerOverSubrelations>; - auto tmp = ((new_term.cmp_b_lo_shift - new_term.cmp_p_sub_a_lo) * new_term.cmp_shift_sel); + auto tmp = ((new_term.cmp_a_hi_shift - new_term.cmp_b_hi) * new_term.cmp_shift_sel); tmp *= scaling_factor; std::get<21>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<22, ContainerOverSubrelations>; - auto tmp = ((new_term.cmp_b_hi_shift - new_term.cmp_p_sub_a_hi) * new_term.cmp_shift_sel); + auto tmp = ((new_term.cmp_b_lo_shift - new_term.cmp_p_sub_a_lo) * new_term.cmp_shift_sel); tmp *= scaling_factor; std::get<22>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<23, ContainerOverSubrelations>; - auto tmp = ((new_term.cmp_p_sub_a_lo_shift - new_term.cmp_p_sub_b_lo) * new_term.cmp_shift_sel); + auto tmp = ((new_term.cmp_b_hi_shift - new_term.cmp_p_sub_a_hi) * new_term.cmp_shift_sel); tmp *= scaling_factor; std::get<23>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<24, ContainerOverSubrelations>; - auto tmp = ((new_term.cmp_p_sub_a_hi_shift - new_term.cmp_p_sub_b_hi) * new_term.cmp_shift_sel); + auto tmp = ((new_term.cmp_p_sub_a_lo_shift - new_term.cmp_p_sub_b_lo) * new_term.cmp_shift_sel); tmp *= scaling_factor; std::get<24>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<25, ContainerOverSubrelations>; - auto tmp = ((new_term.cmp_p_sub_b_lo_shift - new_term.cmp_res_lo) * new_term.cmp_shift_sel); + auto tmp = ((new_term.cmp_p_sub_a_hi_shift - new_term.cmp_p_sub_b_hi) * new_term.cmp_shift_sel); tmp *= scaling_factor; std::get<25>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<26, ContainerOverSubrelations>; - auto tmp = ((new_term.cmp_p_sub_b_hi_shift - new_term.cmp_res_hi) * new_term.cmp_shift_sel); + auto tmp = ((new_term.cmp_p_sub_b_lo_shift - new_term.cmp_res_lo) * new_term.cmp_shift_sel); tmp *= scaling_factor; std::get<26>(evals) += typename Accumulator::View(tmp); } + { + using Accumulator = typename std::tuple_element_t<27, ContainerOverSubrelations>; + auto tmp = ((new_term.cmp_p_sub_b_hi_shift - new_term.cmp_res_hi) * new_term.cmp_shift_sel); + tmp *= scaling_factor; + std::get<27>(evals) += typename Accumulator::View(tmp); + } } }; @@ -219,39 +228,39 @@ template class cmp : public Relation> { static std::string get_subrelation_label(size_t index) { switch (index) { - case 2: - return "CMP_RES_IS_BOOL"; case 3: - return "CMP_OP_EQ"; + return "CMP_RES_IS_BOOL"; case 4: - return "INPUT_DECOMP_1"; + return "CMP_OP_EQ"; case 5: + return "INPUT_DECOMP_1"; + case 6: return "INPUT_DECOMP_2"; - case 7: - return "SUB_LO_1"; case 8: + return "SUB_LO_1"; + case 9: return "SUB_HI_1"; - case 10: - return "SUB_LO_2"; case 11: - return "SUB_HI_2"; + return "SUB_LO_2"; case 12: - return "RES_LO"; + return "SUB_HI_2"; case 13: + return "RES_LO"; + case 14: return "RES_HI"; - case 16: - return "CMP_CTR_REL_1"; case 17: - return "CMP_CTR_REL_2"; + return "CMP_CTR_REL_1"; case 18: - return "CTR_NON_ZERO_REL"; + return "CMP_CTR_REL_2"; case 19: + return "CTR_NON_ZERO_REL"; + case 20: return "SHIFT_RELS_0"; - case 21: + case 22: return "SHIFT_RELS_1"; - case 23: + case 24: return "SHIFT_RELS_2"; - case 25: + case 26: return "SHIFT_RELS_3"; } return std::to_string(index); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/gas.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/gas.hpp index a2a23059087..57c198089db 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/gas.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/gas.hpp @@ -10,7 +10,7 @@ template class gasImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 3, 3, 3, 3, 5, 5, 4, 4 }; + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 3, 3, 3, 3, 5, 5, 4, 4, 2, 2 }; template void static accumulate(ContainerOverSubrelations& evals, @@ -94,6 +94,20 @@ template class gasImpl { tmp *= scaling_factor; std::get<9>(evals) += typename Accumulator::View(tmp); } + { + using Accumulator = typename std::tuple_element_t<10, ContainerOverSubrelations>; + auto tmp = (new_term.main_abs_l2_rem_gas - + (new_term.main_l2_gas_u16_r0 + (new_term.main_l2_gas_u16_r1 * FF(65536)))); + tmp *= scaling_factor; + std::get<10>(evals) += typename Accumulator::View(tmp); + } + { + using Accumulator = typename std::tuple_element_t<11, ContainerOverSubrelations>; + auto tmp = (new_term.main_abs_da_rem_gas - + (new_term.main_da_gas_u16_r0 + (new_term.main_da_gas_u16_r1 * FF(65536)))); + tmp *= scaling_factor; + std::get<11>(evals) += typename Accumulator::View(tmp); + } } }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/kernel.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/kernel.hpp index a18277a8633..efc5b9f621b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/kernel.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/kernel.hpp @@ -12,7 +12,7 @@ template class kernelImpl { static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4 }; template void static accumulate(ContainerOverSubrelations& evals, @@ -364,7 +364,8 @@ template class kernelImpl { } { using Accumulator = typename std::tuple_element_t<41, ContainerOverSubrelations>; - auto tmp = (main_KERNEL_OUTPUT_SELECTORS * (FF(1) - new_term.main_sel_q_kernel_output_lookup)); + auto tmp = ((main_KERNEL_OUTPUT_SELECTORS * (FF(1) - new_term.main_sel_q_kernel_output_lookup)) * + (FF(1) - new_term.main_op_err)); tmp *= scaling_factor; std::get<41>(evals) += typename Accumulator::View(tmp); } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookup_da_gas_rng_chk_0.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookup_da_gas_rng_chk_0.hpp new file mode 100644 index 00000000000..8fcb4503428 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookup_da_gas_rng_chk_0.hpp @@ -0,0 +1,64 @@ +// AUTOGENERATED FILE +#pragma once + +#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" + +#include +#include + +namespace bb { + +class lookup_da_gas_rng_chk_0_lookup_settings { + public: + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + static constexpr size_t LOOKUP_TUPLE_SIZE = 1; + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + static constexpr size_t READ_TERM_DEGREE = 0; + static constexpr size_t WRITE_TERM_DEGREE = 0; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.main_is_gas_accounted == 1 || in.main_sel_rng_16 == 1); + } + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in.main_is_gas_accounted); + const auto is_table_entry = View(in.main_sel_rng_16); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return std::forward_as_tuple(in.lookup_da_gas_rng_chk_0_inv, + in.lookup_da_gas_rng_chk_0_counts, + in.main_is_gas_accounted, + in.main_sel_rng_16, + in.main_da_gas_u16_r0, + in.main_clk); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple(in.lookup_da_gas_rng_chk_0_inv, + in.lookup_da_gas_rng_chk_0_counts, + in.main_is_gas_accounted, + in.main_sel_rng_16, + in.main_da_gas_u16_r0, + in.main_clk); + } +}; + +template +class lookup_da_gas_rng_chk_0_relation : public GenericLookupRelation { + public: + static constexpr const char* NAME = "LOOKUP_DA_GAS_RNG_CHK_0"; +}; +template using lookup_da_gas_rng_chk_0 = GenericLookup; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookup_da_gas_rng_chk_1.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookup_da_gas_rng_chk_1.hpp new file mode 100644 index 00000000000..6886d88b660 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookup_da_gas_rng_chk_1.hpp @@ -0,0 +1,64 @@ +// AUTOGENERATED FILE +#pragma once + +#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" + +#include +#include + +namespace bb { + +class lookup_da_gas_rng_chk_1_lookup_settings { + public: + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + static constexpr size_t LOOKUP_TUPLE_SIZE = 1; + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + static constexpr size_t READ_TERM_DEGREE = 0; + static constexpr size_t WRITE_TERM_DEGREE = 0; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.main_is_gas_accounted == 1 || in.main_sel_rng_16 == 1); + } + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in.main_is_gas_accounted); + const auto is_table_entry = View(in.main_sel_rng_16); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return std::forward_as_tuple(in.lookup_da_gas_rng_chk_1_inv, + in.lookup_da_gas_rng_chk_1_counts, + in.main_is_gas_accounted, + in.main_sel_rng_16, + in.main_da_gas_u16_r1, + in.main_clk); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple(in.lookup_da_gas_rng_chk_1_inv, + in.lookup_da_gas_rng_chk_1_counts, + in.main_is_gas_accounted, + in.main_sel_rng_16, + in.main_da_gas_u16_r1, + in.main_clk); + } +}; + +template +class lookup_da_gas_rng_chk_1_relation : public GenericLookupRelation { + public: + static constexpr const char* NAME = "LOOKUP_DA_GAS_RNG_CHK_1"; +}; +template using lookup_da_gas_rng_chk_1 = GenericLookup; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookup_l2_gas_rng_chk_0.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookup_l2_gas_rng_chk_0.hpp new file mode 100644 index 00000000000..b3ea9f7257e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookup_l2_gas_rng_chk_0.hpp @@ -0,0 +1,64 @@ +// AUTOGENERATED FILE +#pragma once + +#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" + +#include +#include + +namespace bb { + +class lookup_l2_gas_rng_chk_0_lookup_settings { + public: + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + static constexpr size_t LOOKUP_TUPLE_SIZE = 1; + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + static constexpr size_t READ_TERM_DEGREE = 0; + static constexpr size_t WRITE_TERM_DEGREE = 0; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.main_is_gas_accounted == 1 || in.main_sel_rng_16 == 1); + } + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in.main_is_gas_accounted); + const auto is_table_entry = View(in.main_sel_rng_16); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return std::forward_as_tuple(in.lookup_l2_gas_rng_chk_0_inv, + in.lookup_l2_gas_rng_chk_0_counts, + in.main_is_gas_accounted, + in.main_sel_rng_16, + in.main_l2_gas_u16_r0, + in.main_clk); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple(in.lookup_l2_gas_rng_chk_0_inv, + in.lookup_l2_gas_rng_chk_0_counts, + in.main_is_gas_accounted, + in.main_sel_rng_16, + in.main_l2_gas_u16_r0, + in.main_clk); + } +}; + +template +class lookup_l2_gas_rng_chk_0_relation : public GenericLookupRelation { + public: + static constexpr const char* NAME = "LOOKUP_L2_GAS_RNG_CHK_0"; +}; +template using lookup_l2_gas_rng_chk_0 = GenericLookup; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookup_l2_gas_rng_chk_1.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookup_l2_gas_rng_chk_1.hpp new file mode 100644 index 00000000000..5f5afa771e2 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookup_l2_gas_rng_chk_1.hpp @@ -0,0 +1,64 @@ +// AUTOGENERATED FILE +#pragma once + +#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" + +#include +#include + +namespace bb { + +class lookup_l2_gas_rng_chk_1_lookup_settings { + public: + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = { 0 }; + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = { 0 }; + static constexpr size_t LOOKUP_TUPLE_SIZE = 1; + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = 4; + static constexpr size_t READ_TERM_DEGREE = 0; + static constexpr size_t WRITE_TERM_DEGREE = 0; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.main_is_gas_accounted == 1 || in.main_sel_rng_16 == 1); + } + + template + static inline auto compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + const auto is_operation = View(in.main_is_gas_accounted); + const auto is_table_entry = View(in.main_sel_rng_16); + return (is_operation + is_table_entry - is_operation * is_table_entry); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return std::forward_as_tuple(in.lookup_l2_gas_rng_chk_1_inv, + in.lookup_l2_gas_rng_chk_1_counts, + in.main_is_gas_accounted, + in.main_sel_rng_16, + in.main_l2_gas_u16_r1, + in.main_clk); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple(in.lookup_l2_gas_rng_chk_1_inv, + in.lookup_l2_gas_rng_chk_1_counts, + in.main_is_gas_accounted, + in.main_sel_rng_16, + in.main_l2_gas_u16_r1, + in.main_clk); + } +}; + +template +class lookup_l2_gas_rng_chk_1_relation : public GenericLookupRelation { + public: + static constexpr const char* NAME = "LOOKUP_L2_GAS_RNG_CHK_1"; +}; +template using lookup_l2_gas_rng_chk_1 = GenericLookup; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/main.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/main.hpp index 4278b2cbb29..841dfc71ba6 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/main.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/main.hpp @@ -10,11 +10,11 @@ template class mainImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { - 2, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, 3, 3, 3, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 4, 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, 2, 2 + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { + 2, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, 3, 3, 3, 4, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 2, 3 }; template @@ -72,18 +72,20 @@ template class mainImpl { new_term.main_sel_op_ecadd) + new_term.main_sel_op_msm); const auto main_SEL_ALL_MEMORY = (new_term.main_sel_op_mov + new_term.main_sel_op_set); - const auto main_OPCODE_SELECTORS = ((((((((((((new_term.main_sel_op_fdiv + new_term.main_sel_op_calldata_copy) + - new_term.main_sel_op_get_contract_instance) + - new_term.main_sel_op_returndata_size) + - new_term.main_sel_op_returndata_copy) + - main_SEL_ALL_ALU) + - main_SEL_ALL_BINARY) + - main_SEL_ALL_MEMORY) + - main_SEL_ALL_GADGET) + - main_KERNEL_INPUT_SELECTORS) + - main_KERNEL_OUTPUT_SELECTORS) + - main_SEL_ALL_LEFTGAS) + - main_SEL_ALL_CTRL_FLOW); + const auto main_OPCODE_SELECTORS = + (((((((((((((new_term.main_sel_op_fdiv + new_term.main_sel_op_calldata_copy) + + new_term.main_sel_op_get_contract_instance) + + new_term.main_sel_op_returndata_size) + + new_term.main_sel_op_returndata_copy) + + new_term.main_sel_op_debug_log) + + main_SEL_ALL_ALU) + + main_SEL_ALL_BINARY) + + main_SEL_ALL_MEMORY) + + main_SEL_ALL_GADGET) + + main_KERNEL_INPUT_SELECTORS) + + main_KERNEL_OUTPUT_SELECTORS) + + main_SEL_ALL_LEFTGAS) + + main_SEL_ALL_CTRL_FLOW); const auto main_CUR_AND_NEXT_ARE_MAIN = (new_term.main_sel_execution_row * new_term.main_sel_execution_row_shift); @@ -249,540 +251,544 @@ template class mainImpl { } { using Accumulator = typename std::tuple_element_t<26, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_radix_be * (FF(1) - new_term.main_sel_op_radix_be)); + auto tmp = (new_term.main_sel_op_debug_log * (FF(1) - new_term.main_sel_op_debug_log)); tmp *= scaling_factor; std::get<26>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<27, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_sha256 * (FF(1) - new_term.main_sel_op_sha256)); + auto tmp = (new_term.main_sel_op_radix_be * (FF(1) - new_term.main_sel_op_radix_be)); tmp *= scaling_factor; std::get<27>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<28, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_poseidon2 * (FF(1) - new_term.main_sel_op_poseidon2)); + auto tmp = (new_term.main_sel_op_sha256 * (FF(1) - new_term.main_sel_op_sha256)); tmp *= scaling_factor; std::get<28>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<29, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_keccak * (FF(1) - new_term.main_sel_op_keccak)); + auto tmp = (new_term.main_sel_op_poseidon2 * (FF(1) - new_term.main_sel_op_poseidon2)); tmp *= scaling_factor; std::get<29>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<30, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_ecadd * (FF(1) - new_term.main_sel_op_ecadd)); + auto tmp = (new_term.main_sel_op_keccak * (FF(1) - new_term.main_sel_op_keccak)); tmp *= scaling_factor; std::get<30>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<31, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_msm * (FF(1) - new_term.main_sel_op_msm)); + auto tmp = (new_term.main_sel_op_ecadd * (FF(1) - new_term.main_sel_op_ecadd)); tmp *= scaling_factor; std::get<31>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<32, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_add * (FF(1) - new_term.main_sel_op_add)); + auto tmp = (new_term.main_sel_op_msm * (FF(1) - new_term.main_sel_op_msm)); tmp *= scaling_factor; std::get<32>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<33, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_sub * (FF(1) - new_term.main_sel_op_sub)); + auto tmp = (new_term.main_sel_op_add * (FF(1) - new_term.main_sel_op_add)); tmp *= scaling_factor; std::get<33>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<34, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_mul * (FF(1) - new_term.main_sel_op_mul)); + auto tmp = (new_term.main_sel_op_sub * (FF(1) - new_term.main_sel_op_sub)); tmp *= scaling_factor; std::get<34>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<35, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_div * (FF(1) - new_term.main_sel_op_div)); + auto tmp = (new_term.main_sel_op_mul * (FF(1) - new_term.main_sel_op_mul)); tmp *= scaling_factor; std::get<35>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<36, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_fdiv * (FF(1) - new_term.main_sel_op_fdiv)); + auto tmp = (new_term.main_sel_op_div * (FF(1) - new_term.main_sel_op_div)); tmp *= scaling_factor; std::get<36>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<37, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_not * (FF(1) - new_term.main_sel_op_not)); + auto tmp = (new_term.main_sel_op_fdiv * (FF(1) - new_term.main_sel_op_fdiv)); tmp *= scaling_factor; std::get<37>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<38, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_eq * (FF(1) - new_term.main_sel_op_eq)); + auto tmp = (new_term.main_sel_op_not * (FF(1) - new_term.main_sel_op_not)); tmp *= scaling_factor; std::get<38>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<39, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_and * (FF(1) - new_term.main_sel_op_and)); + auto tmp = (new_term.main_sel_op_eq * (FF(1) - new_term.main_sel_op_eq)); tmp *= scaling_factor; std::get<39>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<40, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_or * (FF(1) - new_term.main_sel_op_or)); + auto tmp = (new_term.main_sel_op_and * (FF(1) - new_term.main_sel_op_and)); tmp *= scaling_factor; std::get<40>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<41, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_xor * (FF(1) - new_term.main_sel_op_xor)); + auto tmp = (new_term.main_sel_op_or * (FF(1) - new_term.main_sel_op_or)); tmp *= scaling_factor; std::get<41>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<42, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_cast * (FF(1) - new_term.main_sel_op_cast)); + auto tmp = (new_term.main_sel_op_xor * (FF(1) - new_term.main_sel_op_xor)); tmp *= scaling_factor; std::get<42>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<43, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_lt * (FF(1) - new_term.main_sel_op_lt)); + auto tmp = (new_term.main_sel_op_cast * (FF(1) - new_term.main_sel_op_cast)); tmp *= scaling_factor; std::get<43>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<44, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_lte * (FF(1) - new_term.main_sel_op_lte)); + auto tmp = (new_term.main_sel_op_lt * (FF(1) - new_term.main_sel_op_lt)); tmp *= scaling_factor; std::get<44>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<45, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_shl * (FF(1) - new_term.main_sel_op_shl)); + auto tmp = (new_term.main_sel_op_lte * (FF(1) - new_term.main_sel_op_lte)); tmp *= scaling_factor; std::get<45>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<46, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_shr * (FF(1) - new_term.main_sel_op_shr)); + auto tmp = (new_term.main_sel_op_shl * (FF(1) - new_term.main_sel_op_shl)); tmp *= scaling_factor; std::get<46>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<47, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_call * (FF(1) - new_term.main_sel_op_internal_call)); + auto tmp = (new_term.main_sel_op_shr * (FF(1) - new_term.main_sel_op_shr)); tmp *= scaling_factor; std::get<47>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<48, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_return * (FF(1) - new_term.main_sel_op_internal_return)); + auto tmp = (new_term.main_sel_op_internal_call * (FF(1) - new_term.main_sel_op_internal_call)); tmp *= scaling_factor; std::get<48>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<49, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_jump * (FF(1) - new_term.main_sel_op_jump)); + auto tmp = (new_term.main_sel_op_internal_return * (FF(1) - new_term.main_sel_op_internal_return)); tmp *= scaling_factor; std::get<49>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<50, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_jumpi * (FF(1) - new_term.main_sel_op_jumpi)); + auto tmp = (new_term.main_sel_op_jump * (FF(1) - new_term.main_sel_op_jump)); tmp *= scaling_factor; std::get<50>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<51, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_external_call * (FF(1) - new_term.main_sel_op_external_call)); + auto tmp = (new_term.main_sel_op_jumpi * (FF(1) - new_term.main_sel_op_jumpi)); tmp *= scaling_factor; std::get<51>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<52, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_static_call * (FF(1) - new_term.main_sel_op_static_call)); + auto tmp = (new_term.main_sel_op_external_call * (FF(1) - new_term.main_sel_op_external_call)); tmp *= scaling_factor; std::get<52>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<53, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_calldata_copy * (FF(1) - new_term.main_sel_op_calldata_copy)); + auto tmp = (new_term.main_sel_op_static_call * (FF(1) - new_term.main_sel_op_static_call)); tmp *= scaling_factor; std::get<53>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<54, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_returndata_size * (FF(1) - new_term.main_sel_op_returndata_size)); + auto tmp = (new_term.main_sel_op_calldata_copy * (FF(1) - new_term.main_sel_op_calldata_copy)); tmp *= scaling_factor; std::get<54>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<55, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_returndata_copy * (FF(1) - new_term.main_sel_op_returndata_copy)); + auto tmp = (new_term.main_sel_op_returndata_size * (FF(1) - new_term.main_sel_op_returndata_size)); tmp *= scaling_factor; std::get<55>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<56, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_external_return * (FF(1) - new_term.main_sel_op_external_return)); + auto tmp = (new_term.main_sel_op_returndata_copy * (FF(1) - new_term.main_sel_op_returndata_copy)); tmp *= scaling_factor; std::get<56>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<57, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_external_revert * (FF(1) - new_term.main_sel_op_external_revert)); + auto tmp = (new_term.main_sel_op_external_return * (FF(1) - new_term.main_sel_op_external_return)); tmp *= scaling_factor; std::get<57>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<58, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_set * (FF(1) - new_term.main_sel_op_set)); + auto tmp = (new_term.main_sel_op_external_revert * (FF(1) - new_term.main_sel_op_external_revert)); tmp *= scaling_factor; std::get<58>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<59, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_mov * (FF(1) - new_term.main_sel_op_mov)); + auto tmp = (new_term.main_sel_op_set * (FF(1) - new_term.main_sel_op_set)); tmp *= scaling_factor; std::get<59>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<60, ContainerOverSubrelations>; - auto tmp = (new_term.main_op_err * (FF(1) - new_term.main_op_err)); + auto tmp = (new_term.main_sel_op_mov * (FF(1) - new_term.main_sel_op_mov)); tmp *= scaling_factor; std::get<60>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<61, ContainerOverSubrelations>; - auto tmp = (new_term.main_tag_err * (FF(1) - new_term.main_tag_err)); + auto tmp = (new_term.main_op_err * (FF(1) - new_term.main_op_err)); tmp *= scaling_factor; std::get<61>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<62, ContainerOverSubrelations>; - auto tmp = (new_term.main_id_zero * (FF(1) - new_term.main_id_zero)); + auto tmp = (new_term.main_tag_err * (FF(1) - new_term.main_tag_err)); tmp *= scaling_factor; std::get<62>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<63, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mem_op_a * (FF(1) - new_term.main_sel_mem_op_a)); + auto tmp = (new_term.main_id_zero * (FF(1) - new_term.main_id_zero)); tmp *= scaling_factor; std::get<63>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<64, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mem_op_b * (FF(1) - new_term.main_sel_mem_op_b)); + auto tmp = (new_term.main_sel_mem_op_a * (FF(1) - new_term.main_sel_mem_op_a)); tmp *= scaling_factor; std::get<64>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<65, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mem_op_c * (FF(1) - new_term.main_sel_mem_op_c)); + auto tmp = (new_term.main_sel_mem_op_b * (FF(1) - new_term.main_sel_mem_op_b)); tmp *= scaling_factor; std::get<65>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<66, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mem_op_d * (FF(1) - new_term.main_sel_mem_op_d)); + auto tmp = (new_term.main_sel_mem_op_c * (FF(1) - new_term.main_sel_mem_op_c)); tmp *= scaling_factor; std::get<66>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<67, ContainerOverSubrelations>; - auto tmp = (new_term.main_rwa * (FF(1) - new_term.main_rwa)); + auto tmp = (new_term.main_sel_mem_op_d * (FF(1) - new_term.main_sel_mem_op_d)); tmp *= scaling_factor; std::get<67>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<68, ContainerOverSubrelations>; - auto tmp = (new_term.main_rwb * (FF(1) - new_term.main_rwb)); + auto tmp = (new_term.main_rwa * (FF(1) - new_term.main_rwa)); tmp *= scaling_factor; std::get<68>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<69, ContainerOverSubrelations>; - auto tmp = (new_term.main_rwc * (FF(1) - new_term.main_rwc)); + auto tmp = (new_term.main_rwb * (FF(1) - new_term.main_rwb)); tmp *= scaling_factor; std::get<69>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<70, ContainerOverSubrelations>; - auto tmp = (new_term.main_rwd * (FF(1) - new_term.main_rwd)); + auto tmp = (new_term.main_rwc * (FF(1) - new_term.main_rwc)); tmp *= scaling_factor; std::get<70>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<71, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_resolve_ind_addr_a * (FF(1) - new_term.main_sel_resolve_ind_addr_a)); + auto tmp = (new_term.main_rwd * (FF(1) - new_term.main_rwd)); tmp *= scaling_factor; std::get<71>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<72, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_resolve_ind_addr_b * (FF(1) - new_term.main_sel_resolve_ind_addr_b)); + auto tmp = (new_term.main_sel_resolve_ind_addr_a * (FF(1) - new_term.main_sel_resolve_ind_addr_a)); tmp *= scaling_factor; std::get<72>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<73, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_resolve_ind_addr_c * (FF(1) - new_term.main_sel_resolve_ind_addr_c)); + auto tmp = (new_term.main_sel_resolve_ind_addr_b * (FF(1) - new_term.main_sel_resolve_ind_addr_b)); tmp *= scaling_factor; std::get<73>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<74, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_resolve_ind_addr_d * (FF(1) - new_term.main_sel_resolve_ind_addr_d)); + auto tmp = (new_term.main_sel_resolve_ind_addr_c * (FF(1) - new_term.main_sel_resolve_ind_addr_c)); tmp *= scaling_factor; std::get<74>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<75, ContainerOverSubrelations>; - auto tmp = (((new_term.main_sel_op_eq + new_term.main_sel_op_lte) + new_term.main_sel_op_lt) * - (new_term.main_w_in_tag - constants_MEM_TAG_U1)); + auto tmp = (new_term.main_sel_resolve_ind_addr_d * (FF(1) - new_term.main_sel_resolve_ind_addr_d)); tmp *= scaling_factor; std::get<75>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<76, ContainerOverSubrelations>; - auto tmp = ((new_term.main_sel_op_fdiv * (FF(1) - new_term.main_op_err)) * - ((new_term.main_ic * new_term.main_ib) - new_term.main_ia)); + auto tmp = (((new_term.main_sel_op_eq + new_term.main_sel_op_lte) + new_term.main_sel_op_lt) * + (new_term.main_w_in_tag - constants_MEM_TAG_U1)); tmp *= scaling_factor; std::get<76>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<77, ContainerOverSubrelations>; - auto tmp = ((new_term.main_sel_op_fdiv + new_term.main_sel_op_div) * - (((new_term.main_ib * new_term.main_inv) - FF(1)) + new_term.main_op_err)); + auto tmp = ((new_term.main_sel_op_fdiv * (FF(1) - new_term.main_op_err)) * + ((new_term.main_ic * new_term.main_ib) - new_term.main_ia)); tmp *= scaling_factor; std::get<77>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<78, ContainerOverSubrelations>; - auto tmp = (((new_term.main_sel_op_fdiv + new_term.main_sel_op_div) * new_term.main_op_err) * - (FF(1) - new_term.main_inv)); + auto tmp = ((new_term.main_sel_op_fdiv + new_term.main_sel_op_div) * + (((new_term.main_ib * new_term.main_inv) - FF(1)) + new_term.main_op_err)); tmp *= scaling_factor; std::get<78>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<79, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_fdiv * (new_term.main_r_in_tag - constants_MEM_TAG_FF)); + auto tmp = (((new_term.main_sel_op_fdiv + new_term.main_sel_op_div) * new_term.main_op_err) * + (FF(1) - new_term.main_inv)); tmp *= scaling_factor; std::get<79>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<80, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_fdiv * (new_term.main_w_in_tag - constants_MEM_TAG_FF)); + auto tmp = (new_term.main_sel_op_fdiv * (new_term.main_r_in_tag - constants_MEM_TAG_FF)); tmp *= scaling_factor; std::get<80>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<81, ContainerOverSubrelations>; - auto tmp = (new_term.main_op_err * (((new_term.main_sel_op_fdiv + new_term.main_sel_op_div) + - new_term.main_sel_op_get_contract_instance) - - FF(1))); + auto tmp = (new_term.main_sel_op_fdiv * (new_term.main_w_in_tag - constants_MEM_TAG_FF)); tmp *= scaling_factor; std::get<81>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<82, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_jump * (new_term.main_pc_shift - new_term.main_ia)); + auto tmp = (new_term.main_tag_err * (FF(1) - new_term.main_op_err)); tmp *= scaling_factor; std::get<82>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<83, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_jumpi * - (((FF(1) - new_term.main_id_zero) * (new_term.main_pc_shift - new_term.main_ia)) + - (new_term.main_id_zero * ((new_term.main_pc_shift - new_term.main_pc) - FF(8))))); + auto tmp = (new_term.main_sel_op_jump * (new_term.main_pc_shift - new_term.main_ia)); tmp *= scaling_factor; std::get<83>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<84, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_call * - (new_term.main_internal_return_ptr_shift - (new_term.main_internal_return_ptr + FF(1)))); + auto tmp = (new_term.main_sel_op_jumpi * + (((FF(1) - new_term.main_id_zero) * (new_term.main_pc_shift - new_term.main_ia)) + + (new_term.main_id_zero * ((new_term.main_pc_shift - new_term.main_pc) - FF(8))))); tmp *= scaling_factor; std::get<84>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<85, ContainerOverSubrelations>; - auto tmp = - (new_term.main_sel_op_internal_call * (new_term.main_internal_return_ptr - new_term.main_mem_addr_b)); + auto tmp = (new_term.main_sel_op_internal_call * + (new_term.main_internal_return_ptr_shift - (new_term.main_internal_return_ptr + FF(1)))); tmp *= scaling_factor; std::get<85>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<86, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_call * (new_term.main_pc_shift - new_term.main_ia)); + auto tmp = + (new_term.main_sel_op_internal_call * (new_term.main_internal_return_ptr - new_term.main_mem_addr_b)); tmp *= scaling_factor; std::get<86>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<87, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_call * ((new_term.main_pc + FF(5)) - new_term.main_ib)); + auto tmp = (new_term.main_sel_op_internal_call * (new_term.main_pc_shift - new_term.main_ia)); tmp *= scaling_factor; std::get<87>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<88, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_call * (new_term.main_rwb - FF(1))); + auto tmp = (new_term.main_sel_op_internal_call * ((new_term.main_pc + FF(5)) - new_term.main_ib)); tmp *= scaling_factor; std::get<88>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<89, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_call * (new_term.main_sel_mem_op_b - FF(1))); + auto tmp = (new_term.main_sel_op_internal_call * (new_term.main_rwb - FF(1))); tmp *= scaling_factor; std::get<89>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<90, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_return * - (new_term.main_internal_return_ptr_shift - (new_term.main_internal_return_ptr - FF(1)))); + auto tmp = (new_term.main_sel_op_internal_call * (new_term.main_sel_mem_op_b - FF(1))); tmp *= scaling_factor; std::get<90>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<91, ContainerOverSubrelations>; auto tmp = (new_term.main_sel_op_internal_return * - ((new_term.main_internal_return_ptr - FF(1)) - new_term.main_mem_addr_a)); + (new_term.main_internal_return_ptr_shift - (new_term.main_internal_return_ptr - FF(1)))); tmp *= scaling_factor; std::get<91>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<92, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_return * (new_term.main_pc_shift - new_term.main_ia)); + auto tmp = (new_term.main_sel_op_internal_return * + ((new_term.main_internal_return_ptr - FF(1)) - new_term.main_mem_addr_a)); tmp *= scaling_factor; std::get<92>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<93, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_return * new_term.main_rwa); + auto tmp = (new_term.main_sel_op_internal_return * (new_term.main_pc_shift - new_term.main_ia)); tmp *= scaling_factor; std::get<93>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<94, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_internal_return * (new_term.main_sel_mem_op_a - FF(1))); + auto tmp = (new_term.main_sel_op_internal_return * new_term.main_rwa); tmp *= scaling_factor; std::get<94>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<95, ContainerOverSubrelations>; - auto tmp = ((main_CUR_AND_NEXT_ARE_MAIN * (FF(1) - main_SEL_ALL_CTRL_FLOW)) * - (new_term.main_internal_return_ptr_shift - new_term.main_internal_return_ptr)); + auto tmp = (new_term.main_sel_op_internal_return * (new_term.main_sel_mem_op_a - FF(1))); tmp *= scaling_factor; std::get<95>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<96, ContainerOverSubrelations>; - auto tmp = ((new_term.main_sel_op_internal_call + new_term.main_sel_op_internal_return) * - (new_term.main_space_id - constants_misc_INTERNAL_CALL_SPACE_ID)); + auto tmp = ((main_CUR_AND_NEXT_ARE_MAIN * (FF(1) - main_SEL_ALL_CTRL_FLOW)) * + (new_term.main_internal_return_ptr_shift - new_term.main_internal_return_ptr)); tmp *= scaling_factor; std::get<96>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<97, ContainerOverSubrelations>; - auto tmp = (((FF(1) - new_term.main_sel_op_internal_call) - new_term.main_sel_op_internal_return) * - (new_term.main_call_ptr - new_term.main_space_id)); + auto tmp = ((new_term.main_sel_op_internal_call + new_term.main_sel_op_internal_return) * + (new_term.main_space_id - constants_misc_INTERNAL_CALL_SPACE_ID)); tmp *= scaling_factor; std::get<97>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<98, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_jumpi * - (((new_term.main_id * new_term.main_inv) - FF(1)) + new_term.main_id_zero)); + auto tmp = (((FF(1) - new_term.main_sel_op_internal_call) - new_term.main_sel_op_internal_return) * + (new_term.main_call_ptr - new_term.main_space_id)); tmp *= scaling_factor; std::get<98>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<99, ContainerOverSubrelations>; - auto tmp = ((new_term.main_sel_op_jumpi * new_term.main_id_zero) * (FF(1) - new_term.main_inv)); + auto tmp = (new_term.main_sel_op_jumpi * + (((new_term.main_id * new_term.main_inv) - FF(1)) + new_term.main_id_zero)); tmp *= scaling_factor; std::get<99>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<100, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mov_ia_to_ic - (new_term.main_sel_op_mov * (FF(1) - new_term.main_id_zero))); + auto tmp = ((new_term.main_sel_op_jumpi * new_term.main_id_zero) * (FF(1) - new_term.main_inv)); tmp *= scaling_factor; std::get<100>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<101, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mov_ia_to_ic * (new_term.main_ia - new_term.main_ic)); + auto tmp = (new_term.main_sel_mov_ia_to_ic - (new_term.main_sel_op_mov * (FF(1) - new_term.main_id_zero))); tmp *= scaling_factor; std::get<101>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<102, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_mov_ib_to_ic * (new_term.main_ib - new_term.main_ic)); + auto tmp = (new_term.main_sel_mov_ia_to_ic * (new_term.main_ia - new_term.main_ic)); tmp *= scaling_factor; std::get<102>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<103, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_mov * (new_term.main_r_in_tag - new_term.main_w_in_tag)); + auto tmp = (new_term.main_sel_mov_ib_to_ic * (new_term.main_ib - new_term.main_ic)); tmp *= scaling_factor; std::get<103>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<104, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_alu - - ((main_SEL_ALL_ALU * (FF(1) - new_term.main_tag_err)) * (FF(1) - new_term.main_op_err))); + auto tmp = (new_term.main_sel_op_mov * (new_term.main_r_in_tag - new_term.main_w_in_tag)); tmp *= scaling_factor; std::get<104>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<105, ContainerOverSubrelations>; - auto tmp = (main_SEL_ALU_R_TAG * (new_term.main_alu_in_tag - new_term.main_r_in_tag)); + auto tmp = (new_term.main_sel_alu - (main_SEL_ALL_ALU * (FF(1) - new_term.main_op_err))); tmp *= scaling_factor; std::get<105>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<106, ContainerOverSubrelations>; - auto tmp = (main_SEL_ALU_W_TAG * (new_term.main_alu_in_tag - new_term.main_w_in_tag)); + auto tmp = (main_SEL_ALU_R_TAG * (new_term.main_alu_in_tag - new_term.main_r_in_tag)); tmp *= scaling_factor; std::get<106>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<107, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_l2gasleft * (new_term.main_ia - new_term.main_l2_gas_remaining_shift)); + auto tmp = (main_SEL_ALU_W_TAG * (new_term.main_alu_in_tag - new_term.main_w_in_tag)); tmp *= scaling_factor; std::get<107>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<108, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_op_dagasleft * (new_term.main_ia - new_term.main_da_gas_remaining_shift)); + auto tmp = (new_term.main_sel_op_l2gasleft * (new_term.main_ia - new_term.main_l2_gas_remaining_shift)); tmp *= scaling_factor; std::get<108>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<109, ContainerOverSubrelations>; - auto tmp = ((new_term.main_ib * (FF(1) - new_term.main_tag_err)) * - ((new_term.main_sel_op_calldata_copy + new_term.main_sel_op_external_return) - - new_term.main_sel_slice_gadget)); + auto tmp = (new_term.main_sel_op_dagasleft * (new_term.main_ia - new_term.main_da_gas_remaining_shift)); tmp *= scaling_factor; std::get<109>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<110, ContainerOverSubrelations>; - auto tmp = (new_term.main_bin_op_id - (new_term.main_sel_op_or + (FF(2) * new_term.main_sel_op_xor))); + auto tmp = ((new_term.main_ib * (FF(1) - new_term.main_op_err)) * + ((new_term.main_sel_op_calldata_copy + new_term.main_sel_op_external_return) - + new_term.main_sel_slice_gadget)); tmp *= scaling_factor; std::get<110>(evals) += typename Accumulator::View(tmp); } { using Accumulator = typename std::tuple_element_t<111, ContainerOverSubrelations>; - auto tmp = (new_term.main_sel_bin - - ((new_term.main_sel_op_and + new_term.main_sel_op_or) + new_term.main_sel_op_xor)); + auto tmp = (new_term.main_bin_op_id - (new_term.main_sel_op_or + (FF(2) * new_term.main_sel_op_xor))); tmp *= scaling_factor; std::get<111>(evals) += typename Accumulator::View(tmp); } + { + using Accumulator = typename std::tuple_element_t<112, ContainerOverSubrelations>; + auto tmp = (new_term.main_sel_bin - + (((new_term.main_sel_op_and + new_term.main_sel_op_or) + new_term.main_sel_op_xor) * + (FF(1) - new_term.main_op_err))); + tmp *= scaling_factor; + std::get<112>(evals) += typename Accumulator::View(tmp); + } } }; @@ -795,51 +801,51 @@ template class main : public Relation> { switch (index) { case 0: return "OPCODE_SELECTORS"; - case 75: - return "OUTPUT_U1"; case 76: - return "SUBOP_FDIV"; + return "OUTPUT_U1"; case 77: - return "SUBOP_FDIV_ZERO_ERR1"; + return "SUBOP_FDIV"; case 78: - return "SUBOP_FDIV_ZERO_ERR2"; + return "SUBOP_FDIV_ZERO_ERR1"; case 79: - return "SUBOP_FDIV_R_IN_TAG_FF"; + return "SUBOP_FDIV_ZERO_ERR2"; case 80: - return "SUBOP_FDIV_W_IN_TAG_FF"; + return "SUBOP_FDIV_R_IN_TAG_FF"; case 81: - return "SUBOP_ERROR_RELEVANT_OP"; + return "SUBOP_FDIV_W_IN_TAG_FF"; case 82: - return "PC_JUMP"; + return "TAG_ERR_IMPLIES_OP_ERR"; case 83: - return "PC_JUMPI"; + return "PC_JUMP"; case 84: + return "PC_JUMPI"; + case 85: return "RETURN_POINTER_INCREMENT"; - case 90: + case 91: return "RETURN_POINTER_DECREMENT"; - case 95: - return "INTERNAL_RETURN_POINTER_CONSISTENCY"; case 96: - return "SPACE_ID_INTERNAL"; + return "INTERNAL_RETURN_POINTER_CONSISTENCY"; case 97: - return "SPACE_ID_STANDARD_OPCODES"; + return "SPACE_ID_INTERNAL"; case 98: - return "JMP_CONDITION_RES_1"; + return "SPACE_ID_STANDARD_OPCODES"; case 99: + return "JMP_CONDITION_RES_1"; + case 100: return "JMP_CONDITION_RES_2"; - case 101: - return "MOV_SAME_VALUE_A"; case 102: - return "MOV_SAME_VALUE_B"; + return "MOV_SAME_VALUE_A"; case 103: + return "MOV_SAME_VALUE_B"; + case 104: return "MOV_MAIN_SAME_TAG"; - case 107: - return "L2GASLEFT"; case 108: + return "L2GASLEFT"; + case 109: return "DAGASLEFT"; - case 110: - return "BIN_SEL_1"; case 111: + return "BIN_SEL_1"; + case 112: return "BIN_SEL_2"; } return std::to_string(index); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perm_cmp_alu.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perm_cmp_alu.hpp index fd66a4aed55..a7b3db16d10 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perm_cmp_alu.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perm_cmp_alu.hpp @@ -11,7 +11,7 @@ namespace bb { class perm_cmp_alu_permutation_settings { public: // This constant defines how many columns are bundled together to form each set. - constexpr static size_t COLUMNS_PER_SET = 6; + constexpr static size_t COLUMNS_PER_SET = 7; template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) { @@ -30,12 +30,14 @@ class perm_cmp_alu_permutation_settings { in.cmp_result, in.cmp_op_eq, in.cmp_op_gt, + in.cmp_op_non_ff_gt, in.alu_clk, in.alu_cmp_gadget_input_a, in.alu_cmp_gadget_input_b, in.alu_cmp_gadget_result, in.alu_op_eq, - in.alu_cmp_gadget_gt); + in.alu_cmp_gadget_gt, + in.alu_cmp_gadget_non_ff_gt); } template static inline auto get_nonconst_entities(AllEntities& in) @@ -50,12 +52,14 @@ class perm_cmp_alu_permutation_settings { in.cmp_result, in.cmp_op_eq, in.cmp_op_gt, + in.cmp_op_non_ff_gt, in.alu_clk, in.alu_cmp_gadget_input_a, in.alu_cmp_gadget_input_b, in.alu_cmp_gadget_result, in.alu_op_eq, - in.alu_cmp_gadget_gt); + in.alu_cmp_gadget_gt, + in.alu_cmp_gadget_non_ff_gt); } }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perm_rng_gas_da.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perm_rng_gas_da.hpp deleted file mode 100644 index af01d132211..00000000000 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perm_rng_gas_da.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// AUTOGENERATED FILE -#pragma once - -#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" - -#include -#include - -namespace bb { - -class perm_rng_gas_da_permutation_settings { - public: - // This constant defines how many columns are bundled together to form each set. - constexpr static size_t COLUMNS_PER_SET = 2; - - template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) - { - return (in.range_check_gas_da_rng_chk == 1 || in.main_is_gas_accounted == 1); - } - - template static inline auto get_const_entities(const AllEntities& in) - { - return std::forward_as_tuple(in.perm_rng_gas_da_inv, - in.range_check_gas_da_rng_chk, - in.range_check_gas_da_rng_chk, - in.main_is_gas_accounted, - in.range_check_clk, - in.range_check_value, - in.main_clk, - in.main_abs_da_rem_gas); - } - - template static inline auto get_nonconst_entities(AllEntities& in) - { - return std::forward_as_tuple(in.perm_rng_gas_da_inv, - in.range_check_gas_da_rng_chk, - in.range_check_gas_da_rng_chk, - in.main_is_gas_accounted, - in.range_check_clk, - in.range_check_value, - in.main_clk, - in.main_abs_da_rem_gas); - } -}; - -template -class perm_rng_gas_da_relation : public GenericPermutationRelation { - public: - static constexpr const char* NAME = "PERM_RNG_GAS_DA"; -}; -template using perm_rng_gas_da = GenericPermutation; - -} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perm_rng_gas_l2.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perm_rng_gas_l2.hpp deleted file mode 100644 index 2c4fa16bdec..00000000000 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perm_rng_gas_l2.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// AUTOGENERATED FILE -#pragma once - -#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" - -#include -#include - -namespace bb { - -class perm_rng_gas_l2_permutation_settings { - public: - // This constant defines how many columns are bundled together to form each set. - constexpr static size_t COLUMNS_PER_SET = 2; - - template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) - { - return (in.range_check_gas_l2_rng_chk == 1 || in.main_is_gas_accounted == 1); - } - - template static inline auto get_const_entities(const AllEntities& in) - { - return std::forward_as_tuple(in.perm_rng_gas_l2_inv, - in.range_check_gas_l2_rng_chk, - in.range_check_gas_l2_rng_chk, - in.main_is_gas_accounted, - in.range_check_clk, - in.range_check_value, - in.main_clk, - in.main_abs_l2_rem_gas); - } - - template static inline auto get_nonconst_entities(AllEntities& in) - { - return std::forward_as_tuple(in.perm_rng_gas_l2_inv, - in.range_check_gas_l2_rng_chk, - in.range_check_gas_l2_rng_chk, - in.main_is_gas_accounted, - in.range_check_clk, - in.range_check_value, - in.main_clk, - in.main_abs_l2_rem_gas); - } -}; - -template -class perm_rng_gas_l2_relation : public GenericPermutationRelation { - public: - static constexpr const char* NAME = "PERM_RNG_GAS_L2"; -}; -template using perm_rng_gas_l2 = GenericPermutation; - -} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perm_rng_non_ff_cmp.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perm_rng_non_ff_cmp.hpp new file mode 100644 index 00000000000..2e5258e7152 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perm_rng_non_ff_cmp.hpp @@ -0,0 +1,53 @@ +// AUTOGENERATED FILE +#pragma once + +#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" + +#include +#include + +namespace bb { + +class perm_rng_non_ff_cmp_permutation_settings { + public: + // This constant defines how many columns are bundled together to form each set. + constexpr static size_t COLUMNS_PER_SET = 2; + + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.range_check_cmp_non_ff_rng_chk == 1 || in.cmp_op_non_ff_gt == 1); + } + + template static inline auto get_const_entities(const AllEntities& in) + { + return std::forward_as_tuple(in.perm_rng_non_ff_cmp_inv, + in.range_check_cmp_non_ff_rng_chk, + in.range_check_cmp_non_ff_rng_chk, + in.cmp_op_non_ff_gt, + in.range_check_clk, + in.range_check_value, + in.cmp_range_chk_clk, + in.cmp_diff); + } + + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple(in.perm_rng_non_ff_cmp_inv, + in.range_check_cmp_non_ff_rng_chk, + in.range_check_cmp_non_ff_rng_chk, + in.cmp_op_non_ff_gt, + in.range_check_clk, + in.range_check_value, + in.cmp_range_chk_clk, + in.cmp_diff); + } +}; + +template +class perm_rng_non_ff_cmp_relation : public GenericPermutationRelation { + public: + static constexpr const char* NAME = "PERM_RNG_NON_FF_CMP"; +}; +template using perm_rng_non_ff_cmp = GenericPermutation; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/range_check.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/range_check.hpp index 6f05962b1e2..5a6f317d75c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/range_check.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/range_check.hpp @@ -10,8 +10,8 @@ template class range_checkImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, - 3, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3 }; + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 2, 3, + 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 }; template void static accumulate(ContainerOverSubrelations& evals, @@ -243,6 +243,12 @@ template class range_checkImpl { tmp *= scaling_factor; std::get<23>(evals) += typename Accumulator::View(tmp); } + { + using Accumulator = typename std::tuple_element_t<24, ContainerOverSubrelations>; + auto tmp = (new_term.range_check_cmp_non_ff_rng_chk * (new_term.range_check_rng_chk_bits - FF(128))); + tmp *= scaling_factor; + std::get<24>(evals) += typename Accumulator::View(tmp); + } } }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp index 7f3733dd636..46a00c1a004 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp @@ -232,7 +232,8 @@ class AvmArithmeticTests : public ::testing::Test { trace_builder.op_set(0, a, addr_a, tag); trace_builder.op_set(0, b, addr_b, tag); trace_builder.op_eq(0, addr_a, addr_b, addr_c); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); return trace_builder.finalize(); } @@ -244,7 +245,8 @@ class AvmArithmeticTests : public ::testing::Test { trace_builder.op_set(0, a, 0, tag); trace_builder.op_set(0, b, 1, tag); trace_builder.op_add(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto select_row = [](Row r) { return r.main_sel_op_add == FF(1); }; @@ -261,7 +263,8 @@ class AvmArithmeticTests : public ::testing::Test { trace_builder.op_set(0, a, 0, tag); trace_builder.op_set(0, b, 1, tag); trace_builder.op_sub(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto select_row = [](Row r) { return r.main_sel_op_sub == FF(1); }; @@ -278,7 +281,8 @@ class AvmArithmeticTests : public ::testing::Test { trace_builder.op_set(0, a, 0, tag); trace_builder.op_set(0, b, 1, tag); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto select_row = [](Row r) { return r.main_sel_op_mul == FF(1); }; @@ -298,7 +302,8 @@ class AvmArithmeticTests : public ::testing::Test { trace_builder.op_set(0, a, 0, tag); trace_builder.op_set(0, b, 1, tag); trace_builder.op_eq(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto select_row = [](Row r) { return r.main_sel_op_eq == FF(1); }; @@ -398,23 +403,27 @@ std::vector> positive_op_div_test_values = { { // Test on basic addition over finite field type. TEST_F(AvmArithmeticTestsFF, addition) { - std::vector const calldata = { 37, 4, 11 }; + const FF a = FF::modulus - 19; + const FF b = FF::modulus - 5; + const FF c = FF::modulus - 24; // c = a + b + std::vector const calldata = { a, b, 4 }; gen_trace_builder(calldata); trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); trace_builder.op_set(0, 3, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); - // Memory layout: [37,4,11,0,0,0,....] - trace_builder.op_add(0, 0, 1, 4); // [37,4,11,0,41,0,....] - trace_builder.op_return(0, 0, 5); + // Memory layout: [a,b,4,0,0,....] + trace_builder.op_add(0, 0, 1, 4); // [a,b,4,0,c,0,....] + trace_builder.op_set(0, 5, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); - auto alu_row = common_validate_add(trace, FF(37), FF(4), FF(41), FF(0), FF(1), FF(4), AvmMemoryTag::FF); + auto alu_row = common_validate_add(trace, a, b, c, FF(0), FF(1), FF(4), AvmMemoryTag::FF); EXPECT_EQ(alu_row.alu_ff_tag, FF(1)); EXPECT_EQ(alu_row.alu_cf, FF(0)); - std::vector const returndata = { 37, 4, 11, 0, 41 }; + std::vector const returndata = { a, b, 4, 0, c }; validate_trace(std::move(trace), public_inputs, calldata, returndata); } @@ -422,47 +431,55 @@ TEST_F(AvmArithmeticTestsFF, addition) // Test on basic subtraction over finite field type. TEST_F(AvmArithmeticTestsFF, subtraction) { - std::vector const calldata = { 8, 4, 17 }; + const FF a = 8; + const FF b = FF::modulus - 5; + const FF c = 13; // c = a - b + std::vector const calldata = { b, 4, a }; gen_trace_builder(calldata); trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); trace_builder.op_set(0, 3, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); - // Memory layout: [8,4,17,0,0,0,....] - trace_builder.op_sub(0, 2, 0, 1); // [8,9,17,0,0,0....] - trace_builder.op_return(0, 0, 3); + // Memory layout: [b,4,a,0,0,0,....] + trace_builder.op_sub(0, 2, 0, 1); // [b,c,a,0,0,0....] + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); - auto alu_row = common_validate_sub(trace, FF(17), FF(8), FF(9), FF(2), FF(0), FF(1), AvmMemoryTag::FF); + auto alu_row = common_validate_sub(trace, a, b, c, FF(2), FF(0), FF(1), AvmMemoryTag::FF); EXPECT_EQ(alu_row.alu_ff_tag, FF(1)); EXPECT_EQ(alu_row.alu_cf, FF(0)); - std::vector const returndata = { 8, 9, 17 }; + std::vector const returndata = { b, c, a }; validate_trace(std::move(trace), public_inputs, calldata, returndata); } // Test on basic multiplication over finite field type. TEST_F(AvmArithmeticTestsFF, multiplication) { - std::vector const calldata = { 5, 0, 20 }; + const FF a = FF::modulus - 1; + const FF b = 278; + const FF c = FF::modulus - 278; + std::vector const calldata = { b, 0, a }; gen_trace_builder(calldata); trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); trace_builder.op_set(0, 3, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); - // Memory layout: [5,0,20,0,0,0,....] - trace_builder.op_mul(0, 2, 0, 1); // [5,100,20,0,0,0....] - trace_builder.op_return(0, 0, 3); + // Memory layout: [b,0,a,0,0,0,....] + trace_builder.op_mul(0, 2, 0, 1); // [b,c,a,0,0,0....] + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); - auto alu_row_index = common_validate_mul(trace, FF(20), FF(5), FF(100), FF(2), FF(0), FF(1), AvmMemoryTag::FF); + auto alu_row_index = common_validate_mul(trace, a, b, c, FF(2), FF(0), FF(1), AvmMemoryTag::FF); auto alu_row = trace.at(alu_row_index); EXPECT_EQ(alu_row.alu_ff_tag, FF(1)); EXPECT_EQ(alu_row.alu_cf, FF(0)); - std::vector const returndata = { 5, 100, 20 }; + std::vector const returndata = { b, c, a }; validate_trace(std::move(trace), public_inputs, calldata, returndata); } @@ -477,7 +494,8 @@ TEST_F(AvmArithmeticTestsFF, multiplicationByZero) // Memory layout: [127,0,0,0,0,0,....] trace_builder.op_mul(0, 0, 1, 2); // [127,0,0,0,0,0....] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(127), FF(0), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::FF); @@ -501,7 +519,8 @@ TEST_F(AvmArithmeticTestsFF, fDivision) // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -529,7 +548,8 @@ TEST_F(AvmArithmeticTestsFF, fDivisionNumeratorZero) // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 0); // [0,0,0,0,0,0....] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -558,7 +578,8 @@ TEST_F(AvmArithmeticTestsFF, fDivisionByZeroError) // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -581,7 +602,8 @@ TEST_F(AvmArithmeticTestsFF, fDivisionZeroByZeroError) { // Memory layout: [0,0,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [0,0,0,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -620,7 +642,8 @@ TEST_F(AvmArithmeticTestsFF, mixedOperationsWithError) trace_builder.op_fdiv(0, 3, 5, 1); // [0,23*136^(-1),45,23,68,136,0,136,136^2,0....] trace_builder.op_fdiv(0, 1, 1, 9); // [0,23*136^(-1),45,23,68,136,0,136,136^2,1,0....] trace_builder.op_fdiv(0, 9, 0, 4); // [0,23*136^(-1),45,23,1/0,136,0,136,136^2,1,0....] Error: division by 0 - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); validate_trace(std::move(trace), public_inputs, calldata, {}); @@ -637,7 +660,8 @@ TEST_F(AvmArithmeticTestsFF, equality) trace_builder.op_set(0, 2, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_eq(0, 0, 1, 2); // Memory Layout [q - 1, q - 1, 1, 0..] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_eq(trace, elem, elem, FF(1), FF(0), FF(1), FF(2), AvmMemoryTag::FF); @@ -661,7 +685,8 @@ TEST_F(AvmArithmeticTestsFF, nonEquality) trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_eq(0, 0, 1, 2); // Memory Layout [q - 1, q, 0, 0..] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_eq(trace, elem, FF(0), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::FF); @@ -681,7 +706,8 @@ TEST_P(AvmArithmeticTestsDiv, division) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_div(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); common_validate_div(trace, a, b, output, 0, 1, 2, mem_tag); @@ -699,7 +725,8 @@ TEST_F(AvmArithmeticTests, DivisionByZeroError) trace_builder.op_set(0, 100, 0, AvmMemoryTag::U128); trace_builder.op_set(0, 0, 1, AvmMemoryTag::U128); trace_builder.op_div(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the div selector @@ -729,7 +756,8 @@ TEST_F(AvmArithmeticTestsU1, addition) // Memory layout: [1,0,0,0,0,....] trace_builder.op_add(0, 0, 1, 2); // [1,0,1,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(1), FF(0), FF(1), FF(0), FF(1), FF(2), AvmMemoryTag::U1); @@ -749,7 +777,8 @@ TEST_F(AvmArithmeticTestsU1, additionCarry) // Memory layout: [1,1,0,0,0,....] trace_builder.op_add(0, 0, 1, 2); // [1,1,0,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(1), FF(1), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::U1); @@ -769,7 +798,8 @@ TEST_F(AvmArithmeticTestsU1, subtraction) // Memory layout: [1,1,0,0,0,....] trace_builder.op_sub(0, 0, 1, 2); // [1,1,0,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(1), FF(1), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::U1); @@ -790,7 +820,8 @@ TEST_F(AvmArithmeticTestsU1, subtractionCarry) // Memory layout: [0,1,0,0,0,....] trace_builder.op_sub(0, 0, 1, 2); // [0,1,1,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(0), FF(1), FF(1), FF(0), FF(1), FF(2), AvmMemoryTag::U1); @@ -809,7 +840,8 @@ TEST_F(AvmArithmeticTestsU1, multiplication) trace_builder.op_set(0, 1, 1, AvmMemoryTag::U1); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(1), FF(1), FF(1), FF(0), FF(1), FF(2), AvmMemoryTag::U1); @@ -828,7 +860,8 @@ TEST_F(AvmArithmeticTestsU1, multiplicationByzero) trace_builder.op_set(0, 0, 1, AvmMemoryTag::U1); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(1), FF(0), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::U1); @@ -878,7 +911,8 @@ TEST_F(AvmArithmeticTestsU8, addition) // Memory layout: [62,29,0,0,0,....] trace_builder.op_add(0, 0, 1, 2); // [62,29,91,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(62), FF(29), FF(91), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -898,7 +932,8 @@ TEST_F(AvmArithmeticTestsU8, additionCarry) // Memory layout: [159,100,0,0,0,....] trace_builder.op_add(0, 0, 1, 2); // [159,100,3,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(159), FF(100), FF(3), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -918,7 +953,8 @@ TEST_F(AvmArithmeticTestsU8, subtraction) // Memory layout: [162,29,0,0,0,....] trace_builder.op_sub(0, 0, 1, 2); // [162,29,133,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(162), FF(29), FF(133), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -939,7 +975,8 @@ TEST_F(AvmArithmeticTestsU8, subtractionCarry) // Memory layout: [5,29,0,0,0,....] trace_builder.op_sub(0, 0, 1, 2); // [5,29,232,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(5), FF(29), FF(232), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -958,7 +995,8 @@ TEST_F(AvmArithmeticTestsU8, multiplication) trace_builder.op_set(0, 15, 1, AvmMemoryTag::U8); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(13), FF(15), FF(195), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -977,7 +1015,8 @@ TEST_F(AvmArithmeticTestsU8, multiplicationOverflow) trace_builder.op_set(0, 170, 1, AvmMemoryTag::U8); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(200), FF(170), FF(208), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -1026,7 +1065,8 @@ TEST_F(AvmArithmeticTestsU16, addition) trace_builder.op_set(0, 33005, 546, AvmMemoryTag::U16); trace_builder.op_add(0, 546, 119, 5); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = @@ -1046,7 +1086,8 @@ TEST_F(AvmArithmeticTestsU16, additionCarry) trace_builder.op_set(0, 1000, 1, AvmMemoryTag::U16); trace_builder.op_add(0, 1, 0, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = @@ -1066,7 +1107,8 @@ TEST_F(AvmArithmeticTestsU16, subtraction) trace_builder.op_set(0, 33005, 546, AvmMemoryTag::U16); trace_builder.op_sub(0, 546, 119, 5); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = @@ -1087,7 +1129,8 @@ TEST_F(AvmArithmeticTestsU16, subtractionCarry) trace_builder.op_set(0, 1000, 1, AvmMemoryTag::U16); trace_builder.op_sub(0, 1, 0, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = @@ -1107,7 +1150,8 @@ TEST_F(AvmArithmeticTestsU16, multiplication) trace_builder.op_set(0, 245, 1, AvmMemoryTag::U16); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_index = common_validate_mul(trace, FF(200), FF(245), FF(49000), FF(0), FF(1), FF(2), AvmMemoryTag::U16); @@ -1126,7 +1170,8 @@ TEST_F(AvmArithmeticTestsU16, multiplicationOverflow) trace_builder.op_set(0, 1024, 1, AvmMemoryTag::U16); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_index = common_validate_mul(trace, FF(512), FF(1024), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::U16); @@ -1175,7 +1220,8 @@ TEST_F(AvmArithmeticTestsU32, addition) trace_builder.op_set(0, 1234567891, 9, AvmMemoryTag::U32); trace_builder.op_add(0, 8, 9, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add( @@ -1195,7 +1241,8 @@ TEST_F(AvmArithmeticTestsU32, additionCarry) trace_builder.op_set(0, 2293, 9, AvmMemoryTag::U32); trace_builder.op_add(0, 8, 9, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = @@ -1215,7 +1262,8 @@ TEST_F(AvmArithmeticTestsU32, subtraction) trace_builder.op_set(0, 1234567891, 9, AvmMemoryTag::U32); trace_builder.op_sub(0, 8, 9, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub( @@ -1236,7 +1284,8 @@ TEST_F(AvmArithmeticTestsU32, subtractionCarry) trace_builder.op_set(0, uint256_t(3210987654), 9, AvmMemoryTag::U32); trace_builder.op_sub(0, 9, 8, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub( @@ -1256,7 +1305,8 @@ TEST_F(AvmArithmeticTestsU32, multiplication) trace_builder.op_set(0, 11111, 1, AvmMemoryTag::U32); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = @@ -1276,7 +1326,8 @@ TEST_F(AvmArithmeticTestsU32, multiplicationOverflow) trace_builder.op_set(0, 13 << 22, 1, AvmMemoryTag::U32); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = @@ -1333,7 +1384,8 @@ TEST_F(AvmArithmeticTestsU64, addition) trace_builder.op_set(0, b, 9, AvmMemoryTag::U64); trace_builder.op_add(0, 8, 9, 9); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(a), FF(b), FF(c), FF(8), FF(9), FF(9), AvmMemoryTag::U64); @@ -1356,7 +1408,8 @@ TEST_F(AvmArithmeticTestsU64, additionCarry) trace_builder.op_set(0, b, 1, AvmMemoryTag::U64); trace_builder.op_add(0, 0, 1, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(a), FF(b), FF(c), FF(0), FF(1), FF(0), AvmMemoryTag::U64); @@ -1379,7 +1432,8 @@ TEST_F(AvmArithmeticTestsU64, subtraction) trace_builder.op_set(0, b, 9, AvmMemoryTag::U64); trace_builder.op_sub(0, 8, 9, 9); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(a), FF(b), FF(c), FF(8), FF(9), FF(9), AvmMemoryTag::U64); @@ -1403,7 +1457,8 @@ TEST_F(AvmArithmeticTestsU64, subtractionCarry) trace_builder.op_set(0, b, 1, AvmMemoryTag::U64); trace_builder.op_sub(0, 0, 1, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(a), FF(b), FF(c), FF(0), FF(1), FF(0), AvmMemoryTag::U64); @@ -1422,7 +1477,8 @@ TEST_F(AvmArithmeticTestsU64, multiplication) trace_builder.op_set(0, 555444333, 1, AvmMemoryTag::U64); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul( @@ -1446,7 +1502,8 @@ TEST_F(AvmArithmeticTestsU64, multiplicationOverflow) trace_builder.op_set(0, b, 1, AvmMemoryTag::U64); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(a), FF(b), FF(1), FF(0), FF(1), FF(2), AvmMemoryTag::U64); @@ -1500,7 +1557,8 @@ TEST_F(AvmArithmeticTestsU128, addition) trace_builder.op_set(0, b, 9, AvmMemoryTag::U128); trace_builder.op_add(0, 8, 9, 9); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, a, b, c, FF(8), FF(9), FF(9), AvmMemoryTag::U128); @@ -1524,7 +1582,8 @@ TEST_F(AvmArithmeticTestsU128, additionCarry) trace_builder.op_set(0, b, 9, AvmMemoryTag::U128); trace_builder.op_add(0, 8, 9, 9); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, a, b, c, FF(8), FF(9), FF(9), AvmMemoryTag::U128); @@ -1547,7 +1606,8 @@ TEST_F(AvmArithmeticTestsU128, subtraction) trace_builder.op_set(0, b, 9, AvmMemoryTag::U128); trace_builder.op_sub(0, 8, 9, 9); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, a, b, c, FF(8), FF(9), FF(9), AvmMemoryTag::U128); @@ -1570,7 +1630,8 @@ TEST_F(AvmArithmeticTestsU128, subtractionCarry) trace_builder.op_set(0, b, 9, AvmMemoryTag::U128); trace_builder.op_sub(0, 8, 9, 9); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, a, b, c, FF(8), FF(9), FF(9), AvmMemoryTag::U128); @@ -1591,7 +1652,8 @@ TEST_F(AvmArithmeticTestsU128, multiplication) FF c{ uint256_t{ 0xA7DDA0BAE60CA3A5, 0x70289AEB0, 0, 0 } }; trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul( @@ -1616,7 +1678,8 @@ TEST_F(AvmArithmeticTestsU128, multiplicationOverflow) trace_builder.op_set(0, b, 1, AvmMemoryTag::U128); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, a, b, FF{ 8 }, FF(0), FF(1), FF(2), AvmMemoryTag::U128); @@ -1710,7 +1773,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivision) // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto select_row = [](Row r) { return r.main_sel_op_fdiv == FF(1); }; @@ -1729,7 +1793,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionNoZeroButError) // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -1757,7 +1822,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionByZeroNoError) // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -1774,7 +1840,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionZeroByZeroNoError) { // Memory layout: [0,0,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [0,0,0,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -1794,7 +1861,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongRInTag) trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [18,6,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [18,6,3,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -1814,7 +1882,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongWInTag) trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [18,6,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [18,6,3,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -1836,8 +1905,10 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag1) // Memory layout: [37,4,11,0,0,0,....] trace_builder.op_add(0, 0, 1, 4); // [37,4,11,0,41,0,....] - trace_builder.op_return(0, 0, 5); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 5, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the addition selector @@ -1857,7 +1928,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag2) // Memory layout: [8,4,17,0,0,0,....] trace_builder.op_sub(0, 2, 0, 1); // [8,9,17,0,0,0....] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the subtraction selector @@ -1877,7 +1949,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag3) // Memory layout: [5,0,20,0,0,0,....] trace_builder.op_mul(0, 2, 0, 1); // [5,100,20,0,0,0....] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the multiplication selector @@ -1920,7 +1993,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, eqOutputWrongTag) gen_trace_builder(calldata); trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_eq(0, 0, 1, 2); // Memory Layout [elem, elem, 1, 0..] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the eq selector @@ -2270,7 +2344,8 @@ TEST_F(AvmArithmeticNegativeTestsU128, multiplicationSecondRowNoOp) trace_builder.op_set(0, 4, 1, AvmMemoryTag::U128); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(3), FF(4), FF(12), FF(0), FF(1), FF(2), AvmMemoryTag::U128); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp index 9a3b1b8b369..462bed25ff1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp @@ -361,7 +361,8 @@ class AvmBitwiseTests : public ::testing::Test { { trace_builder.op_set(0, a, 0, tag); trace_builder.op_not(0, 0, 1); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto select_row = [](Row r) { return r.main_sel_op_not == FF(1); }; @@ -476,7 +477,8 @@ TEST_P(AvmBitwiseTestsNot, ParamTest) const auto [a, output] = operands; trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_not(0, 0, 1); // [1,254,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); common_validate_op_not(trace, a, output, FF(0), FF(1), mem_tag); validate_trace(std::move(trace), public_inputs); @@ -493,7 +495,8 @@ TEST_P(AvmBitwiseTestsAnd, AllAndTest) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_and(0, 0, 1, 2); - trace_builder.op_return(0, 2, 1); + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 2, 100); auto trace = trace_builder.finalize(); common_validate_bit_op(trace, 0, a, b, output, FF(0), FF(1), FF(2), mem_tag); @@ -510,7 +513,8 @@ TEST_P(AvmBitwiseTestsOr, AllOrTest) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_or(0, 0, 1, 2); - trace_builder.op_return(0, 2, 1); + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 2, 100); auto trace = trace_builder.finalize(); common_validate_bit_op(trace, 1, a, b, output, FF(0), FF(1), FF(2), mem_tag); @@ -527,7 +531,8 @@ TEST_P(AvmBitwiseTestsXor, AllXorTest) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_xor(0, 0, 1, 2); - trace_builder.op_return(0, 2, 1); + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 2, 100); auto trace = trace_builder.finalize(); common_validate_bit_op(trace, 2, a, b, output, FF(0), FF(1), FF(2), mem_tag); @@ -543,9 +548,10 @@ TEST_P(AvmBitwiseTestsShr, AllShrTest) const auto [operands, mem_tag] = GetParam(); const auto [a, b, output] = operands; trace_builder.op_set(0, a, 0, mem_tag); - trace_builder.op_set(0, b, 1, mem_tag); + trace_builder.op_set(0, b, 1, AvmMemoryTag::U8); trace_builder.op_shr(0, 0, 1, 2); - trace_builder.op_return(0, 2, 1); + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 2, 100); auto trace = trace_builder.finalize(); common_validate_shift_op(trace, a, b, output, FF(0), FF(1), FF(2), mem_tag, true); validate_trace(std::move(trace), public_inputs, {}, { output }); @@ -560,9 +566,10 @@ TEST_P(AvmBitwiseTestsShl, AllShlTest) const auto [operands, mem_tag] = GetParam(); const auto [a, b, output] = operands; trace_builder.op_set(0, a, 0, mem_tag); - trace_builder.op_set(0, b, 1, mem_tag); + trace_builder.op_set(0, b, 1, AvmMemoryTag::U8); trace_builder.op_shl(0, 0, 1, 2); - trace_builder.op_return(0, 2, 1); + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 2, 100); auto trace = trace_builder.finalize(); common_validate_shift_op(trace, a, b, output, FF(0), FF(1), FF(2), mem_tag, false); @@ -666,7 +673,8 @@ TEST_P(AvmBitwiseNegativeTestsAnd, AllNegativeTests) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_and(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); std::function&& select_row = [](Row r) { return r.main_sel_op_and == FF(1); }; trace = gen_mutated_trace_bit(trace, std::move(select_row), output, failure_mode); @@ -685,7 +693,8 @@ TEST_P(AvmBitwiseNegativeTestsOr, AllNegativeTests) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_or(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); std::function&& select_row = [](Row r) { return r.main_sel_op_or == FF(1); }; trace = gen_mutated_trace_bit(trace, std::move(select_row), output, failure_mode); @@ -703,7 +712,8 @@ TEST_P(AvmBitwiseNegativeTestsXor, AllNegativeTests) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_xor(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); std::function&& select_row = [](Row r) { return r.main_sel_op_xor == FF(1); }; trace = gen_mutated_trace_bit(trace, std::move(select_row), output, failure_mode); @@ -721,7 +731,8 @@ TEST_P(AvmBitwiseNegativeTestsShr, AllNegativeTests) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_shr(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); std::function&& select_row = [](Row r) { return r.main_sel_op_shr == FF(1); }; @@ -740,7 +751,8 @@ TEST_P(AvmBitwiseNegativeTestsShl, AllNegativeTests) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_shl(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); std::function&& select_row = [](Row r) { return r.main_sel_op_shl == FF(1); }; @@ -760,7 +772,8 @@ TEST_F(AvmBitwiseNegativeTestsFF, UndefinedOverFF) trace_builder.op_not(0, 0, 1); // Finally, we will have a write in row 3 of the mem_trace to copy the result // from the op_not operation. - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); // Manually update the memory tags in the relevant trace; auto trace = trace_builder.finalize(); // TODO(ilyas): When the SET opcodes applies relational constraints, this will fail diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp index 82715ee6065..1dd11e5bf6c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp @@ -37,7 +37,8 @@ class AvmCastTests : public ::testing::Test { { trace_builder.op_set(0, uint256_t::from_uint128(a), src_address, src_tag); trace_builder.op_cast(0, src_address, dst_address, dst_tag); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); } @@ -184,10 +185,12 @@ TEST_F(AvmCastTests, truncationFFToU16ModMinus1) trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata) .set_full_precomputed_tables(false) .set_range_check_required(false); + trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); trace_builder.op_set(0, 1, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); @@ -200,10 +203,12 @@ TEST_F(AvmCastTests, truncationFFToU16ModMinus2) trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata) .set_full_precomputed_tables(false) .set_range_check_required(false); + trace_builder.op_set(0, 0, 0, AvmMemoryTag::U32); trace_builder.op_set(0, 1, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); @@ -227,7 +232,8 @@ TEST_F(AvmCastTests, indirectAddrTruncationU64ToU8) trace_builder.op_set(0, 11, 1, AvmMemoryTag::U32); trace_builder.op_set(0, 256'000'000'203UL, 10, AvmMemoryTag::U64); trace_builder.op_cast(3, 0, 1, AvmMemoryTag::U8); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); @@ -244,7 +250,8 @@ TEST_F(AvmCastTests, indirectAddrWrongResolutionU64ToU8) trace_builder.op_set(0, 11, 6, AvmMemoryTag::U32); trace_builder.op_set(0, 4234, 10, AvmMemoryTag::U64); trace_builder.op_cast(3, 5, 6, AvmMemoryTag::U8); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_cast == FF(1); }); @@ -318,7 +325,8 @@ TEST_F(AvmCastNegativeTests, wrongLimbDecompositionInput) .set_range_check_required(false); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); @@ -345,7 +353,8 @@ TEST_F(AvmCastNegativeTests, wrongPSubAHi) .set_range_check_required(false); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); @@ -385,7 +394,8 @@ TEST_F(AvmCastNegativeTests, wrongRangeCheckDecompositionHi) .set_range_check_required(false); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); @@ -425,7 +435,8 @@ TEST_F(AvmCastNegativeTests, wrongCopySubHiForRangeCheck) .set_range_check_required(false); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U128); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp index a137a0f4d0c..ff633a4d110 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp @@ -122,7 +122,8 @@ TEST_P(AvmCmpTestsLT, ParamTest) trace_builder.op_set(0, b, 1, mem_tag); } trace_builder.op_lt(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Get the row in the avm with the LT selector set @@ -160,7 +161,8 @@ TEST_P(AvmCmpTestsLTE, ParamTest) trace_builder.op_set(0, b, 1, mem_tag); } trace_builder.op_lte(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_lte == FF(1); }); @@ -336,7 +338,8 @@ TEST_P(AvmCmpNegativeTestsLT, ParamTest) .set_range_check_required(false); trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_lt(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); std::function select_row = [](Row r) { return r.main_sel_op_lt == FF(1); }; trace = gen_mutated_trace_cmp(trace, select_row, output, failure_mode, false); @@ -357,7 +360,8 @@ TEST_P(AvmCmpNegativeTestsLTE, ParamTest) .set_range_check_required(false); trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_lte(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); std::function select_row = [](Row r) { return r.main_sel_op_lte == FF(1); }; trace = gen_mutated_trace_cmp(trace, select_row, output, failure_mode, true); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/control_flow.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/control_flow.test.cpp index 7238a75f52e..4ce2715058f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/control_flow.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/control_flow.test.cpp @@ -61,14 +61,17 @@ class AvmControlFlowTests : public ::testing::Test { TEST_F(AvmControlFlowTests, simpleCall) { - uint32_t const CALL_PC = 4; + uint32_t const SET_PC = 4; + uint32_t const CALL_PC = 41; // trace_builder for the following operation // pc opcode // 0 INTERNAL_CALL(pc=4) - // 4 RETURN - trace_builder.op_internal_call(CALL_PC); - trace_builder.op_return(0, 0, 0); + // 4 SET(0, 0, 100) + // 41 RETURN + trace_builder.op_internal_call(SET_PC); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); @@ -78,7 +81,7 @@ TEST_F(AvmControlFlowTests, simpleCall) trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_internal_call == FF(1); }); EXPECT_TRUE(call_row_iter != trace.end()); auto& call_row = trace.at(static_cast(call_row_iter - trace.begin())); - validate_internal_call(call_row, 0, CALL_PC, 0); + validate_internal_call(call_row, 0, SET_PC, 0); } // Check halt @@ -96,14 +99,17 @@ TEST_F(AvmControlFlowTests, simpleCall) TEST_F(AvmControlFlowTests, simpleJump) { - uint32_t const JUMP_PC = 4; + uint32_t const SET_PC = 4; + uint32_t const JUMP_PC = 41; // trace_builder for the following operation // pc opcode // 0 JUMP(pc=4) - // 4 RETURN - trace_builder.op_jump(JUMP_PC); - trace_builder.op_return(0, 0, 0); + // 4 SET(0, 0, 100) + // 41 RETURN + trace_builder.op_jump(SET_PC); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); @@ -113,7 +119,7 @@ TEST_F(AvmControlFlowTests, simpleJump) std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_jump == FF(1); }); EXPECT_TRUE(call_row != trace.end()); EXPECT_EQ(call_row->main_pc, FF(0)); - EXPECT_EQ(call_row->main_ia, FF(JUMP_PC)); + EXPECT_EQ(call_row->main_ia, FF(SET_PC)); } // Check halt @@ -129,16 +135,20 @@ TEST_F(AvmControlFlowTests, simpleJump) TEST_F(AvmControlFlowTests, simpleCallAndReturn) { - uint32_t const CALL_PC = 20; - uint32_t const RETURN_PC = Deserialization::get_pc_increment(OpCode::INTERNALCALL); + uint32_t const SET_PC = Deserialization::get_pc_increment(OpCode::INTERNALCALL); + uint32_t const RETURN_PC = SET_PC + Deserialization::get_pc_increment(OpCode::SET_FF); + uint32_t const INTERNAL_RETURN_PC = RETURN_PC + Deserialization::get_pc_increment(OpCode::RETURN); + // trace_builder for the following operation // pc opcode - // 0 INTERNAL_CALL(pc=20) - // 20 INTERNAL_RETURN - // 5 RETURN - trace_builder.op_internal_call(CALL_PC); + // 0 INTERNAL_CALL(pc=57) + // 57 INTERNAL_RETURN + // 5 SET(0, 0, 100) + // 42 RETURN + trace_builder.op_internal_call(INTERNAL_RETURN_PC); trace_builder.op_internal_return(); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); @@ -148,7 +158,7 @@ TEST_F(AvmControlFlowTests, simpleCallAndReturn) trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_internal_call == FF(1); }); EXPECT_TRUE(call_row_iter != trace.end()); auto& call_row = trace.at(static_cast(call_row_iter - trace.begin())); - validate_internal_call(call_row, 0, CALL_PC, 0); + validate_internal_call(call_row, 0, INTERNAL_RETURN_PC, 0); } // Check return @@ -159,7 +169,7 @@ TEST_F(AvmControlFlowTests, simpleCallAndReturn) // Check that the correct result is stored at the expected memory location. EXPECT_TRUE(return_row_iter != trace.end()); auto& return_row = trace.at(static_cast(return_row_iter - trace.begin())); - validate_internal_return(return_row, CALL_PC, RETURN_PC, 1); + validate_internal_return(return_row, INTERNAL_RETURN_PC, SET_PC, 1); } // Check halt @@ -188,6 +198,7 @@ TEST_F(AvmControlFlowTests, multipleCallsAndReturns) const uint32_t NEXT_PC_2 = CALL_PC_1 + INTERNALCALL_SIZE; const uint32_t NEXT_PC_3 = CALL_PC_2 + INTERNALCALL_SIZE; const uint32_t NEXT_PC_4 = CALL_PC_2 + 2 * INTERNALCALL_SIZE; + const uint32_t RETURN_PC = NEXT_PC_1 + Deserialization::get_pc_increment(OpCode::SET_FF); // trace_builder for the following operation // pc opcode @@ -210,7 +221,8 @@ TEST_F(AvmControlFlowTests, multipleCallsAndReturns) trace_builder.op_jump(JUMP_PC_1); trace_builder.op_internal_return(); trace_builder.op_internal_return(); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); @@ -308,7 +320,7 @@ TEST_F(AvmControlFlowTests, multipleCallsAndReturns) std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_external_return == FF(1); }); EXPECT_TRUE(halt_row != trace.end()); - EXPECT_EQ(halt_row->main_pc, FF(NEXT_PC_1)); + EXPECT_EQ(halt_row->main_pc, FF(RETURN_PC)); validate_trace(std::move(trace), public_inputs); } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp index ba245cbcfc0..c04ea043b62 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp @@ -138,16 +138,21 @@ TEST_F(AvmExecutionTests, basicAddReturn) "0007" // addr a 7 "0009" // addr b 9 "0001" // addr c 1 + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); // 2 instructions - ASSERT_THAT(instructions, SizeIs(4)); + ASSERT_THAT(instructions, SizeIs(5)); // ADD EXPECT_THAT(instructions.at(2), @@ -157,12 +162,21 @@ TEST_F(AvmExecutionTests, basicAddReturn) VariantWith(7), VariantWith(9), VariantWith(1))))); - - // RETURN + // SET EXPECT_THAT(instructions.at(3), - AllOf(Field(&Instruction::op_code, OpCode::RETURN), + AllOf(Field(&Instruction::op_code, OpCode::SET_8), Field(&Instruction::operands, - ElementsAre(VariantWith(0), VariantWith(0), VariantWith(0))))); + ElementsAre(VariantWith(0), + VariantWith(AvmMemoryTag::U32), + VariantWith(0), + VariantWith(255))))); + + // RETURN + EXPECT_THAT( + instructions.at(4), + AllOf(Field(&Instruction::op_code, OpCode::RETURN), + Field(&Instruction::operands, + ElementsAre(VariantWith(0), VariantWith(0), VariantWith(255))))); auto trace = gen_trace_from_bytecode(bytecode); validate_trace(std::move(trace), public_inputs, {}, {}); @@ -179,22 +193,27 @@ TEST_F(AvmExecutionTests, setAndSubOpcodes) + to_hex(OpCode::SET_16) + // opcode SET "00" // Indirect flag + to_hex(AvmMemoryTag::U16) + - "9103" // val 37123 - "0033" // dst_offset 51 - + to_hex(OpCode::SUB_8) + // opcode SUB - "00" // Indirect flag - "AA" // addr a - "33" // addr b - "01" // addr c 1 + "9103" // val 37123 + "0033" // dst_offset 51 + + to_hex(OpCode::SUB_8) + // opcode SUB + "00" // Indirect flag + "AA" // addr a + "33" // addr b + "01" // addr c 1 + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(4)); + ASSERT_THAT(instructions, SizeIs(5)); // SET EXPECT_THAT(instructions.at(0), @@ -239,6 +258,7 @@ TEST_F(AvmExecutionTests, setAndSubOpcodes) // the result at offset 1. TEST_F(AvmExecutionTests, powerWithMulOpcodes) { + const int NUM_MUL_ITERATIONS = 12; std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag + to_hex(AvmMemoryTag::U64) + @@ -256,21 +276,27 @@ TEST_F(AvmExecutionTests, powerWithMulOpcodes) "01" // addr b "01"; // addr c 1 + std::string const set_return_size_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" + // Indirect flag + to_hex(AvmMemoryTag::U32) + + "00" // val + "FF"; // dst_offset + std::string const ret_hex = to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 - for (int i = 0; i < 12; i++) { + for (int i = 0; i < NUM_MUL_ITERATIONS; i++) { bytecode_hex.append(mul_hex); } - + bytecode_hex.append(set_return_size_hex); bytecode_hex.append(ret_hex); auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(15)); + ASSERT_THAT(instructions, SizeIs(16)); // MUL first pos EXPECT_THAT(instructions.at(2), @@ -282,7 +308,7 @@ TEST_F(AvmExecutionTests, powerWithMulOpcodes) VariantWith(1))))); // MUL last pos - EXPECT_THAT(instructions.at(13), + EXPECT_THAT(instructions.at(NUM_MUL_ITERATIONS + 1), AllOf(Field(&Instruction::op_code, OpCode::MUL_8), Field(&Instruction::operands, ElementsAre(VariantWith(0), @@ -290,22 +316,39 @@ TEST_F(AvmExecutionTests, powerWithMulOpcodes) VariantWith(1), VariantWith(1))))); - // RETURN - EXPECT_THAT(instructions.at(14), - AllOf(Field(&Instruction::op_code, OpCode::RETURN), + // SET + EXPECT_THAT(instructions.at(NUM_MUL_ITERATIONS + 2), + AllOf(Field(&Instruction::op_code, OpCode::SET_8), Field(&Instruction::operands, - ElementsAre(VariantWith(0), VariantWith(0), VariantWith(0))))); + ElementsAre(VariantWith(0), + VariantWith(AvmMemoryTag::U32), + VariantWith(0), + VariantWith(255))))); + + // RETURN + EXPECT_THAT( + instructions.at(NUM_MUL_ITERATIONS + 3), + AllOf(Field(&Instruction::op_code, OpCode::RETURN), + Field(&Instruction::operands, + ElementsAre(VariantWith(0), VariantWith(0), VariantWith(255))))); auto trace = gen_trace_from_bytecode(bytecode); // Find the first row enabling the multiplication selector and pc of last multiplication - const auto last_mul_pc = - 2 * Deserialization::get_pc_increment(OpCode::SET_8) + 11 * Deserialization::get_pc_increment(OpCode::MUL_8); + const auto last_mul_pc = 2 * Deserialization::get_pc_increment(OpCode::SET_8) + + (NUM_MUL_ITERATIONS - 1) * Deserialization::get_pc_increment(OpCode::MUL_8); auto row = std::ranges::find_if(trace.begin(), trace.end(), [last_mul_pc](Row r) { return r.main_sel_op_mul == 1 && r.main_pc == last_mul_pc; }); - EXPECT_EQ(row->main_ic, 244140625); // 5^12 = 244140625 + + int result = 1; + // Compute 5 ^ NUM_MUL_ITERATIONS + for (int i = 0; i < NUM_MUL_ITERATIONS; i++) { + result *= 5; + } + + EXPECT_EQ(row->main_ic, result); validate_trace(std::move(trace), public_inputs); } @@ -317,9 +360,9 @@ TEST_F(AvmExecutionTests, powerWithMulOpcodes) // CALL internal routine // ADD M[4] with M[7] and output in M[9] // Internal routine bytecode is at the end. -// Bytecode layout: SET_32 INTERNAL_CALL ADD_16 RETURN SET_32 INTERNAL_RETURN -// Instr. Index 0 1 2 3 4 5 -// PC Index 0 9 14 22 28 37 +// Bytecode layout: SET_32 INTERNAL_CALL ADD_16 SET_8 RETURN SET_32 INTERNAL_RETURN +// Instr. Index 0 1 2 3 4 5 6 +// PC Index 0 9 14 22 27 33 42 TEST_F(AvmExecutionTests, simpleInternalCall) { std::string bytecode_hex = to_hex(OpCode::SET_32) + // opcode SET @@ -328,19 +371,24 @@ TEST_F(AvmExecutionTests, simpleInternalCall) "0D3D2518" // val 222111000 = 0xD3D2518 "0004" // dst_offset 4 + to_hex(OpCode::INTERNALCALL) + // opcode INTERNALCALL - "0000001C" // jmp_dest 28 + "00000021" // jmp_dest 33 + to_hex(OpCode::ADD_16) + // opcode ADD "00" // Indirect flag "0004" // addr a 4 "0007" // addr b 7 "0009" // addr c9 - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "0000" // ret offset 0 - "0000" // ret size 0 - + to_hex(OpCode::SET_32) + // opcode SET + + to_hex(OpCode::SET_8) + // opcode SET (for return size) "00" // Indirect flag + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0000" // ret offset 0 + "00FF" // ret size offset 255 + + to_hex(OpCode::SET_32) + // opcode SET + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + "075BCD15" // val 123456789 = 0x75BCD15 "0007" // dst_offset 7 + to_hex(OpCode::INTERNALRETURN) // opcode INTERNALRETURN @@ -349,24 +397,24 @@ TEST_F(AvmExecutionTests, simpleInternalCall) auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - EXPECT_THAT(instructions, SizeIs(6)); + EXPECT_THAT(instructions, SizeIs(7)); // We test parsing step for INTERNALCALL and INTERNALRETURN. // INTERNALCALL EXPECT_THAT(instructions.at(1), AllOf(Field(&Instruction::op_code, OpCode::INTERNALCALL), - Field(&Instruction::operands, ElementsAre(VariantWith(28))))); + Field(&Instruction::operands, ElementsAre(VariantWith(33))))); // INTERNALRETURN - EXPECT_EQ(instructions.at(5).op_code, OpCode::INTERNALRETURN); + EXPECT_EQ(instructions.at(6).op_code, OpCode::INTERNALRETURN); auto trace = gen_trace_from_bytecode(bytecode); // Expected sequence of PCs during execution - std::vector pc_sequence{ 0, 9, 28, 37, 14, 22 }; + std::vector pc_sequence{ 0, 9, 33, 42, 14, 22, 27 }; - for (size_t i = 0; i < 6; i++) { + for (size_t i = 0; i < 7; i++) { EXPECT_EQ(trace.at(i + 1).main_pc, pc_sequence.at(i)); } @@ -384,9 +432,9 @@ TEST_F(AvmExecutionTests, simpleInternalCall) // G: F1 SET(17,3) F2 where SET(17,3) means M[3] = 17 // MAIN: SET(4,2) SET(7,3) G // Whole execution should compute: (4 + 7) * 17 = 187 -// Bytecode layout: SET(4,2) SET(7,3) INTERNAL_CALL_G RETURN BYTECODE(F2) BYTECODE(F1) BYTECODE(G) -// Instr Index: 0 1 2 3 4 6 8 -// PC Index: 0 9 18 23 29 35 41 +// Bytecode layout: SET(4,2) SET(7,3) INTERNAL_CALL_G SET_8 RETURN BYTECODE(F2) BYTECODE(F1) BYTECODE(G) +// Instr Index: 0 1 2 3 4 5 7 9 +// PC Index: 0 9 18 23 28 34 40 46 // BYTECODE(F1): ADD(2,3,2) INTERNAL_RETURN // BYTECODE(F2): MUL(2,3,2) INTERNAL_RETURN // BYTECODE(G): INTERNAL_CALL(35) SET(17,3) INTERNAL_CALL(29) INTERNAL_RETURN @@ -409,47 +457,54 @@ TEST_F(AvmExecutionTests, nestedInternalCalls) "03" // addr b 3 "02"; // addr c 2 + std::string const set_return_size_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" + // Indirect flag + to_hex(AvmMemoryTag::U32) + + "00" // val + "FF"; // dst_offset 255 + const std::string return_instruction_hex = to_hex(OpCode::RETURN) // opcode RETURN + "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 const std::string bytecode_f1 = to_hex(OpCode::ADD_8) + tag_address_arguments + to_hex(OpCode::INTERNALRETURN); const std::string bytecode_f2 = to_hex(OpCode::MUL_8) + tag_address_arguments + to_hex(OpCode::INTERNALRETURN); - const std::string bytecode_g = internalCallInstructionHex("23") + setInstructionHex("11", "03") + - internalCallInstructionHex("1D") + to_hex(OpCode::INTERNALRETURN); + const std::string bytecode_g = internalCallInstructionHex("28") + setInstructionHex("11", "03") + + internalCallInstructionHex("22") + to_hex(OpCode::INTERNALRETURN); std::string bytecode_hex = setInstructionHex("04", "02") + setInstructionHex("07", "03") + - internalCallInstructionHex("29") + return_instruction_hex + bytecode_f2 + bytecode_f1 + - bytecode_g; + internalCallInstructionHex("2E") + set_return_size_hex + return_instruction_hex + + bytecode_f2 + bytecode_f1 + bytecode_g; auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(12)); + ASSERT_THAT(instructions, SizeIs(13)); // Expected sequence of opcodes - std::vector const opcode_sequence{ OpCode::SET_32, OpCode::SET_32, OpCode::INTERNALCALL, - OpCode::RETURN, OpCode::MUL_8, OpCode::INTERNALRETURN, - OpCode::ADD_8, OpCode::INTERNALRETURN, OpCode::INTERNALCALL, - OpCode::SET_32, OpCode::INTERNALCALL, OpCode::INTERNALRETURN }; + std::vector const opcode_sequence{ OpCode::SET_32, OpCode::SET_32, OpCode::INTERNALCALL, + OpCode::SET_8, OpCode::RETURN, OpCode::MUL_8, + OpCode::INTERNALRETURN, OpCode::ADD_8, OpCode::INTERNALRETURN, + OpCode::INTERNALCALL, OpCode::SET_32, OpCode::INTERNALCALL, + OpCode::INTERNALRETURN }; - for (size_t i = 0; i < 12; i++) { + for (size_t i = 0; i < 13; i++) { EXPECT_EQ(instructions.at(i).op_code, opcode_sequence.at(i)); } auto trace = gen_trace_from_bytecode(bytecode); // Expected sequence of PCs during execution - std::vector pc_sequence{ 0, 9, 18, 41, 35, 40, 46, 55, 29, 34, 60, 23 }; + std::vector pc_sequence{ 0, 9, 18, 46, 40, 45, 51, 60, 34, 39, 65, 23, 28 }; - for (size_t i = 0; i < 12; i++) { + for (size_t i = 0; i < 13; i++) { EXPECT_EQ(trace.at(i + 1).main_pc, pc_sequence.at(i)); } // Find the first row enabling the multiplication selector. auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_mul == 1; }); EXPECT_EQ(row->main_ic, 187); - EXPECT_EQ(row->main_pc, 29); + EXPECT_EQ(row->main_pc, 34); validate_trace(std::move(trace), public_inputs); } @@ -458,9 +513,9 @@ TEST_F(AvmExecutionTests, nestedInternalCalls) // We test bytecode which first invokes CALLDATACOPY on a FF array of two values. // Then, a JUMP call skips a SUB opcode to land to a FDIV operation and RETURN. // Calldata: [13, 156] -// Bytecode layout: SET_8 SET_8 CALLDATACOPY JUMP SUB FDIV RETURN -// Instr. Index: 0 1 2 3 4 5 6 -// PC index: 0 5 10 18 23 28 33 +// Bytecode layout: SET_8 SET_8 CALLDATACOPY JUMP SUB FDIV SET_8 RETURN +// Instr. Index: 0 1 2 3 4 5 6 7 +// PC index: 0 5 10 18 23 28 33 38 TEST_F(AvmExecutionTests, jumpAndCalldatacopy) { std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET @@ -490,16 +545,21 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) "0B" // addr 11 "0A" // addr 10 "01" // addr c 1 (156 / 13 = 12) - + to_hex(OpCode::RETURN) + // opcode RETURN + + to_hex(OpCode::SET_8) + // opcode SET (for return size) "00" // Indirect flag - "0000" // ret offset 0 - "0000" // ret size 0 + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0000" // ret offset 0 + "00FF" // ret size offset 255 ; auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(7)); + ASSERT_THAT(instructions, SizeIs(8)); // We test parsing steps for CALLDATACOPY and JUMP. @@ -522,9 +582,9 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) auto trace = gen_trace(bytecode, std::vector{ 13, 156 }, public_inputs_vec, returndata, execution_hints); // Expected sequence of PCs during execution - std::vector pc_sequence{ 0, 5, 10, 18, 28, 33 }; + std::vector pc_sequence{ 0, 5, 10, 18, 28, 33, 38 }; - for (size_t i = 0; i < 6; i++) { + for (size_t i = 0; i < 7; i++) { EXPECT_EQ(trace.at(i + 1).main_pc, pc_sequence.at(i)); } @@ -547,9 +607,9 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) // Then, we set value 20 (UINT16) at memory offset 101. // Then, a JUMPI call is performed. Depending of the conditional value, the next opcode (ADD) is // omitted or not, i.e., we jump to the subsequent opcode MUL. -// Bytecode layout: SET SET CALLDATACOPY SET JUMPI ADD MUL RETURN -// Instr. Index: 0 1 2 3 4 5 6 7 -// PC Index: 0 5 10 18 23 31 39 44 +// Bytecode layout: SET SET CALLDATACOPY SET JUMPI ADD MUL SET_8 RETURN +// Instr. Index: 0 1 2 3 4 5 6 7 8 +// PC Index: 0 5 10 18 23 31 39 44 49 // We test this bytecode with two calldatacopy inputs: {9873123} and {0}. TEST_F(AvmExecutionTests, jumpiAndCalldatacopy) { @@ -587,16 +647,21 @@ TEST_F(AvmExecutionTests, jumpiAndCalldatacopy) "65" // addr 101 "65" // addr 101 "66" // output of MUL addr 102 - + to_hex(OpCode::RETURN) + // opcode RETURN + + to_hex(OpCode::SET_8) + // opcode SET (for return size) "00" // Indirect flag - "0000" // ret offset 0 - "0000" // ret size 0 + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0000" // ret offset 0 + "00FF" // ret size offset 255 ; auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(8)); + ASSERT_THAT(instructions, SizeIs(9)); // We test parsing of JUMPI. @@ -613,15 +678,15 @@ TEST_F(AvmExecutionTests, jumpiAndCalldatacopy) auto trace_no_jump = gen_trace(bytecode, std::vector{ 0 }, public_inputs_vec, returndata, execution_hints); // Expected sequence of PCs during execution with jump - std::vector pc_sequence_jump{ 0, 5, 10, 18, 23, 39, 44 }; + std::vector pc_sequence_jump{ 0, 5, 10, 18, 23, 39, 44, 49 }; // Expected sequence of PCs during execution without jump - std::vector pc_sequence_no_jump{ 0, 5, 10, 18, 23, 31, 39, 44 }; + std::vector pc_sequence_no_jump{ 0, 5, 10, 18, 23, 31, 39, 44, 49 }; - for (size_t i = 0; i < 7; i++) { + for (size_t i = 0; i < 8; i++) { EXPECT_EQ(trace_jump.at(i + 1).main_pc, pc_sequence_jump.at(i)); } - for (size_t i = 0; i < 8; i++) { + for (size_t i = 0; i < 9; i++) { EXPECT_EQ(trace_no_jump.at(i + 1).main_pc, pc_sequence_no_jump.at(i)); } @@ -636,21 +701,26 @@ TEST_F(AvmExecutionTests, movOpcode) std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag + to_hex(AvmMemoryTag::U8) + - "13" // val 19 - "AB" // dst_offset 171 - + to_hex(OpCode::MOV_8) + // opcode MOV - "00" // Indirect flag - "AB" // src_offset 171 - "21" // dst_offset 33 + "13" // val 19 + "AB" // dst_offset 171 + + to_hex(OpCode::MOV_8) + // opcode MOV + "00" // Indirect flag + "AB" // src_offset 171 + "21" // dst_offset 33 + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(3)); + ASSERT_THAT(instructions, SizeIs(4)); // SET EXPECT_THAT(instructions.at(0), @@ -694,21 +764,26 @@ TEST_F(AvmExecutionTests, indMovOpcode) + to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag + to_hex(AvmMemoryTag::U8) + - "FF" // val 255 - "0A" // dst_offset 10 - + to_hex(OpCode::MOV_8) + // opcode MOV - "01" // Indirect flag - "01" // src_offset 1 --> direct offset 10 - "02" // dst_offset 2 --> direct offset 11 + "FF" // val 255 + "0A" // dst_offset 10 + + to_hex(OpCode::MOV_8) + // opcode MOV + "01" // Indirect flag + "01" // src_offset 1 --> direct offset 10 + "02" // dst_offset 2 --> direct offset 11 + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(5)); + ASSERT_THAT(instructions, SizeIs(6)); // MOV EXPECT_THAT(instructions.at(3), @@ -737,17 +812,22 @@ TEST_F(AvmExecutionTests, setAndCastOpcodes) + to_hex(OpCode::CAST_8) + // opcode CAST "00" // Indirect flag + to_hex(AvmMemoryTag::U8) + - "11" // addr a - "12" // addr casted a + "11" // addr a + "12" // addr casted a + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(3)); + ASSERT_THAT(instructions, SizeIs(4)); // SUB EXPECT_THAT(instructions.at(1), @@ -807,10 +887,15 @@ TEST_F(AvmExecutionTests, toRadixBeOpcodeBytes) "0080" // radix_offset 80 (direct) "0100" // limbs: 256 "00" // output_bits: false - + to_hex(OpCode::RETURN) + // opcode RETURN + + to_hex(OpCode::SET_16) + // opcode SET (for return size) "00" // Indirect flag - "0005" // ret offset 0 - "0100"; // ret size 0 + + to_hex(AvmMemoryTag::U32) + + "0100" // val: 256 + "0200" + // dst_offset=512 + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0005" // ret offset 5 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -876,10 +961,15 @@ TEST_F(AvmExecutionTests, toRadixBeOpcodeBitsMode) "0080" // radix_offset 80 (direct) "0100" // limbs: 256 "01" // output_bits: true - + to_hex(OpCode::RETURN) + // opcode RETURN + + to_hex(OpCode::SET_16) + // opcode SET (for return size) "00" // Indirect flag - "0005" // ret offset 0 - "0100"; // ret size 0 + + to_hex(AvmMemoryTag::U32) + + "0100" // val: 256 + "0200" + // dst_offset=512 + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0005" // ret offset 5 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -948,10 +1038,15 @@ TEST_F(AvmExecutionTests, sha256CompressionOpcode) "0100" // output offset "0001" // state offset "0009" // input offset - + to_hex(OpCode::RETURN) + // opcode RETURN + + to_hex(OpCode::SET_16) + // opcode SET (for return size) "00" // Indirect flag - "0100" // ret offset 256 - "0008"; // ret size 8 + + to_hex(AvmMemoryTag::U32) + + "0008" // val: 8 + "0200" // dst_offset=512 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0100" // ret offset 256 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -1010,10 +1105,15 @@ TEST_F(AvmExecutionTests, poseidon2PermutationOpCode) "03" // Indirect flag (first 2 operands indirect) "0024" // input offset (indirect 36) "0023" // output offset (indirect 35) - + to_hex(OpCode::RETURN) + // opcode RETURN + + to_hex(OpCode::SET_16) + // opcode SET (for return size) "00" // Indirect flag - "0009" // ret offset 256 - "0004"; // ret size 8 + + to_hex(AvmMemoryTag::U32) + + "0004" // val: 4 + "0200" // dst_offset=512 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0009" // ret offset 256 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -1037,7 +1137,6 @@ TEST_F(AvmExecutionTests, poseidon2PermutationOpCode) // Positive test with Keccakf1600. TEST_F(AvmExecutionTests, keccakf1600OpCode) { - // Test vectors taken noir/noir-repo/acvm-repo/blackbox_solver/src/hash.rs std::vector state = { 0xF1258F7940E1DDE7LLU, 0x84D5CCF933C0478ALLU, 0xD598261EA65AA9EELLU, 0xBD1547306F80494DLLU, @@ -1083,10 +1182,15 @@ TEST_F(AvmExecutionTests, keccakf1600OpCode) "03" // Indirect flag (first 2 operands indirect) "0023" // output offset (indirect 35) "0024" // input offset (indirect 36) - + to_hex(OpCode::RETURN) + // opcode RETURN + + to_hex(OpCode::SET_16) + // opcode SET (for return size) "00" // Indirect flag - "0100" // ret offset 256 - "0019"; // ret size 25 + + to_hex(AvmMemoryTag::U32) + + "0019" // val: 25 + "0200" // dst_offset=512 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0100" // ret offset 256 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -1112,14 +1216,14 @@ TEST_F(AvmExecutionTests, embeddedCurveAddOpCode) auto b_is_inf = b.is_point_at_infinity(); grumpkin::g1::affine_element res = a + b; auto expected_output = std::vector{ res.x, res.y, res.is_point_at_infinity() }; - std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "00" // val - "00" // dst_offset - + to_hex(OpCode::SET_8) + // opcode SET - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // + "00" // val + "00" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // "06" // val "01" // dst_offset + to_hex(OpCode::CALLDATACOPY) + // Calldatacopy @@ -1129,32 +1233,37 @@ TEST_F(AvmExecutionTests, embeddedCurveAddOpCode) "0000" // dst_offset + to_hex(OpCode::CAST_8) + // opcode CAST inf to U8 "00" // Indirect flag - + to_hex(AvmMemoryTag::U8) + - "02" // a_is_inf - "02" // a_is_inf - + to_hex(OpCode::CAST_8) + // opcode CAST inf to U8 - "00" // Indirect flag - + to_hex(AvmMemoryTag::U8) + - "05" // b_is_inf - "05" // b_is_inf - + to_hex(OpCode::SET_8) + // opcode SET for direct src_length - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "07" // value - "06" // dst_offset - + to_hex(OpCode::ECADD) + // opcode ECADD - "0040" // Indirect flag (sixth operand indirect) - "0000" // hash_index offset (direct) - "0001" // dest offset (direct) - "0002" // input offset (indirect) - "0003" // length offset (direct) - "0004" // length offset (direct) - "0005" // length offset (direct) - "0006" // length offset (direct) - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "0007" // ret offset 3 - "0003"; // ret size 1 + + to_hex(AvmMemoryTag::U1) + // + "02" // a_is_inf + "02" // a_is_inf + + to_hex(OpCode::CAST_8) + // opcode CAST inf to U8 + "00" // Indirect flag + + to_hex(AvmMemoryTag::U1) + // + "05" // b_is_inf + "05" // b_is_inf + + to_hex(OpCode::SET_8) + // opcode SET for direct src_length + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // + "07" // value + "06" // dst_offset + + to_hex(OpCode::ECADD) + // opcode ECADD + "0040" // Indirect flag (sixth operand indirect) + "0000" // lhs_x_offset (direct) + "0001" // lhs_y_offset (direct) + "0002" // lhs_is_inf_offset (direct) + "0003" // rhs_x_offset (direct) + "0004" // rhs_y_offset (direct) + "0005" // rhs_is_inf_offset (direct) + "0006" // output_offset (indirect) and resolves to 7 + + to_hex(OpCode::SET_16) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // + "0003" // val: 3 + "0200" // dst_offset=512 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0007" // ret offset 7 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -1189,16 +1298,17 @@ TEST_F(AvmExecutionTests, msmOpCode) // Send all the input as Fields and cast them to U8 later std::vector calldata = { FF(a.x), FF(a.y), a_is_inf, FF(b.x), FF(b.y), b_is_inf, scalar_a_lo, scalar_a_hi, scalar_b_lo, scalar_b_hi }; - std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "00" // val - "00" // dst_offset - + to_hex(OpCode::SET_8) + // opcode SET - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "0A" // val - "01" + + + std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // + "00" // val + "00" // dst_offset + + to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // + "0A" // val + "01" + // to_hex(OpCode::CALLDATACOPY) + // Calldatacopy "00" // Indirect flag "0000" // cd_offset 0 @@ -1206,44 +1316,49 @@ TEST_F(AvmExecutionTests, msmOpCode) "0000" // dst_offset 0 + to_hex(OpCode::CAST_8) + // opcode CAST inf to U8 "00" // Indirect flag - + to_hex(AvmMemoryTag::U8) + - "02" // a_is_inf - "02" // - + to_hex(OpCode::CAST_8) + // opcode CAST inf to U8 - "00" // Indirect flag - + to_hex(AvmMemoryTag::U8) + - "05" // b_is_inf - "05" // - + to_hex(OpCode::SET_8) + // opcode SET for length - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "06" // Length of point elements (6) - "0b" // dst offset (11) - + to_hex(OpCode::SET_8) + // SET Indirects - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "00" // points offset - "0d" // dst offset + - + to_hex(OpCode::SET_8) + // SET Indirects - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "06" // scalars offset - "0e" + // dst offset - to_hex(OpCode::SET_8) + // SET Indirects - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "0c" // output offset - "0f" + // dst offset - to_hex(OpCode::MSM) + // opcode MSM - "07" // Indirect flag (first 3 indirect) - "000d" // points offset - "000e" // scalars offset - "000f" // output offset - "000b" // length offset - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "000c" // ret offset 12 (this overwrites) - "0003"; // ret size 3 + + to_hex(AvmMemoryTag::U1) + // + "02" // a_is_inf + "02" // + + to_hex(OpCode::CAST_8) + // opcode CAST inf to U8 + "00" // Indirect flag + + to_hex(AvmMemoryTag::U1) + // + "05" // b_is_inf + "05" // + + to_hex(OpCode::SET_8) + // opcode SET for length + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // + "06" // Length of point elements (6) + "0b" // dst offset (11) + + to_hex(OpCode::SET_8) + // SET Indirects + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // + "00" // points offset + "0d" // dst offset + + + to_hex(OpCode::SET_8) + // SET Indirects + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // + "06" // scalars offset + "0e" + // dst offset + to_hex(OpCode::SET_8) + // SET Indirects + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // + "0c" // output offset + "0f" + // dst offset + to_hex(OpCode::MSM) + // opcode MSM + "07" // Indirect flag (first 3 indirect) + "000d" // points offset + "000e" // scalars offset + "000f" // output offset + "000b" // length offset + + to_hex(OpCode::SET_16) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // + "0003" // val: 3 + "0200" // dst_offset=512 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "000c" // ret offset 12 (this overwrites) + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -1306,15 +1421,20 @@ TEST_F(AvmExecutionTests, getEnvOpcode) "00" // Indirect flag + to_hex(static_cast(EnvironmentVariable::ISSTATICCALL)) + // envvar ISSTATICCALL "000B" // dst_offset + + to_hex(OpCode::SET_16) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // tag U32 + "000B" // val: 12 + "0200" // dst_offset=512 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0001" // ret offset 1 - "000B"; // ret size 12 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(12)); + ASSERT_THAT(instructions, SizeIs(13)); // ADDRESS EXPECT_THAT(instructions.at(0), @@ -1548,16 +1668,21 @@ TEST_F(AvmExecutionTests, l2GasLeft) + to_hex(OpCode::GETENVVAR_16) + // opcode L2GASLEFT "01" // Indirect flag + to_hex(static_cast(EnvironmentVariable::L2GASLEFT)) + - "0011" // dst_offset (indirect addr: 17) + "0011" // dst_offset (indirect addr: 17) + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(3)); + ASSERT_THAT(instructions, SizeIs(4)); // L2GASLEFT EXPECT_THAT(instructions.at(1), @@ -1592,16 +1717,21 @@ TEST_F(AvmExecutionTests, daGasLeft) + to_hex(OpCode::GETENVVAR_16) + // opcode DAGASLEFT "00" // Indirect flag + to_hex(static_cast(EnvironmentVariable::DAGASLEFT)) + - "0027" // dst_offset (indirect addr: 17) + "0027" // dst_offset (indirect addr: 17) + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(3)); + ASSERT_THAT(instructions, SizeIs(4)); // DAGASLEFT EXPECT_THAT(instructions.at(1), @@ -1669,6 +1799,11 @@ TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes) { // Set values into the first register to emit std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode Set + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // tag U32 + "00" // value 0 + "02" // dst_offset 2 + + to_hex(OpCode::SET_8) + // opcode Set "00" // Indirect flag + to_hex(AvmMemoryTag::U32) + // tag U32 "01" // value 1 @@ -1700,7 +1835,7 @@ TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes) auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(7)); + ASSERT_THAT(instructions, SizeIs(8)); std::vector calldata = {}; std::vector returndata = {}; @@ -1739,12 +1874,32 @@ TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes) feed_output(emit_nullifier_out_offset, 1, 1, 0); // CHECK EMIT UNENCRYPTED LOG + // Unencrypted logs are hashed with sha256 and truncated to 31 bytes - and then padded back to 32 bytes + auto [contract_class_id, contract_instance] = gen_test_contract_hint(bytecode); + FF address = AvmBytecodeTraceBuilder::compute_address_from_instance(contract_instance); + + std::vector contract_address_bytes = address.to_buffer(); + // Test log is empty, so just have to hash the contract address with 0 + // + std::vector bytes_to_hash; + bytes_to_hash.insert(bytes_to_hash.end(), + std::make_move_iterator(contract_address_bytes.begin()), + std::make_move_iterator(contract_address_bytes.end())); + uint32_t num_bytes = 0; + std::vector log_size_bytes = to_buffer(num_bytes); + // Add the log size to the hash to bytes + bytes_to_hash.insert(bytes_to_hash.end(), + std::make_move_iterator(log_size_bytes.begin()), + std::make_move_iterator(log_size_bytes.end())); + + std::array output = crypto::sha256(bytes_to_hash); + // Truncate the hash to 31 bytes so it will be a valid field element + FF expected_hash = FF(from_buffer(output.data()) >> 8); + auto emit_log_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_emit_unencrypted_log == 1; }); ASSERT_TRUE(emit_log_row != trace.end()); - // Trust me bro for now, this is the truncated sha output - FF expected_hash = FF(std::string("0x00b5c135991581f3049df936e35ef23af34bb04a4775426481d944d35a618e9d")); EXPECT_EQ(emit_log_row->main_ia, expected_hash); EXPECT_EQ(emit_log_row->main_side_effect_counter, 2); // Value is 40 = 32 * log_length + 40 (and log_length is 0 in this case). @@ -1790,21 +1945,26 @@ TEST_F(AvmExecutionTests, kernelOutputStorageLoadOpcodeSimple) + to_hex(OpCode::CAST_8) + // opcode CAST (Cast set to field) "00" // Indirect flag + to_hex(AvmMemoryTag::FF) + - "01" // dst 1 - "01" // dst 1 - + to_hex(OpCode::SLOAD) + // opcode SLOAD - "00" // Indirect flag - "0001" // slot offset 1 - "0002" // write storage value to offset 2 + "01" // dst 1 + "01" // dst 1 + + to_hex(OpCode::SLOAD) + // opcode SLOAD + "00" // Indirect flag + "0001" // slot offset 1 + "0002" // write storage value to offset 2 + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(4)); + ASSERT_THAT(instructions, SizeIs(5)); std::vector calldata = {}; std::vector returndata = {}; @@ -1857,10 +2017,15 @@ TEST_F(AvmExecutionTests, kernelOutputStorageStoreOpcodeSimple) "00" // Indirect flag "0001" // src offset "0003" // slot offset + + to_hex(OpCode::SET_16) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // tag U32 + "0000" // val: 0 + "0200" // dst_offset=512 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -1914,15 +2079,20 @@ TEST_F(AvmExecutionTests, kernelOutputStorageOpcodes) "00" // Indirect flag "0002" // src offset 2 (since the sload writes to 2) "0001" // slot offset is 1 + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(5)); + ASSERT_THAT(instructions, SizeIs(6)); std::vector calldata = {}; std::vector returndata = {}; @@ -1995,15 +2165,20 @@ TEST_F(AvmExecutionTests, kernelOutputHashExistsOpcodes) "0001" // slot offset 1 "0002" // Lead offset 2 "0003" // value write offset 2 (exists value) + + to_hex(OpCode::SET_16) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // tag U32 + "0000" // val: 0 + "0200" // dst_offset=512 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(6)); + ASSERT_THAT(instructions, SizeIs(7)); std::vector calldata = {}; std::vector returndata = {}; @@ -2073,6 +2248,7 @@ TEST_F(AvmExecutionTests, opCallOpcodes) // Calldata for l2_gas, da_gas, contract_address, nested_call_args (4 elements), std::vector calldata = { 17, 10, 34802342, 1, 2, 3, 4 }; std::string bytecode_preamble; + // Set up Gas offsets bytecode_preamble += to_hex(OpCode::SET_8) + // opcode SET for gas offset indirect "00" // Indirect flag @@ -2092,11 +2268,16 @@ TEST_F(AvmExecutionTests, opCallOpcodes) "03" // val 3 (the start of the args array) "13"; // dst_offset 19 // Set up args size offset - bytecode_preamble += to_hex(OpCode::SET_8) + // opcode SET for ret offset indirect + bytecode_preamble += to_hex(OpCode::SET_8) + // opcode SET for args size indirect "00" // Indirect flag + to_hex(AvmMemoryTag::U32) + - "04" // val 4 (the length of the args array) - "14"; // dst_offset 20 + "04" // val 4 - resolved address + "14"; // dst_offset 20 + bytecode_preamble += to_hex(OpCode::SET_8) + // opcode SET + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // + "00" // val 0 (args size) + "04"; // dst_offset 4 // Set up the ret offset bytecode_preamble += to_hex(OpCode::SET_16) + // opcode SET for ret offset indirect "00" // Indirect flag @@ -2104,7 +2285,7 @@ TEST_F(AvmExecutionTests, opCallOpcodes) "0100" // val 256 (the start of where to write the return data) "0015"; // dst_offset 21 // Set up the success offset - bytecode_preamble += to_hex(OpCode::SET_16) + // opcode SET for ret offset indirect + bytecode_preamble += to_hex(OpCode::SET_16) + // opcode SET for success offset indirect "00" // Indirect flag + to_hex(AvmMemoryTag::U32) + "0102" // val 258 (write the success flag at ret_offset + ret_size) @@ -2138,10 +2319,15 @@ TEST_F(AvmExecutionTests, opCallOpcodes) "0011" // start offset (0) "0012" // ret size (2) "0100" // dst offset + + to_hex(OpCode::SET_16) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // tag U32 + "0003" // val: 3 (extra read is for the success flag) + "0200" // dst_offset=512 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0100" // ret offset 8 - "0003"; // ret size 3 (extra read is for the success flag) + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -2192,8 +2378,8 @@ TEST_F(AvmExecutionTests, opGetContractInstanceOpcode) std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag - + to_hex(AvmMemoryTag::U8) + to_hex(address_byte) + // val - "01" // dst_offset 0 + + to_hex(AvmMemoryTag::FF) + to_hex(address_byte) + // val + "01" // dst_offset 1 + to_hex(OpCode::GETCONTRACTINSTANCE) + // opcode GETCONTRACTINSTANCE "00" // Indirect flag + to_hex(static_cast(ContractInstanceMember::DEPLOYER)) + // member enum @@ -2212,15 +2398,20 @@ TEST_F(AvmExecutionTests, opGetContractInstanceOpcode) "0001" // address offset "0014" // dst offset "0015" // exists offset - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "0010" // ret offset 1 - "0006"; // ret size 6 (dst & exists for all 3) + + to_hex(OpCode::SET_16) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // tag U32 + "0006" // val: 6 (dst & exists for all 3) + "0200" // dst_offset=512 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0010" // ret offset 1 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(5)); + ASSERT_THAT(instructions, SizeIs(6)); std::vector const calldata{}; // alternating member value, exists bool diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/gas.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/gas.test.cpp index 50fc78456ea..26cfe7468c7 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/gas.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/gas.test.cpp @@ -44,7 +44,8 @@ void test_gas(StartGas startGas, OpcodesFunc apply_opcodes, CheckFunc check_trac // We should return a value of 1 for the sender, as it exists at index 0 apply_opcodes(trace_builder); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/indirect_mem.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/indirect_mem.test.cpp index 7e3b48ffaed..e98acc28c6a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/indirect_mem.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/indirect_mem.test.cpp @@ -42,7 +42,8 @@ TEST_F(AvmIndirectMemTests, allIndirectAdd) // All indirect flags are encoded as 7 = 1 + 2 + 4 trace_builder.op_add(7, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the addition selector @@ -91,7 +92,8 @@ TEST_F(AvmIndirectMemTests, indirectOutputSub) // The indirect flag is encoded as 4 trace_builder.op_sub(4, 50, 51, 5); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the subtraction selector @@ -139,7 +141,8 @@ TEST_F(AvmIndirectMemTests, indirectInputAMul) // The indirect flag is encoded as 1 trace_builder.op_mul(1, 1000, 101, 102); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the multiplication selector diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp index ac0088fbbb4..b913418b678 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp @@ -58,7 +58,8 @@ class AvmPermMainAluNegativeTests : public AvmInterTableTests { trace_builder.op_add(0, 0, 1, 1); // 19 + 15 = 34 trace_builder.op_add(0, 0, 1, 1); // 19 + 34 = 53 trace_builder.op_mul(0, 0, 1, 2); // 19 * 53 = 1007 - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); @@ -153,7 +154,8 @@ class AvmRangeCheckNegativeTests : public AvmInterTableTests { trace_builder.op_set(0, a, 0, tag); trace_builder.op_set(0, b, 1, tag); trace_builder.op_add(0, 0, 1, 2); // 7 + 8 = 15 - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); // Find the row with addition operation and retrieve clk. @@ -404,7 +406,8 @@ class AvmPermMainMemNegativeTests : public AvmInterTableTests { trace_builder.op_set(0, a, 52, AvmMemoryTag::U8); trace_builder.op_set(0, b, 11, AvmMemoryTag::U8); trace_builder.op_sub(0, 52, 11, 55); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); @@ -450,7 +453,8 @@ TEST_F(AvmPermMainMemNegativeTests, tagErrNotCopiedInMain) trace_builder.op_set(0, 32, 18, AvmMemoryTag::U128); trace_builder.op_set(0, 32, 76, AvmMemoryTag::U16); trace_builder.op_eq(0, 18, 76, 65); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the row with equality operation and mutate the error tag. diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp index 2143d2419f2..219f8c668b7 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp @@ -75,7 +75,8 @@ void test_kernel_lookup(bool indirect, apply_opcodes(trace_builder); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); @@ -582,7 +583,8 @@ void negative_test_incorrect_ia_kernel_lookup(OpcodesFunc apply_opcodes, // We should return a value of 1 for the sender, as it exists at index 0 apply_opcodes(trace_builder); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp index f218f873053..40a0d822d24 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp @@ -56,7 +56,8 @@ class AvmMemOpcodeTests : public ::testing::Test { } trace_builder.op_mov(indirect ? 3 : 0, src_offset, dst_offset); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); } @@ -218,7 +219,8 @@ TEST_F(AvmMemOpcodeTests, uninitializedValueMov) { trace_builder.op_set(0, 4, 1, AvmMemoryTag::U32); trace_builder.op_mov(0, 0, 1); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); validate_mov_trace(false, 0, 0, 1, AvmMemoryTag::FF); @@ -233,7 +235,8 @@ TEST_F(AvmMemOpcodeTests, indUninitializedValueMov) trace_builder.op_set(0, 4, 1, AvmMemoryTag::U32); trace_builder.op_set(0, 5, 2, AvmMemoryTag::U32); trace_builder.op_mov(3, 2, 3); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); validate_mov_trace(true, 0, 2, 3, AvmMemoryTag::FF, 5, 1); @@ -247,7 +250,8 @@ TEST_F(AvmMemOpcodeTests, indUninitializedAddrMov) trace_builder.op_set(0, 1, 3, AvmMemoryTag::U32); trace_builder.op_set(0, 4, 1, AvmMemoryTag::U32); trace_builder.op_mov(3, 2, 3); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); validate_mov_trace(true, 0, 2, 3, AvmMemoryTag::FF, 0, 1, true); @@ -271,7 +275,8 @@ TEST_F(AvmMemOpcodeTests, indirectMovInvalidAddressTag) trace_builder.op_set(0, 16, 101, AvmMemoryTag::U128); // This will make the indirect load failing. trace_builder.op_set(0, 5, 15, AvmMemoryTag::FF); trace_builder.op_mov(3, 100, 101); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); compute_mov_indices(true); @@ -293,7 +298,8 @@ TEST_F(AvmMemOpcodeTests, indirectMovInvalidAddressTag) TEST_F(AvmMemOpcodeTests, directSet) { trace_builder.op_set(0, 5683, 99, AvmMemoryTag::U128); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); compute_index_c(1, false); @@ -321,7 +327,8 @@ TEST_F(AvmMemOpcodeTests, indirectSet) { trace_builder.op_set(0, 100, 10, AvmMemoryTag::U32); trace_builder.op_set(1, 1979, 10, AvmMemoryTag::U64); // Set 1979 at memory index 100 - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); // TODO(JEANMON): Turn following boolean to true once we have constraining address resolution @@ -367,7 +374,8 @@ TEST_F(AvmMemOpcodeTests, indirectSetWrongTag) trace_builder.op_set(0, 100, 10, AvmMemoryTag::U8); // The address 100 has incorrect tag U8. trace_builder.op_set(1, 1979, 10, AvmMemoryTag::U64); // Set 1979 at memory index 100 - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); compute_index_c(2, true); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp index 1232d3023c4..7502b743de1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp @@ -43,7 +43,8 @@ TEST_F(AvmMemoryTests, mismatchedTagAddOperation) trace_builder.op_set(0, 12, 1, AvmMemoryTag::U16); trace_builder.op_add(0, 0, 1, 4); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the addition selector @@ -90,7 +91,8 @@ TEST_F(AvmMemoryTests, mismatchedTagEqOperation) trace_builder.op_set(0, 5, 1, AvmMemoryTag::U16); trace_builder.op_eq(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the equality selector @@ -134,7 +136,8 @@ TEST_F(AvmMemoryTests, mLastAccessViolation) // Memory layout: [4,9,0,0,0,0,....] trace_builder.op_sub(0, 1, 0, 2); // [4,9,5,0,0,0.....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the row with subtraction operation @@ -165,14 +168,15 @@ TEST_F(AvmMemoryTests, readWriteConsistencyValViolation) // Memory layout: [4,9,0,0,0,0,....] trace_builder.op_mul(0, 1, 0, 2); // [4,9,36,0,0,0.....] - trace_builder.op_return(0, 2, 1); // Return single memory word at position 2 (36) + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 2, 100); // Return single memory word at position 2 (36) auto trace = trace_builder.finalize(); // Find the row with multiplication operation auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_mul == FF(1); }); EXPECT_TRUE(row != trace.end()); - auto clk = row->main_clk + 1; // return operation is just after the multiplication + auto clk = row->main_clk + 2; // return operation is two opcodes after the multiplication // Find the row for memory trace with last memory entry for address 2 (read for multiplication) row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { @@ -195,14 +199,15 @@ TEST_F(AvmMemoryTests, readWriteConsistencyTagViolation) // Memory layout: [4,9,0,0,0,0,....] trace_builder.op_mul(0, 1, 0, 2); // [4,9,36,0,0,0.....] - trace_builder.op_return(0, 2, 1); // Return single memory word at position 2 (36) + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 2, 100); // Return single memory word at position 2 (36) auto trace = trace_builder.finalize(); // Find the row with multiplication operation auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_mul == FF(1); }); EXPECT_TRUE(row != trace.end()); - auto clk = row->main_clk + 1; // return operation is just after the multiplication + auto clk = row->main_clk + 2; // return operation is two opcodes after the multiplication // Find the row for memory trace with last memory entry for address 2 (read for multiplication) row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { @@ -220,7 +225,8 @@ TEST_F(AvmMemoryTests, readWriteConsistencyTagViolation) // Testing violation that a memory read at uninitialized location must have value 0. TEST_F(AvmMemoryTests, readUninitializedMemoryViolation) { - trace_builder.op_return(0, 1, 1); // Return single memory word at position 1 + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 1, 100); // Return single memory word at position 1 auto trace = trace_builder.finalize(); trace[1].mem_val = 9; @@ -238,7 +244,8 @@ TEST_F(AvmMemoryTests, mismatchedTagErrorViolation) trace_builder.op_set(0, 12, 1, AvmMemoryTag::U16); trace_builder.op_sub(0, 0, 1, 4); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the subtraction selector @@ -269,7 +276,8 @@ TEST_F(AvmMemoryTests, consistentTagNoErrorViolation) trace_builder.op_set(0, 2, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_fdiv(0, 0, 1, 4); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -298,7 +306,8 @@ TEST_F(AvmMemoryTests, noErrorTagWriteViolation) trace_builder.op_set(0, 2, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_fdiv(0, 0, 1, 4); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -330,7 +339,8 @@ TEST_F(AvmMemoryTests, directRelativeMemory) // Addition with direct relative addressing on the 2 input operands and direct addressing on the output // indirect byte: 00011000 = 24 trace_builder.op_add(24, 10, 100, 10); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the add selector @@ -361,7 +371,8 @@ TEST_F(AvmMemoryTests, indirectRelativeMemory) // Output c = a + b = 8 is stored at direct relative offset 2, i.e., address 102. // indirect byte: 00111011 = 1 + 2 + 8 + 16 + 32 = 59 trace_builder.op_add(59, 23, 47, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the add selector diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/recursive_verifier.test.cpp index 1de397a31f2..19eeab6d419 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/recursive_verifier.test.cpp @@ -53,7 +53,8 @@ class AvmRecursiveTests : public ::testing::Test { trace_builder.op_set(0, 1, 1, AvmMemoryTag::U8); trace_builder.op_set(0, 1, 2, AvmMemoryTag::U8); trace_builder.op_add(0, 1, 2, 3); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Passing true enables a longer trace with lookups inject_end_gas_values(public_inputs, trace); @@ -120,7 +121,7 @@ TEST_F(AvmRecursiveTests, recursion) // Make a proof of the verification of an AVM proof const size_t srs_size = 1 << 23; auto ultra_instance = std::make_shared( - outer_circuit, TraceStructure::NONE, std::make_shared>(srs_size)); + outer_circuit, TraceSettings{}, std::make_shared>(srs_size)); OuterProver ultra_prover(ultra_instance); auto ultra_verification_key = std::make_shared(ultra_instance->proving_key); OuterVerifier ultra_verifier(ultra_verification_key); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp index 9a43ef6bf27..d3a3c8883ec 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp @@ -47,7 +47,8 @@ class AvmSliceTests : public ::testing::Test { trace_builder.op_set(0, col_offset, 0, AvmMemoryTag::U32); trace_builder.op_set(0, copy_size, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(static_cast(indirect), 0, 1, dst_offset); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); } @@ -170,7 +171,8 @@ TEST_F(AvmSliceTests, twoCallsNoOverlap) trace_builder.op_set(0, 3, 1, AvmMemoryTag::U32); trace_builder.op_set(0, 2, 2, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 1, 2, 2123); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); // Main trace views of rows enabling the calldata_copy selector @@ -207,7 +209,8 @@ TEST_F(AvmSliceTests, indirectTwoCallsOverlap) trace_builder.op_set(0, 3, 3, AvmMemoryTag::U32); trace_builder.op_calldata_copy(4, 1, 3, 100); trace_builder.op_calldata_copy(4, 2, 3, 101); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); // Main trace views of rows enabling the calldata_copy selector @@ -250,7 +253,8 @@ TEST_F(AvmSliceTests, indirectFailedResolution) trace_builder.op_set(0, 1, 1, AvmMemoryTag::U32); trace_builder.op_set(0, 3, 3, AvmMemoryTag::U32); trace_builder.op_calldata_copy(4, 1, 3, 100); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); // Check that slice trace is empty @@ -321,7 +325,8 @@ TEST_F(AvmSliceNegativeTests, wrongCDValueInCalldataVerifier) { gen_trace_builder({ 2, 3, 4, 5, 6 }); trace_builder.op_calldata_copy(0, 1, 3, 100); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); validate_trace(std::move(trace), public_inputs, { 2, 3, 4, 5, 7 }, {}, false, true); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/alu_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/alu_trace.cpp index 25d1b54ebc6..3b4f198b127 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/alu_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/alu_trace.cpp @@ -106,10 +106,14 @@ void AvmAluTraceBuilder::reset() FF AvmAluTraceBuilder::op_add(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t const clk) { bool carry = false; - uint256_t c_u256 = uint256_t(a) + uint256_t(b); - FF c = cast_to_mem_tag(c_u256, in_tag); + FF c; + + if (in_tag == AvmMemoryTag::FF) { + c = a + b; + } else { + uint256_t c_u256 = uint256_t(a) + uint256_t(b); + c = cast_to_mem_tag(c_u256, in_tag); - if (in_tag != AvmMemoryTag::FF) { // a_u128 + b_u128 >= 2^128 <==> c_u128 < a_u128 if (uint128_t(c) < uint128_t(a)) { carry = true; @@ -150,10 +154,14 @@ FF AvmAluTraceBuilder::op_add(FF const& a, FF const& b, AvmMemoryTag in_tag, uin FF AvmAluTraceBuilder::op_sub(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t const clk) { bool carry = false; - uint256_t c_u256 = uint256_t(a) - uint256_t(b); - FF c = cast_to_mem_tag(c_u256, in_tag); + FF c; + + if (in_tag == AvmMemoryTag::FF) { + c = a - b; + } else { + uint256_t c_u256 = uint256_t(a) - uint256_t(b); + c = cast_to_mem_tag(c_u256, in_tag); - if (in_tag != AvmMemoryTag::FF) { // Underflow when a_u128 < b_u128 if (uint128_t(a) < uint128_t(b)) { carry = true; @@ -189,29 +197,41 @@ FF AvmAluTraceBuilder::op_sub(FF const& a, FF const& b, AvmMemoryTag in_tag, uin */ FF AvmAluTraceBuilder::op_mul(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t const clk) { - uint256_t a_u256{ a }; - uint256_t b_u256{ b }; - uint256_t c_u256 = a_u256 * b_u256; // Multiplication over the integers (not mod. 2^128) + FF c = 0; + uint256_t alu_a_lo = 0; + uint256_t alu_a_hi = 0; + uint256_t alu_b_lo = 0; + uint256_t alu_b_hi = 0; + uint256_t c_hi = 0; + uint256_t partial_prod_lo = 0; + uint256_t partial_prod_hi = 0; - FF c = cast_to_mem_tag(c_u256, in_tag); + if (in_tag == AvmMemoryTag::FF) { + c = a * b; + } else { - uint8_t bits = mem_tag_bits(in_tag); - // limbs are size 1 for u1 - uint8_t limb_bits = bits == 1 ? 1 : bits / 2; - uint8_t num_bits = bits; + uint256_t a_u256{ a }; + uint256_t b_u256{ b }; + uint256_t c_u256 = a_u256 * b_u256; // Multiplication over the integers (not mod. 2^128) - // Decompose a - auto [alu_a_lo, alu_a_hi] = decompose(a_u256, limb_bits); - // Decompose b - auto [alu_b_lo, alu_b_hi] = decompose(b_u256, limb_bits); + c = cast_to_mem_tag(c_u256, in_tag); - uint256_t partial_prod = alu_a_lo * alu_b_hi + alu_a_hi * alu_b_lo; - // Decompose the partial product - auto [partial_prod_lo, partial_prod_hi] = decompose(partial_prod, limb_bits); + uint8_t bits = mem_tag_bits(in_tag); + // limbs are size 1 for u1 + uint8_t limb_bits = bits == 1 ? 1 : bits / 2; + uint8_t num_bits = bits; - auto c_hi = c_u256 >> num_bits; + // Decompose a + std::tie(alu_a_lo, alu_a_hi) = decompose(a_u256, limb_bits); + // Decompose b + std::tie(alu_b_lo, alu_b_hi) = decompose(b_u256, limb_bits); + + uint256_t partial_prod = alu_a_lo * alu_b_hi + alu_a_hi * alu_b_lo; + // Decompose the partial product + std::tie(partial_prod_lo, partial_prod_hi) = decompose(partial_prod, limb_bits); + + c_hi = c_u256 >> num_bits; - if (in_tag != AvmMemoryTag::FF) { cmp_builder.range_check_builder.assert_range(uint128_t(c), mem_tag_bits(in_tag), EventEmitter::ALU, clk); } @@ -267,7 +287,7 @@ FF AvmAluTraceBuilder::op_div(FF const& a, FF const& b, AvmMemoryTag in_tag, uin static_cast(c_u256), mem_tag_bits(in_tag), EventEmitter::ALU, clk); } // Also check the remainder < divisor (i.e. remainder < b) - bool is_gt = cmp_builder.constrained_gt(b, rem_u256, clk, EventEmitter::ALU); + bool is_gt = cmp_builder.constrained_non_ff_gt(uint128_t(b), uint128_t(rem_u256), clk, EventEmitter::ALU); AvmAluTraceBuilder::AluTraceEntry row{ .alu_clk = clk, @@ -348,7 +368,12 @@ FF AvmAluTraceBuilder::op_eq(FF const& a, FF const& b, AvmMemoryTag in_tag, uint FF AvmAluTraceBuilder::op_lt(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t const clk) { // Note: This is counter-intuitive, to show that a < b we use the GT gadget with the inputs swapped - bool result = cmp_builder.constrained_gt(b, a, clk, EventEmitter::ALU); + bool result = false; + if (in_tag == AvmMemoryTag::FF) { + result = cmp_builder.constrained_gt(b, a, clk, EventEmitter::ALU); + } else { + result = cmp_builder.constrained_non_ff_gt(uint128_t(b), uint128_t(a), clk, EventEmitter::ALU); + } bool c = result; // The subtlety is here that the circuit is designed as a GT(x,y) circuit, therefore we swap the inputs a & b @@ -383,7 +408,12 @@ FF AvmAluTraceBuilder::op_lt(FF const& a, FF const& b, AvmMemoryTag in_tag, uint FF AvmAluTraceBuilder::op_lte(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t const clk) { // Note: This is counter-intuitive, to show that a <= b we actually show that a > b and then invert the answer - bool result = cmp_builder.constrained_gt(a, b, clk, EventEmitter::ALU); + bool result = false; + if (in_tag == AvmMemoryTag::FF) { + result = cmp_builder.constrained_gt(a, b, clk, EventEmitter::ALU); + } else { + result = cmp_builder.constrained_non_ff_gt(uint128_t(a), uint128_t(b), clk, EventEmitter::ALU); + } bool c = !result; // Construct the row that performs the lte check @@ -450,9 +480,8 @@ FF AvmAluTraceBuilder::op_not(FF const& a, AvmMemoryTag in_tag, uint32_t const c */ FF AvmAluTraceBuilder::op_shl(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t clk) { - // TODO(9497): this should raise error flag in main trace, not assert - ASSERT(in_tag != AvmMemoryTag::FF); - // Check that the shifted amount is an 8-bit integer + // Check that the shifted amount is an 8-bit integer. + // Caller from trace.cpp ensures that the tag is U8. ASSERT(uint256_t(b) < 256); // Perform the shift operation over 256-bit integers @@ -466,7 +495,7 @@ FF AvmAluTraceBuilder::op_shl(FF const& a, FF const& b, AvmMemoryTag in_tag, uin auto [a_lo, a_hi] = decompose(a, num_bits - b_u8); // Check if this is a trivial shift - i.e. we shift more than the max bits of our input - bool zero_shift = cmp_builder.constrained_gt(b, num_bits - 1, clk, EventEmitter::ALU); + bool zero_shift = cmp_builder.constrained_non_ff_gt(uint128_t(b), num_bits - 1, clk, EventEmitter::ALU); if (!zero_shift) { u8_pow_2_counters[0][b_u8]++; u8_pow_2_counters[1][num_bits - b_u8]++; @@ -513,9 +542,8 @@ FF AvmAluTraceBuilder::op_shl(FF const& a, FF const& b, AvmMemoryTag in_tag, uin */ FF AvmAluTraceBuilder::op_shr(FF const& a, FF const& b, AvmMemoryTag in_tag, uint32_t clk) { - // TODO(9497): this should raise error flag in main trace, not assert - ASSERT(in_tag != AvmMemoryTag::FF); - // Check that the shifted amount is an 8-bit integer + // Check that the shifted amount is an 8-bit integer. + // Caller from trace.cpp ensures that the tag is U8. ASSERT(uint256_t(b) < 256); // Perform the shift operation over 256-bit integers @@ -526,7 +554,7 @@ FF AvmAluTraceBuilder::op_shr(FF const& a, FF const& b, AvmMemoryTag in_tag, uin FF c = cast_to_mem_tag(c_u256, in_tag); uint8_t num_bits = mem_tag_bits(in_tag); - bool zero_shift = cmp_builder.constrained_gt(b, num_bits - 1, clk, EventEmitter::ALU); + bool zero_shift = cmp_builder.constrained_non_ff_gt(uint128_t(b), num_bits - 1, clk, EventEmitter::ALU); if (!zero_shift) { // Add counters for the pow of two lookups u8_pow_2_counters[0][b_u8]++; @@ -708,8 +736,9 @@ void AvmAluTraceBuilder::finalize(std::vector>& main_trace) dest.alu_cmp_gadget_input_a = src.cmp_input_a; dest.alu_cmp_gadget_input_b = src.cmp_input_b; dest.alu_cmp_gadget_result = src.cmp_result; - dest.alu_cmp_gadget_gt = FF(static_cast(src.cmp_op_is_gt)); - dest.alu_cmp_gadget_sel = dest.alu_cmp_gadget_gt + dest.alu_op_eq; + dest.alu_cmp_gadget_gt = FF(static_cast(src.cmp_op_is_gt && src.tag == AvmMemoryTag::FF)); + dest.alu_cmp_gadget_non_ff_gt = FF(static_cast(src.cmp_op_is_gt && src.tag != AvmMemoryTag::FF)); + dest.alu_cmp_gadget_sel = dest.alu_cmp_gadget_gt + dest.alu_op_eq + dest.alu_cmp_gadget_non_ff_gt; } reset(); } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/alu_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/alu_trace.hpp index f75bd99d6c1..a75fc8cb250 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/alu_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/alu_trace.hpp @@ -59,6 +59,7 @@ class AvmAluTraceBuilder { FF cmp_input_b{}; FF cmp_result{}; bool cmp_op_is_gt = false; + bool cmp_op_is_gt_non_ff = false; bool cmp_op_is_eq = false; }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/common.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/common.hpp index fd5de470550..c8983191ec4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/common.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/common.hpp @@ -49,6 +49,16 @@ enum class AvmMemoryTag : uint32_t { static const uint32_t MAX_MEM_TAG = MEM_TAG_U128; +enum class AvmError : uint32_t { + NO_ERROR, + TAG_ERROR, + ADDR_RES_ERROR, + DIV_ZERO, + PARSING_ERROR, + ENV_VAR_UNKNOWN, + CONTRACT_INST_MEM_UNKNOWN +}; + static const size_t NUM_MEM_SPACES = 256; static const uint8_t INTERNAL_CALL_SPACE_ID = 255; static const uint32_t MAX_SIZE_INTERNAL_STACK = 1 << 16; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp index 4d15050345c..71385470d45 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp @@ -287,9 +287,9 @@ std::vector Execution::gen_trace(std::vector const& calldata, // is determined by this value which require read access to the code below. uint32_t pc = 0; uint32_t counter = 0; - while ((pc = trace_builder.get_pc()) < bytecode.size()) { + AvmError error = AvmError::NO_ERROR; + while (error == AvmError::NO_ERROR && (pc = trace_builder.get_pc()) < bytecode.size()) { auto inst = Deserialization::parse(bytecode, pc); - debug("[PC:" + std::to_string(pc) + "] [IC:" + std::to_string(counter++) + "] " + inst.to_string() + " (gasLeft l2=" + std::to_string(trace_builder.get_l2_gas_left()) + ")"); @@ -297,404 +297,405 @@ std::vector Execution::gen_trace(std::vector const& calldata, // Compute // Compute - Arithmetic case OpCode::ADD_8: - trace_builder.op_add(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::ADD_8); + error = trace_builder.op_add(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::ADD_8); break; case OpCode::ADD_16: - trace_builder.op_add(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::ADD_16); + error = trace_builder.op_add(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::ADD_16); break; case OpCode::SUB_8: - trace_builder.op_sub(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::SUB_8); + error = trace_builder.op_sub(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::SUB_8); break; case OpCode::SUB_16: - trace_builder.op_sub(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::SUB_16); + error = trace_builder.op_sub(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::SUB_16); break; case OpCode::MUL_8: - trace_builder.op_mul(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::MUL_8); + error = trace_builder.op_mul(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::MUL_8); break; case OpCode::MUL_16: - trace_builder.op_mul(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::MUL_16); + error = trace_builder.op_mul(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::MUL_16); break; case OpCode::DIV_8: - trace_builder.op_div(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::DIV_8); + error = trace_builder.op_div(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::DIV_8); break; case OpCode::DIV_16: - trace_builder.op_div(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::DIV_16); + error = trace_builder.op_div(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::DIV_16); break; case OpCode::FDIV_8: - trace_builder.op_fdiv(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::FDIV_8); + error = trace_builder.op_fdiv(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::FDIV_8); break; case OpCode::FDIV_16: - trace_builder.op_fdiv(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::FDIV_16); + error = trace_builder.op_fdiv(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::FDIV_16); break; case OpCode::EQ_8: - trace_builder.op_eq(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::EQ_8); + error = trace_builder.op_eq(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::EQ_8); break; case OpCode::EQ_16: - trace_builder.op_eq(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::EQ_16); + error = trace_builder.op_eq(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::EQ_16); break; case OpCode::LT_8: - trace_builder.op_lt(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::LT_8); + error = trace_builder.op_lt(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::LT_8); break; case OpCode::LT_16: - trace_builder.op_lt(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::LT_16); + error = trace_builder.op_lt(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::LT_16); break; case OpCode::LTE_8: - trace_builder.op_lte(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::LTE_8); + error = trace_builder.op_lte(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::LTE_8); break; case OpCode::LTE_16: - trace_builder.op_lte(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::LTE_16); + error = trace_builder.op_lte(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::LTE_16); break; case OpCode::AND_8: - trace_builder.op_and(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::AND_8); + error = trace_builder.op_and(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::AND_8); break; case OpCode::AND_16: - trace_builder.op_and(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::AND_16); + error = trace_builder.op_and(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::AND_16); break; case OpCode::OR_8: - trace_builder.op_or(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::OR_8); + error = trace_builder.op_or(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::OR_8); break; case OpCode::OR_16: - trace_builder.op_or(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::OR_16); + error = trace_builder.op_or(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::OR_16); break; case OpCode::XOR_8: - trace_builder.op_xor(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::XOR_8); + error = trace_builder.op_xor(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::XOR_8); break; case OpCode::XOR_16: - trace_builder.op_xor(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::XOR_16); + error = trace_builder.op_xor(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::XOR_16); break; case OpCode::NOT_8: - trace_builder.op_not(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - OpCode::NOT_8); + error = trace_builder.op_not(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + OpCode::NOT_8); break; case OpCode::NOT_16: - trace_builder.op_not(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - OpCode::NOT_16); + error = trace_builder.op_not(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + OpCode::NOT_16); break; case OpCode::SHL_8: - trace_builder.op_shl(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::SHL_8); + error = trace_builder.op_shl(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::SHL_8); break; case OpCode::SHL_16: - trace_builder.op_shl(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::SHL_16); + error = trace_builder.op_shl(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::SHL_16); break; case OpCode::SHR_8: - trace_builder.op_shr(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::SHR_8); + error = trace_builder.op_shr(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::SHR_8); break; case OpCode::SHR_16: - trace_builder.op_shr(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - OpCode::SHR_16); + error = trace_builder.op_shr(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + OpCode::SHR_16); break; // Compute - Type Conversions case OpCode::CAST_8: - trace_builder.op_cast(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(1)), - OpCode::CAST_8); + error = trace_builder.op_cast(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1)), + OpCode::CAST_8); break; case OpCode::CAST_16: - trace_builder.op_cast(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(1)), - OpCode::CAST_16); + error = trace_builder.op_cast(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1)), + OpCode::CAST_16); break; // Execution Environment // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6284): support indirect for below case OpCode::GETENVVAR_16: - trace_builder.op_get_env_var(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2))); + error = trace_builder.op_get_env_var(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2))); break; // Execution Environment - Calldata case OpCode::CALLDATACOPY: - trace_builder.op_calldata_copy(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3))); + error = trace_builder.op_calldata_copy(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3))); break; case OpCode::RETURNDATASIZE: - trace_builder.op_returndata_size(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1))); + error = trace_builder.op_returndata_size(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1))); break; case OpCode::RETURNDATACOPY: - trace_builder.op_returndata_copy(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3))); + error = trace_builder.op_returndata_copy(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3))); break; // Machine State - Internal Control Flow case OpCode::JUMP_32: - trace_builder.op_jump(std::get(inst.operands.at(0))); + error = trace_builder.op_jump(std::get(inst.operands.at(0))); break; case OpCode::JUMPI_32: - trace_builder.op_jumpi(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2))); + error = trace_builder.op_jumpi(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2))); break; case OpCode::INTERNALCALL: - trace_builder.op_internal_call(std::get(inst.operands.at(0))); + error = trace_builder.op_internal_call(std::get(inst.operands.at(0))); break; case OpCode::INTERNALRETURN: - trace_builder.op_internal_return(); + error = trace_builder.op_internal_return(); break; // Machine State - Memory case OpCode::SET_8: { - trace_builder.op_set(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(1)), - OpCode::SET_8); + error = trace_builder.op_set(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1)), + OpCode::SET_8); break; } case OpCode::SET_16: { - trace_builder.op_set(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(1)), - OpCode::SET_16); + error = trace_builder.op_set(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1)), + OpCode::SET_16); break; } case OpCode::SET_32: { - trace_builder.op_set(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(1)), - OpCode::SET_32); + error = trace_builder.op_set(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1)), + OpCode::SET_32); break; } case OpCode::SET_64: { - trace_builder.op_set(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(1)), - OpCode::SET_64); + error = trace_builder.op_set(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1)), + OpCode::SET_64); break; } case OpCode::SET_128: { - trace_builder.op_set(std::get(inst.operands.at(0)), - uint256_t::from_uint128(std::get(inst.operands.at(2))), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(1)), - OpCode::SET_128); + error = trace_builder.op_set(std::get(inst.operands.at(0)), + uint256_t::from_uint128(std::get(inst.operands.at(2))), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1)), + OpCode::SET_128); break; } case OpCode::SET_FF: { - trace_builder.op_set(std::get(inst.operands.at(0)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(1)), - OpCode::SET_FF); + error = trace_builder.op_set(std::get(inst.operands.at(0)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(1)), + OpCode::SET_FF); break; } case OpCode::MOV_8: - trace_builder.op_mov(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - OpCode::MOV_8); + error = trace_builder.op_mov(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + OpCode::MOV_8); break; case OpCode::MOV_16: - trace_builder.op_mov(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - OpCode::MOV_16); + error = trace_builder.op_mov(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + OpCode::MOV_16); break; // World State case OpCode::SLOAD: - trace_builder.op_sload(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - 1, - std::get(inst.operands.at(2))); + error = trace_builder.op_sload(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + 1, + std::get(inst.operands.at(2))); break; case OpCode::SSTORE: - trace_builder.op_sstore(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - 1, - std::get(inst.operands.at(2))); + error = trace_builder.op_sstore(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + 1, + std::get(inst.operands.at(2))); break; case OpCode::NOTEHASHEXISTS: - trace_builder.op_note_hash_exists(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3))); + error = trace_builder.op_note_hash_exists(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3))); break; case OpCode::EMITNOTEHASH: - trace_builder.op_emit_note_hash(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1))); + error = trace_builder.op_emit_note_hash(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1))); break; case OpCode::NULLIFIEREXISTS: - trace_builder.op_nullifier_exists(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3))); + error = trace_builder.op_nullifier_exists(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3))); break; case OpCode::EMITNULLIFIER: - trace_builder.op_emit_nullifier(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1))); + error = trace_builder.op_emit_nullifier(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1))); break; case OpCode::L1TOL2MSGEXISTS: - trace_builder.op_l1_to_l2_msg_exists(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3))); + error = trace_builder.op_l1_to_l2_msg_exists(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3))); break; case OpCode::GETCONTRACTINSTANCE: - trace_builder.op_get_contract_instance(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4))); + error = trace_builder.op_get_contract_instance(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4))); break; // Accrued Substate case OpCode::EMITUNENCRYPTEDLOG: - trace_builder.op_emit_unencrypted_log(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2))); + error = trace_builder.op_emit_unencrypted_log(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2))); break; case OpCode::SENDL2TOL1MSG: - trace_builder.op_emit_l2_to_l1_msg(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2))); + error = trace_builder.op_emit_l2_to_l1_msg(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2))); break; // Control Flow - Contract Calls case OpCode::CALL: - trace_builder.op_call(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), - std::get(inst.operands.at(5))); + error = trace_builder.op_call(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(5))); break; case OpCode::STATICCALL: - trace_builder.op_static_call(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), - std::get(inst.operands.at(5))); + error = trace_builder.op_static_call(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(5))); break; case OpCode::RETURN: { auto ret = trace_builder.op_return(std::get(inst.operands.at(0)), std::get(inst.operands.at(1)), std::get(inst.operands.at(2))); - returndata.insert(returndata.end(), ret.begin(), ret.end()); + error = ret.error; + returndata.insert(returndata.end(), ret.return_data.begin(), ret.return_data.end()); break; } @@ -703,7 +704,8 @@ std::vector Execution::gen_trace(std::vector const& calldata, auto ret = trace_builder.op_revert(std::get(inst.operands.at(0)), std::get(inst.operands.at(1)), std::get(inst.operands.at(2))); - returndata.insert(returndata.end(), ret.begin(), ret.end()); + error = ret.error; + returndata.insert(returndata.end(), ret.return_data.begin(), ret.return_data.end()); break; } @@ -712,66 +714,69 @@ std::vector Execution::gen_trace(std::vector const& calldata, auto ret = trace_builder.op_revert(std::get(inst.operands.at(0)), std::get(inst.operands.at(1)), std::get(inst.operands.at(2))); - returndata.insert(returndata.end(), ret.begin(), ret.end()); + error = ret.error; + returndata.insert(returndata.end(), ret.return_data.begin(), ret.return_data.end()); break; } // Misc case OpCode::DEBUGLOG: - // We want a noop, but we need to execute something that both advances the PC, - // and adds a valid row to the trace. - trace_builder.op_jump(pc + Deserialization::get_pc_increment(OpCode::DEBUGLOG)); + error = trace_builder.op_debug_log(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4))); break; // Gadgets case OpCode::POSEIDON2PERM: - trace_builder.op_poseidon2_permutation(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2))); + error = trace_builder.op_poseidon2_permutation(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2))); break; case OpCode::SHA256COMPRESSION: - trace_builder.op_sha256_compression(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3))); + error = trace_builder.op_sha256_compression(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3))); break; case OpCode::KECCAKF1600: - trace_builder.op_keccakf1600(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2))); + error = trace_builder.op_keccakf1600(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2))); break; case OpCode::ECADD: - trace_builder.op_ec_add(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), - std::get(inst.operands.at(5)), - std::get(inst.operands.at(6)), - std::get(inst.operands.at(7))); + error = trace_builder.op_ec_add(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(5)), + std::get(inst.operands.at(6)), + std::get(inst.operands.at(7))); break; case OpCode::MSM: - trace_builder.op_variable_msm(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4))); + error = trace_builder.op_variable_msm(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4))); break; // Conversions case OpCode::TORADIXBE: - trace_builder.op_to_radix_be(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - std::get(inst.operands.at(4)), - std::get(inst.operands.at(5))); + error = trace_builder.op_to_radix_be(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3)), + std::get(inst.operands.at(4)), + std::get(inst.operands.at(5))); break; default: @@ -781,6 +786,15 @@ std::vector Execution::gen_trace(std::vector const& calldata, } } + if (error != AvmError::NO_ERROR) { + info("AVM stopped due to exceptional halting condition. Error: ", + to_name(error), + " at PC: ", + pc, + " IC: ", + counter - 1); // Need adjustement as counter increment occurs in loop body + } + auto trace = trace_builder.finalize(); show_trace_info(trace); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution_hints.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution_hints.hpp index 4e9fe566bb8..c2905791119 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution_hints.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution_hints.hpp @@ -8,13 +8,111 @@ namespace bb::avm_trace { using FF = AvmFlavorSettings::FF; using AffinePoint = grumpkin::g1::affine_element; +struct PublicDataTreeLeafPreimage { + FF slot; + FF value; + FF next_index; + FF next_slot; +}; + +inline void read(uint8_t const*& it, PublicDataTreeLeafPreimage& hint) +{ + using serialize::read; + read(it, hint.slot); + read(it, hint.value); + read(it, hint.next_index); + read(it, hint.next_slot); +} + +struct PublicDataReadTreeHint { + PublicDataTreeLeafPreimage leaf_preimage; + FF leaf_index; + std::vector sibling_path; +}; + +inline void read(uint8_t const*& it, PublicDataReadTreeHint& hint) +{ + using serialize::read; + read(it, hint.leaf_preimage); + read(it, hint.leaf_index); + read(it, hint.sibling_path); +} + +struct PublicDataWriteTreeHint { + PublicDataReadTreeHint low_leaf_membership; + PublicDataTreeLeafPreimage new_leaf_preimage; + std::vector insertion_path; +}; + +inline void read(uint8_t const*& it, PublicDataWriteTreeHint& hint) +{ + using serialize::read; + read(it, hint.low_leaf_membership); + read(it, hint.new_leaf_preimage); + read(it, hint.insertion_path); +} + +struct NullifierLeafPreimage { + FF nullifier; + FF next_nullifier; + FF next_index; +}; + +inline void read(uint8_t const*& it, NullifierLeafPreimage& hint) +{ + using serialize::read; + read(it, hint.nullifier); + read(it, hint.next_nullifier); + read(it, hint.next_index); +} + +struct NullifierReadTreeHint { + NullifierLeafPreimage low_leaf_preimage; + FF low_leaf_index; + std::vector low_leaf_sibling_path; +}; + +inline void read(uint8_t const*& it, NullifierReadTreeHint& hint) +{ + using serialize::read; + read(it, hint.low_leaf_preimage); + read(it, hint.low_leaf_index); + read(it, hint.low_leaf_sibling_path); +} + +struct NullifierWriteTreeHint { + NullifierReadTreeHint low_leaf_membership; + std::vector insertion_path; +}; + +inline void read(uint8_t const*& it, NullifierWriteTreeHint& hint) +{ + using serialize::read; + read(it, hint.low_leaf_membership); + read(it, hint.insertion_path); +} + +struct AppendTreeHint { + FF leaf_index; + FF leaf_value; + std::vector sibling_path; +}; + +inline void read(uint8_t const*& it, AppendTreeHint& hint) +{ + using serialize::read; + read(it, hint.leaf_index); + read(it, hint.leaf_value); + read(it, hint.sibling_path); +} + struct ExternalCallHint { - FF success; + FF success{}; std::vector return_data; uint32_t l2_gas_used; uint32_t da_gas_used; - FF end_side_effect_counter; - FF contract_address; + FF end_side_effect_counter{}; + FF contract_address{}; }; // Add support for deserialization of ExternalCallHint. This is implicitly used by serialize::read @@ -31,9 +129,9 @@ inline void read(uint8_t const*& it, ExternalCallHint& hint) } struct ContractClassIdHint { - FF artifact_hash; - FF private_fn_root; - FF public_bytecode_commitment; + FF artifact_hash{}; + FF private_fn_root{}; + FF public_bytecode_commitment{}; }; inline void read(uint8_t const*& it, ContractClassIdHint& preimage) @@ -61,12 +159,12 @@ struct PublicKeysHint { }; struct ContractInstanceHint { - FF address; + FF address{}; bool exists; // Useful for membership checks - FF salt; - FF deployer_addr; - FF contract_class_id; - FF initialisation_hash; + FF salt{}; + FF deployer_addr{}; + FF contract_class_id{}; + FF initialisation_hash{}; PublicKeysHint public_keys; }; @@ -128,6 +226,13 @@ struct ExecutionHints { std::map contract_instance_hints; // We could make this address-indexed std::vector all_contract_bytecode; + std::vector storage_read_hints; + std::vector storage_write_hints; + std::vector nullifier_read_hints; + std::vector nullifier_write_hints; + std::vector note_hash_read_hints; + std::vector note_hash_write_hints; + std::vector l1_to_l2_message_read_hints; ExecutionHints() = default; @@ -222,6 +327,27 @@ struct ExecutionHints { std::vector all_contract_bytecode; read(it, all_contract_bytecode); + std::vector storage_read_hints; + read(it, storage_read_hints); + + std::vector storage_write_hints; + read(it, storage_write_hints); + + std::vector nullifier_read_hints; + read(it, nullifier_read_hints); + + std::vector nullifier_write_hints; + read(it, nullifier_write_hints); + + std::vector note_hash_read_hints; + read(it, note_hash_read_hints); + + std::vector note_hash_write_hints; + read(it, note_hash_write_hints); + + std::vector l1_to_l2_message_read_hints; + read(it, l1_to_l2_message_read_hints); + if (it != data.data() + data.size()) { throw_or_abort("Failed to deserialize ExecutionHints: only read " + std::to_string(it - data.data()) + " bytes out of " + std::to_string(data.size()) + " bytes"); @@ -230,7 +356,12 @@ struct ExecutionHints { return { std::move(storage_value_hints), std::move(note_hash_exists_hints), std::move(nullifier_exists_hints), std::move(l1_to_l2_message_exists_hints), std::move(externalcall_hints), std::move(contract_instance_hints), - std::move(all_contract_bytecode) }; + std::move(all_contract_bytecode), std::move(storage_read_hints), + std::move(storage_write_hints), std::move(nullifier_read_hints), + std::move(nullifier_write_hints), std::move(note_hash_read_hints), + std::move(note_hash_write_hints), std::move(l1_to_l2_message_read_hints) + + }; } private: @@ -240,7 +371,15 @@ struct ExecutionHints { std::vector> l1_to_l2_message_exists_hints, std::vector externalcall_hints, std::map contract_instance_hints, - std::vector all_contract_bytecode) + std::vector all_contract_bytecode, + std::vector storage_read_hints, + std::vector storage_write_hints, + std::vector nullifier_read_hints, + std::vector nullifier_write_hints, + std::vector note_hash_read_hints, + std::vector note_hash_write_hints, + std::vector l1_to_l2_message_read_hints) + : storage_value_hints(std::move(storage_value_hints)) , note_hash_exists_hints(std::move(note_hash_exists_hints)) , nullifier_exists_hints(std::move(nullifier_exists_hints)) @@ -248,6 +387,13 @@ struct ExecutionHints { , externalcall_hints(std::move(externalcall_hints)) , contract_instance_hints(std::move(contract_instance_hints)) , all_contract_bytecode(std::move(all_contract_bytecode)) + , storage_read_hints(std::move(storage_read_hints)) + , storage_write_hints(std::move(storage_write_hints)) + , nullifier_read_hints(std::move(nullifier_read_hints)) + , nullifier_write_hints(std::move(nullifier_write_hints)) + , note_hash_read_hints(std::move(note_hash_read_hints)) + , note_hash_write_hints(std::move(note_hash_write_hints)) + , l1_to_l2_message_read_hints(std::move(l1_to_l2_message_read_hints)) {} }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp index bb9eda6172e..79e6e4a69c8 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp @@ -83,7 +83,7 @@ const std::unordered_map GAS_COST_TABLE = { { OpCode::RETURN, make_cost(AVM_RETURN_BASE_L2_GAS, 0, AVM_RETURN_DYN_L2_GAS, 0) }, { OpCode::REVERT_8, make_cost(AVM_REVERT_BASE_L2_GAS, 0, AVM_REVERT_DYN_L2_GAS, 0) }, { OpCode::REVERT_16, make_cost(AVM_REVERT_BASE_L2_GAS, 0, AVM_REVERT_DYN_L2_GAS, 0) }, - { OpCode::DEBUGLOG, make_cost(AVM_DEBUGLOG_BASE_L2_GAS, 0, 0, 0) }, + { OpCode::DEBUGLOG, make_cost(AVM_DEBUGLOG_BASE_L2_GAS, 0, AVM_DEBUGLOG_DYN_L2_GAS, 0) }, { OpCode::POSEIDON2PERM, make_cost(AVM_POSEIDON2_BASE_L2_GAS, 0, 0, 0) }, { OpCode::SHA256COMPRESSION, make_cost(AVM_SHA256COMPRESSION_BASE_L2_GAS, 0, 0, 0) }, { OpCode::KECCAKF1600, make_cost(AVM_KECCAKF1600_BASE_L2_GAS, 0, 0, 0) }, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/cmp.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/cmp.cpp index 742a2efdb91..a2e289b8f76 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/cmp.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/cmp.cpp @@ -70,6 +70,14 @@ bool AvmCmpBuilder::constrained_gt(FF a, FF b, uint64_t clk, EventEmitter e) return uint256_t(a) > uint256_t(b); } +bool AvmCmpBuilder::constrained_non_ff_gt(uint128_t a, uint128_t b, uint64_t clk, EventEmitter e) +{ + auto a_ff = FF(uint256_t::from_uint128(a)); + auto b_ff = FF(uint256_t::from_uint128(b)); + cmp_events.push_back({ clk, a_ff, b_ff, e, CmpOp::GT_NON_FF }); + return a > b; +} + /************************************************************************************************** * FINALIZE **************************************************************************************************/ @@ -91,6 +99,13 @@ std::vector AvmCmpBuilder::finalize() entry.result = diff == FF::zero() ? FF::one() : FF::zero(); entry.op_eq_diff_inv = diff == FF::zero() ? FF::zero() : diff.invert(); entry.is_eq = true; + } else if (CmpOp::GT_NON_FF == event.op) { + entry.result = input_a_u256 > input_b_u256; + FF diff = + (input_a_u256 > input_b_u256) ? input_a_u256 - input_b_u256 - FF::one() : input_b_u256 - input_a_u256; + entry.is_gt_non_ff = true; + auto range_chk_clk = (entry.clk * (static_cast(1) << 8)); + range_check_builder.assert_range(static_cast(diff), 128, EventEmitter::NON_FF_GT, range_chk_clk); } else { entry.result = input_a_u256 > input_b_u256; auto range_chk_clk = (entry.clk * (uint64_t(1) << 8)) + 4; // 4 is the range check counter @@ -144,6 +159,7 @@ std::vector AvmCmpBuilder::into_canonical(std::vector(entry.is_gt)); row.op_eq = FF(static_cast(entry.is_eq)); + row.op_non_ff_gt = FF(static_cast(entry.is_gt_non_ff)); row.a_lo = std::get<0>(entry.a_limbs); row.a_hi = std::get<1>(entry.a_limbs); @@ -200,6 +216,11 @@ std::vector AvmCmpBuilder::into_canonical(std::vector(1) << 8); + row.diff = uint256_t(row.input_a) > uint256_t(row.input_b) ? row.input_a - row.input_b - FF::one() + : row.input_b - row.input_a; + dest_rows.push_back(row); } else { // EQ operations just have the single row dest_rows.push_back(row); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/cmp.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/cmp.hpp index 4afd7517417..557a3445738 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/cmp.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/cmp.hpp @@ -6,7 +6,7 @@ #include "barretenberg/vm/avm/trace/gadgets/range_check.hpp" #include -enum class CmpOp { EQ, GT }; +enum class CmpOp { EQ, GT, GT_NON_FF }; namespace bb::avm_trace { class AvmCmpBuilder { @@ -26,6 +26,7 @@ class AvmCmpBuilder { FF result; FF op_eq_diff_inv; bool is_gt; + bool is_gt_non_ff; bool is_eq; std::tuple a_limbs; std::tuple b_limbs; @@ -42,6 +43,9 @@ class AvmCmpBuilder { FF op_eq_diff_inv; FF op_gt; FF op_eq; + FF op_non_ff_gt; + FF non_ff_gt_diff_inv; + FF diff; FF a_lo; FF a_hi; FF b_lo; @@ -69,6 +73,8 @@ class AvmCmpBuilder { bool constrained_eq(FF a, FF b, uint64_t clk, EventEmitter e); // Constrains a > b bool constrained_gt(FF a, FF b, uint64_t clk, EventEmitter e); + // Constrains a > b when a and b are at most 128 bits + bool constrained_non_ff_gt(uint128_t a, uint128_t b, uint64_t clk, EventEmitter e); uint32_t get_cmp_trace_size() const; @@ -83,8 +89,11 @@ class AvmCmpBuilder { row.cmp_result = entry.result; row.cmp_op_eq_diff_inv = entry.op_eq_diff_inv; row.cmp_op_gt = entry.op_gt; + row.cmp_op_non_ff_gt = entry.op_non_ff_gt; row.cmp_op_eq = entry.op_eq; + row.cmp_diff = entry.diff; + row.cmp_a_lo = entry.a_lo; row.cmp_a_hi = entry.a_hi; row.cmp_b_lo = entry.b_lo; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/range_check.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/range_check.cpp index 5dea409ea77..f7d55fde340 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/range_check.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/range_check.cpp @@ -102,6 +102,9 @@ std::vector AvmRangeCheckBuilder::finaliz case EventEmitter::CMP_HI: entry.is_cmp_hi = true; break; + case EventEmitter::NON_FF_GT: + entry.is_cmp_non_ff = true; + break; } entries.push_back(entry); } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/range_check.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/range_check.hpp index eb9c85a3236..177099f2b61 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/range_check.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/range_check.hpp @@ -5,7 +5,7 @@ #include "barretenberg/vm/avm/trace/common.hpp" #include -enum class EventEmitter { ALU, MEMORY, GAS_L2, GAS_DA, CMP_LO, CMP_HI }; +enum class EventEmitter { ALU, MEMORY, GAS_L2, GAS_DA, CMP_LO, CMP_HI, NON_FF_GT }; namespace bb::avm_trace { class AvmRangeCheckBuilder { @@ -38,6 +38,7 @@ class AvmRangeCheckBuilder { bool is_gas_da_sel; bool is_cmp_lo; bool is_cmp_hi; + bool is_cmp_non_ff; // Need this for sorting bool operator<(RangeCheckEntry const& other) const { return clk < other.clk; } @@ -96,6 +97,7 @@ class AvmRangeCheckBuilder { row.range_check_gas_da_rng_chk = entry.is_gas_da_sel; row.range_check_cmp_lo_bits_rng_chk = entry.is_cmp_lo; row.range_check_cmp_hi_bits_rng_chk = entry.is_cmp_hi; + row.range_check_cmp_non_ff_rng_chk = entry.is_cmp_non_ff; } private: diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gas_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gas_trace.cpp index 0575537d0e4..27fe2bca7a6 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gas_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gas_trace.cpp @@ -138,7 +138,17 @@ void AvmGasTraceBuilder::finalize(std::vector>& main_trace) uint32_t abs_da_gas_remaining = da_out_of_gas ? -gas_entry.remaining_da_gas : gas_entry.remaining_da_gas; dest.main_abs_l2_rem_gas = abs_l2_gas_remaining; + dest.main_l2_gas_u16_r0 = static_cast(abs_l2_gas_remaining); + rem_gas_rng_check_counts.at(0)[static_cast(abs_l2_gas_remaining)]++; + + dest.main_l2_gas_u16_r1 = static_cast(abs_l2_gas_remaining >> 16); + rem_gas_rng_check_counts.at(1)[static_cast(abs_l2_gas_remaining >> 16)]++; + dest.main_abs_da_rem_gas = abs_da_gas_remaining; + dest.main_da_gas_u16_r0 = static_cast(abs_da_gas_remaining); + rem_gas_rng_check_counts.at(2)[static_cast(abs_da_gas_remaining)]++; + dest.main_da_gas_u16_r1 = static_cast(abs_da_gas_remaining >> 16); + rem_gas_rng_check_counts.at(3)[static_cast(abs_da_gas_remaining >> 16)]++; dest.main_l2_out_of_gas = static_cast(l2_out_of_gas); dest.main_da_out_of_gas = static_cast(da_out_of_gas); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp index 6c44d1b01e1..1960cac37b3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp @@ -71,27 +71,27 @@ bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx) return (ind_value & (1 << operand_idx)) != 0; } -std::string to_hex(bb::avm_trace::AvmMemoryTag tag) +std::string to_hex(AvmMemoryTag tag) { return to_hex(static_cast(tag)); } -std::string to_name(bb::avm_trace::AvmMemoryTag tag) +std::string to_name(AvmMemoryTag tag) { switch (tag) { - case bb::avm_trace::AvmMemoryTag::FF: + case AvmMemoryTag::FF: return "Field"; - case bb::avm_trace::AvmMemoryTag::U1: + case AvmMemoryTag::U1: return "Uint1"; - case bb::avm_trace::AvmMemoryTag::U8: + case AvmMemoryTag::U8: return "Uint8"; - case bb::avm_trace::AvmMemoryTag::U16: + case AvmMemoryTag::U16: return "Uint16"; - case bb::avm_trace::AvmMemoryTag::U32: + case AvmMemoryTag::U32: return "Uint32"; - case bb::avm_trace::AvmMemoryTag::U64: + case AvmMemoryTag::U64: return "Uint64"; - case bb::avm_trace::AvmMemoryTag::U128: + case AvmMemoryTag::U128: return "Uint128"; default: throw std::runtime_error("Invalid memory tag"); @@ -99,6 +99,29 @@ std::string to_name(bb::avm_trace::AvmMemoryTag tag) } } +std::string to_name(AvmError error) +{ + switch (error) { + case AvmError::NO_ERROR: + return "NO ERROR"; + case AvmError::TAG_ERROR: + return "TAG ERROR"; + case AvmError::ADDR_RES_ERROR: + return "ADDRESS RESOLUTION ERROR"; + case AvmError::DIV_ZERO: + return "DIVISION BY ZERO"; + case AvmError::PARSING_ERROR: + return "PARSING ERROR"; + case AvmError::ENV_VAR_UNKNOWN: + return "ENVIRONMENT VARIABLE UNKNOWN"; + case AvmError::CONTRACT_INST_MEM_UNKNOWN: + return "CONTRACT INSTANCE MEMBER UNKNOWN"; + default: + throw std::runtime_error("Invalid error type"); + break; + } +} + /** * * ONLY FOR TESTS - Required by dsl module and therefore cannot be moved to test/helpers.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp index bd45a1b472c..cc1976dc501 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.hpp @@ -232,6 +232,8 @@ std::string to_hex(bb::avm_trace::AvmMemoryTag tag); std::string to_name(bb::avm_trace::AvmMemoryTag tag); +std::string to_name(AvmError error); + // Mutate the inputs void inject_end_gas_values(VmPublicInputs& public_inputs, std::vector& trace); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp index 14ba70fa24a..58bd15bd44f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp @@ -47,7 +47,8 @@ namespace { uint32_t finalize_rng_chks_for_testing(std::vector& main_trace, AvmAluTraceBuilder const& alu_trace_builder, AvmMemTraceBuilder const& mem_trace_builder, - AvmRangeCheckBuilder const& rng_chk_trace_builder) + AvmRangeCheckBuilder const& rng_chk_trace_builder, + AvmGasTraceBuilder const& gas_trace_builder) { // Build the main_trace, and add any new rows with specific clks that line up with lookup reads @@ -67,6 +68,10 @@ uint32_t finalize_rng_chks_for_testing(std::vector& main_trace, rng_chk_trace_builder.u16_range_chk_counters.begin(), rng_chk_trace_builder.u16_range_chk_counters.end()); + u16_rng_chks.insert(u16_rng_chks.end(), + gas_trace_builder.rem_gas_rng_check_counts.begin(), + gas_trace_builder.rem_gas_rng_check_counts.end()); + auto custom_clk = std::set{}; for (auto const& row : u8_rng_chks) { for (auto const& [key, value] : row) { @@ -104,6 +109,21 @@ template std::array vec_to_arr(std::vector return arr; } +bool check_tag_integral(AvmMemoryTag tag) +{ + switch (tag) { + case AvmMemoryTag::U1: + case AvmMemoryTag::U8: + case AvmMemoryTag::U16: + case AvmMemoryTag::U32: + case AvmMemoryTag::U64: + case AvmMemoryTag::U128: + return true; + default: + return false; + } +} + } // anonymous namespace /************************************************************************************************** @@ -201,6 +221,21 @@ AvmMemoryTag AvmTraceBuilder::unconstrained_get_memory_tag(AddressWithMode addr) return mem_trace_builder.unconstrained_get_memory_tag(call_ptr, offset); } +bool AvmTraceBuilder::check_tag(AvmMemoryTag tag, AddressWithMode addr) +{ + return unconstrained_get_memory_tag(addr) == tag; +} + +bool AvmTraceBuilder::check_tag_range(AvmMemoryTag tag, AddressWithMode start_offset, uint32_t size) +{ + for (uint32_t i = 0; i < size; i++) { + if (!check_tag(tag, start_offset + i)) { + return false; + } + } + return true; +} + FF AvmTraceBuilder::unconstrained_read_from_memory(AddressWithMode addr) { auto offset = addr.offset; @@ -291,7 +326,7 @@ AvmTraceBuilder::AvmTraceBuilder(VmPublicInputs public_inputs, * @param dst_offset An index in memory pointing to the output of the addition. * @param in_tag The instruction memory tag of the operands. */ -void AvmTraceBuilder::op_add( +AvmError AvmTraceBuilder::op_add( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) { auto clk = static_cast(main_trace.size()) + 1; @@ -353,6 +388,7 @@ void AvmTraceBuilder::op_add( ASSERT(op_code == OpCode::ADD_8 || op_code == OpCode::ADD_16); pc += Deserialization::get_pc_increment(op_code); + return tag_match ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /** @@ -364,7 +400,7 @@ void AvmTraceBuilder::op_add( * @param dst_offset An index in memory pointing to the output of the subtraction. * @param in_tag The instruction memory tag of the operands. */ -void AvmTraceBuilder::op_sub( +AvmError AvmTraceBuilder::op_sub( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) { auto clk = static_cast(main_trace.size()) + 1; @@ -426,6 +462,7 @@ void AvmTraceBuilder::op_sub( ASSERT(op_code == OpCode::SUB_8 || op_code == OpCode::SUB_16); pc += Deserialization::get_pc_increment(op_code); + return tag_match ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /** @@ -437,7 +474,7 @@ void AvmTraceBuilder::op_sub( * @param dst_offset An index in memory pointing to the output of the multiplication. * @param in_tag The instruction memory tag of the operands. */ -void AvmTraceBuilder::op_mul( +AvmError AvmTraceBuilder::op_mul( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) { auto clk = static_cast(main_trace.size()) + 1; @@ -499,6 +536,7 @@ void AvmTraceBuilder::op_mul( ASSERT(op_code == OpCode::MUL_8 || op_code == OpCode::MUL_16); pc += Deserialization::get_pc_increment(op_code); + return tag_match ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /** @@ -510,7 +548,7 @@ void AvmTraceBuilder::op_mul( * @param dst_offset An index in memory pointing to the output of the division. * @param in_tag The instruction memory tag of the operands. */ -void AvmTraceBuilder::op_div( +AvmError AvmTraceBuilder::op_div( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) { auto clk = static_cast(main_trace.size()) + 1; @@ -534,17 +572,16 @@ void AvmTraceBuilder::op_div( // output (c) in memory. FF c; FF inv; - FF error; + bool div_error = false; if (!b.is_zero()) { // If b is not zero, we prove it is not by providing its inverse as well inv = b.invert(); c = tag_match ? alu_trace_builder.op_div(a, b, in_tag, clk) : FF(0); - error = 0; } else { inv = 1; c = 0; - error = 1; + div_error = true; } // Write into memory value c from intermediate register ic. @@ -568,7 +605,7 @@ void AvmTraceBuilder::op_div( .main_mem_addr_a = FF(read_a.direct_address), .main_mem_addr_b = FF(read_b.direct_address), .main_mem_addr_c = FF(write_dst.direct_address), - .main_op_err = tag_match ? error : FF(1), + .main_op_err = tag_match ? FF(static_cast(div_error)) : FF(1), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -585,6 +622,7 @@ void AvmTraceBuilder::op_div( ASSERT(op_code == OpCode::DIV_8 || op_code == OpCode::DIV_16); pc += Deserialization::get_pc_increment(op_code); + return !tag_match ? AvmError::TAG_ERROR : div_error ? AvmError::DIV_ZERO : AvmError::NO_ERROR; } /** @@ -596,7 +634,7 @@ void AvmTraceBuilder::op_div( * @param dst_offset An index in memory pointing to the output of the division. * @param in_tag The instruction memory tag of the operands. */ -void AvmTraceBuilder::op_fdiv( +AvmError AvmTraceBuilder::op_fdiv( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) { auto clk = static_cast(main_trace.size()) + 1; @@ -618,16 +656,15 @@ void AvmTraceBuilder::op_fdiv( FF b = read_b.val; FF c; FF inv; - FF error; + bool div_error = false; if (!b.is_zero()) { inv = b.invert(); c = a * inv; - error = 0; } else { inv = 1; c = 0; - error = 1; + div_error = true; } // Write into memory value c from intermediate register ic. @@ -651,7 +688,7 @@ void AvmTraceBuilder::op_fdiv( .main_mem_addr_a = FF(read_a.direct_address), .main_mem_addr_b = FF(read_b.direct_address), .main_mem_addr_c = FF(write_c.direct_address), - .main_op_err = tag_match ? error : FF(1), + .main_op_err = tag_match ? FF(static_cast(div_error)) : FF(1), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), .main_rwc = FF(1), @@ -668,6 +705,7 @@ void AvmTraceBuilder::op_fdiv( ASSERT(op_code == OpCode::FDIV_8 || op_code == OpCode::FDIV_16); pc += Deserialization::get_pc_increment(op_code); + return !tag_match ? AvmError::TAG_ERROR : div_error ? AvmError::DIV_ZERO : AvmError::NO_ERROR; } /************************************************************************************************** @@ -683,7 +721,8 @@ void AvmTraceBuilder::op_fdiv( * @param dst_offset An index in memory pointing to the output of the equality. * @param in_tag The instruction memory tag of the operands. */ -void AvmTraceBuilder::op_eq(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) +AvmError AvmTraceBuilder::op_eq( + uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) { auto clk = static_cast(main_trace.size()) + 1; @@ -742,9 +781,11 @@ void AvmTraceBuilder::op_eq(uint8_t indirect, uint32_t a_offset, uint32_t b_offs ASSERT(op_code == OpCode::EQ_8 || op_code == OpCode::EQ_16); pc += Deserialization::get_pc_increment(op_code); + return tag_match ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_lt(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) +AvmError AvmTraceBuilder::op_lt( + uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) { auto clk = static_cast(main_trace.size()) + 1; @@ -799,9 +840,10 @@ void AvmTraceBuilder::op_lt(uint8_t indirect, uint32_t a_offset, uint32_t b_offs ASSERT(op_code == OpCode::LT_8 || op_code == OpCode::LT_16); pc += Deserialization::get_pc_increment(op_code); + return tag_match ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_lte( +AvmError AvmTraceBuilder::op_lte( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) { auto clk = static_cast(main_trace.size()) + 1; @@ -858,13 +900,14 @@ void AvmTraceBuilder::op_lte( ASSERT(op_code == OpCode::LTE_8 || op_code == OpCode::LTE_16); pc += Deserialization::get_pc_increment(op_code); + return tag_match ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /************************************************************************************************** * COMPUTE - BITWISE **************************************************************************************************/ -void AvmTraceBuilder::op_and( +AvmError AvmTraceBuilder::op_and( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) { auto clk = static_cast(main_trace.size()) + 1; @@ -877,12 +920,15 @@ void AvmTraceBuilder::op_and( // Reading from memory and loading into ia resp. ib. auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, in_tag, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; + // No need to add check_tag_integral(read_b.tag) as this follows from tag matching and that a has integral tag. + bool op_valid = tag_match && check_tag_integral(read_a.tag); FF a = tag_match ? read_a.val : FF(0); FF b = tag_match ? read_b.val : FF(0); - FF c = tag_match ? bin_trace_builder.op_and(a, b, in_tag, clk) : FF(0); + FF c = op_valid ? bin_trace_builder.op_and(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); @@ -904,10 +950,11 @@ void AvmTraceBuilder::op_and( .main_mem_addr_a = FF(read_a.direct_address), .main_mem_addr_b = FF(read_b.direct_address), .main_mem_addr_c = FF(write_c.direct_address), + .main_op_err = FF(static_cast(!op_valid)), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), - .main_sel_bin = FF(1), + .main_sel_bin = FF(static_cast(op_valid)), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), @@ -921,9 +968,11 @@ void AvmTraceBuilder::op_and( ASSERT(op_code == OpCode::AND_8 || op_code == OpCode::AND_16); pc += Deserialization::get_pc_increment(op_code); + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_or(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) +AvmError AvmTraceBuilder::op_or( + uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) { auto clk = static_cast(main_trace.size()) + 1; auto [resolved_a, resolved_b, resolved_c] = @@ -934,12 +983,15 @@ void AvmTraceBuilder::op_or(uint8_t indirect, uint32_t a_offset, uint32_t b_offs // Reading from memory and loading into ia resp. ib. auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, in_tag, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; + // No need to add check_tag_integral(read_b.tag) as this follows from tag matching and that a has integral tag. + bool op_valid = tag_match && check_tag_integral(read_a.tag); FF a = tag_match ? read_a.val : FF(0); FF b = tag_match ? read_b.val : FF(0); - FF c = tag_match ? bin_trace_builder.op_or(a, b, in_tag, clk) : FF(0); + FF c = op_valid ? bin_trace_builder.op_or(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); @@ -961,10 +1013,11 @@ void AvmTraceBuilder::op_or(uint8_t indirect, uint32_t a_offset, uint32_t b_offs .main_mem_addr_a = FF(read_a.direct_address), .main_mem_addr_b = FF(read_b.direct_address), .main_mem_addr_c = FF(write_c.direct_address), + .main_op_err = FF(static_cast(!op_valid)), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), - .main_sel_bin = FF(1), + .main_sel_bin = FF(static_cast(op_valid)), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), @@ -978,9 +1031,10 @@ void AvmTraceBuilder::op_or(uint8_t indirect, uint32_t a_offset, uint32_t b_offs ASSERT(op_code == OpCode::OR_8 || op_code == OpCode::OR_16); pc += Deserialization::get_pc_increment(op_code); + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_xor( +AvmError AvmTraceBuilder::op_xor( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) { auto clk = static_cast(main_trace.size()) + 1; @@ -993,12 +1047,15 @@ void AvmTraceBuilder::op_xor( // Reading from memory and loading into ia resp. ib. auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, in_tag, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; + // No need to add check_tag_integral(read_b.tag) as this follows from tag matching and that a has integral tag. + bool op_valid = tag_match && check_tag_integral(read_a.tag); FF a = tag_match ? read_a.val : FF(0); FF b = tag_match ? read_b.val : FF(0); - FF c = tag_match ? bin_trace_builder.op_xor(a, b, in_tag, clk) : FF(0); + FF c = op_valid ? bin_trace_builder.op_xor(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); @@ -1020,10 +1077,11 @@ void AvmTraceBuilder::op_xor( .main_mem_addr_a = FF(read_a.direct_address), .main_mem_addr_b = FF(read_b.direct_address), .main_mem_addr_c = FF(write_c.direct_address), + .main_op_err = FF(static_cast(!op_valid)), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), - .main_sel_bin = FF(1), + .main_sel_bin = FF(static_cast(op_valid)), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), @@ -1037,6 +1095,7 @@ void AvmTraceBuilder::op_xor( ASSERT(op_code == OpCode::XOR_8 || op_code == OpCode::XOR_16); pc += Deserialization::get_pc_increment(op_code); + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /** @@ -1046,7 +1105,7 @@ void AvmTraceBuilder::op_xor( * @param a_offset An index in memory pointing to the only operand of Not. * @param dst_offset An index in memory pointing to the output of Not. */ -void AvmTraceBuilder::op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, OpCode op_code) +AvmError AvmTraceBuilder::op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, OpCode op_code) { auto clk = static_cast(main_trace.size()) + 1; @@ -1059,14 +1118,14 @@ void AvmTraceBuilder::op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_o // Reading from memory and loading into ia auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); - bool tag_match = read_a.tag_match; + bool op_valid = check_tag_integral(read_a.tag); // ~a = c FF a = read_a.val; - // In case of a memory tag error, we do not perform the computation. + // In case of an error (tag of type FF), we do not perform the computation. // Therefore, we do not create any entry in ALU table and store the value 0 as // output (c) in memory. - FF c = tag_match ? alu_trace_builder.op_not(a, in_tag, clk) : FF(0); + FF c = op_valid ? alu_trace_builder.op_not(a, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); @@ -1085,6 +1144,7 @@ void AvmTraceBuilder::op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_o .main_internal_return_ptr = FF(internal_return_ptr), .main_mem_addr_a = FF(read_a.direct_address), .main_mem_addr_c = FF(write_c.direct_address), + .main_op_err = FF(static_cast(!op_valid)), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -1093,15 +1153,15 @@ void AvmTraceBuilder::op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_o .main_sel_op_not = FF(1), .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), - .main_tag_err = FF(static_cast(!read_a.tag_match)), .main_w_in_tag = FF(static_cast(in_tag)), }); ASSERT(op_code == OpCode::NOT_8 || op_code == OpCode::NOT_16); pc += Deserialization::get_pc_increment(op_code); + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_shl( +AvmError AvmTraceBuilder::op_shl( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) { auto clk = static_cast(main_trace.size()) + 1; @@ -1112,18 +1172,17 @@ void AvmTraceBuilder::op_shl( // We get our representative memory tag from the resolved_a memory address. AvmMemoryTag in_tag = unconstrained_get_memory_tag(resolved_a); // Reading from memory and loading into ia resp. ib. - // TODO(9497): if simulator fails tag check here, witgen will not. Raise error flag if in_tag is FF! auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); // TODO(8603): once instructions can have multiple different tags for reads, constrain b's read & tag // auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, AvmMemoryTag::U8, AvmMemoryTag::U8, // IntermRegister::IB); bool tag_match = read_a.tag_match && read_b.tag_match; - auto read_b = unconstrained_read_from_memory(resolved_b); // should be tagged as U8 - bool tag_match = read_a.tag_match; + auto read_b = unconstrained_read_from_memory(resolved_b); + bool op_valid = check_tag_integral(read_a.tag) && check_tag(AvmMemoryTag::U8, resolved_b); - FF a = tag_match ? read_a.val : FF(0); - FF b = tag_match ? read_b : FF(0); + FF a = op_valid ? read_a.val : FF(0); + FF b = op_valid ? read_b : FF(0); - FF c = tag_match ? alu_trace_builder.op_shl(a, b, in_tag, clk) : FF(0); + FF c = op_valid ? alu_trace_builder.op_shl(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); @@ -1144,6 +1203,7 @@ void AvmTraceBuilder::op_shl( .main_mem_addr_a = FF(read_a.direct_address), //.main_mem_addr_b = FF(read_b.direct_address), .main_mem_addr_c = FF(write_c.direct_address), + .main_op_err = FF(static_cast(!op_valid)), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -1154,15 +1214,15 @@ void AvmTraceBuilder::op_shl( .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), //.main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), - .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(in_tag)), }); ASSERT(op_code == OpCode::SHL_8 || op_code == OpCode::SHL_16); pc += Deserialization::get_pc_increment(op_code); + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_shr( +AvmError AvmTraceBuilder::op_shr( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code) { auto clk = static_cast(main_trace.size()) + 1; @@ -1173,18 +1233,17 @@ void AvmTraceBuilder::op_shr( // We get our representative memory tag from the resolved_a memory address. AvmMemoryTag in_tag = unconstrained_get_memory_tag(resolved_a); // Reading from memory and loading into ia resp. ib. - // TODO(9497): if simulator fails tag check here, witgen will not. Raise error flag if in_tag is FF! auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); // TODO(8603): once instructions can have multiple different tags for reads, constrain b's read & tag // auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, AvmMemoryTag::U8, AvmMemoryTag::U8, // IntermRegister::IB); bool tag_match = read_a.tag_match && read_b.tag_match; - auto read_b = unconstrained_read_from_memory(resolved_b); // should be tagged as U8 - bool tag_match = read_a.tag_match; + auto read_b = unconstrained_read_from_memory(resolved_b); + bool op_valid = check_tag_integral(read_a.tag) && check_tag(AvmMemoryTag::U8, resolved_b); - FF a = tag_match ? read_a.val : FF(0); - FF b = tag_match ? read_b : FF(0); + FF a = op_valid ? read_a.val : FF(0); + FF b = op_valid ? read_b : FF(0); - FF c = tag_match ? alu_trace_builder.op_shr(a, b, in_tag, clk) : FF(0); + FF c = op_valid ? alu_trace_builder.op_shr(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); @@ -1207,6 +1266,7 @@ void AvmTraceBuilder::op_shr( // TODO(8603): uncomment //.main_mem_addr_b = FF(read_b.direct_address), .main_mem_addr_c = FF(write_c.direct_address), + .main_op_err = FF(static_cast(!op_valid)), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -1219,12 +1279,12 @@ void AvmTraceBuilder::op_shr( // TODO(8603): uncomment //.main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), - .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(in_tag)), }); ASSERT(op_code == OpCode::SHR_8 || op_code == OpCode::SHR_16); pc += Deserialization::get_pc_increment(op_code); + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /************************************************************************************************** @@ -1240,23 +1300,22 @@ void AvmTraceBuilder::op_shr( * @param dst_offset Offset of destination memory cell. * @param dst_tag Destination tag specifying the type the source value must be casted to. */ -void AvmTraceBuilder::op_cast( +AvmError AvmTraceBuilder::op_cast( uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, AvmMemoryTag dst_tag, OpCode op_code) { auto const clk = static_cast(main_trace.size()) + 1; - bool tag_match = true; auto [resolved_a, resolved_c] = Addressing<2>::fromWire(indirect, call_ptr).resolve({ a_offset, dst_offset }, mem_trace_builder); // Reading from memory and loading into ia + // There cannot be any tag error in this case. auto memEntry = mem_trace_builder.read_and_load_cast_opcode(call_ptr, clk, resolved_a, dst_tag); FF a = memEntry.val; - // In case of a memory tag error, we do not perform the computation. // Therefore, we do not create any entry in ALU table and store the value 0 as // output (c) in memory. - FF c = tag_match ? alu_trace_builder.op_cast(a, dst_tag, clk) : FF(0); + FF c = alu_trace_builder.op_cast(a, dst_tag, clk); // Write into memory value c from intermediate register ic. mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IC, resolved_c, c, memEntry.tag, dst_tag); @@ -1279,12 +1338,12 @@ void AvmTraceBuilder::op_cast( .main_sel_mem_op_a = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_cast = FF(1), - .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(dst_tag)), }); ASSERT(op_code == OpCode::CAST_8 || op_code == OpCode::CAST_16); pc += Deserialization::get_pc_increment(op_code); + return AvmError::NO_ERROR; } /************************************************************************************************** @@ -1300,7 +1359,6 @@ void AvmTraceBuilder::op_cast( * * @param indirect - Perform indirect memory resolution * @param dst_offset - Memory address to write the lookup result to - * @param selector - The index of the kernel input lookup column * @param value - The value read from the memory address * @param w_tag - The memory tag of the value read * @return Row @@ -1330,7 +1388,7 @@ Row AvmTraceBuilder::create_kernel_lookup_opcode(uint8_t indirect, uint32_t dst_ }; } -void AvmTraceBuilder::op_get_env_var(uint8_t indirect, uint8_t env_var, uint32_t dst_offset) +AvmError AvmTraceBuilder::op_get_env_var(uint8_t indirect, uint8_t env_var, uint32_t dst_offset) { if (env_var >= static_cast(EnvironmentVariable::MAX_ENV_VAR)) { // Error, bad enum operand @@ -1341,14 +1399,14 @@ void AvmTraceBuilder::op_get_env_var(uint8_t indirect, uint8_t env_var, uint32_t .main_call_ptr = call_ptr, .main_internal_return_ptr = internal_return_ptr, .main_op_err = FF(1), - .main_pc = pc++, + .main_pc = pc, .main_sel_op_address = FF(1), // TODO(9407): what selector should this be? }; // Constrain gas cost gas_trace_builder.constrain_gas(static_cast(row.main_clk), OpCode::GETENVVAR_16); - main_trace.push_back(row); + return AvmError::ENV_VAR_UNKNOWN; } else { EnvironmentVariable var = static_cast(env_var); @@ -1393,11 +1451,13 @@ void AvmTraceBuilder::op_get_env_var(uint8_t indirect, uint8_t env_var, uint32_t op_dagasleft(indirect, dst_offset); break; default: + // Cannot happen thanks to the first if clause. This is to make the compiler happy. throw std::runtime_error("Invalid environment variable"); break; } + pc += Deserialization::get_pc_increment(OpCode::GETENVVAR_16); + return AvmError::NO_ERROR; } - pc += Deserialization::get_pc_increment(OpCode::GETENVVAR_16); } void AvmTraceBuilder::op_address(uint8_t indirect, uint32_t dst_offset) @@ -1569,10 +1629,10 @@ void AvmTraceBuilder::op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset) * @param copy_size_offset The number of finite field elements to be copied into memory. * @param dst_offset The starting index of memory where calldata will be copied to. */ -void AvmTraceBuilder::op_calldata_copy(uint8_t indirect, - uint32_t cd_offset_address, - uint32_t copy_size_address, - uint32_t dst_offset) +AvmError AvmTraceBuilder::op_calldata_copy(uint8_t indirect, + uint32_t cd_offset_address, + uint32_t copy_size_address, + uint32_t dst_offset) { auto clk = static_cast(main_trace.size()) + 1; @@ -1582,16 +1642,14 @@ void AvmTraceBuilder::op_calldata_copy(uint8_t indirect, // This boolean will not be a trivial constant anymore once we constrain address resolution. bool tag_match = true; - - // The only memory operations performed from the main trace are indirect load (address resolutions) - // which are still unconstrained. - // All the other memory operations are triggered by the slice gadget. + bool op_valid = tag_match && check_tag(AvmMemoryTag::U32, cd_offset_resolved) && + check_tag(AvmMemoryTag::U32, copy_size_offset_resolved); // TODO: constrain these. const uint32_t cd_offset = static_cast(unconstrained_read_from_memory(cd_offset_resolved)); const uint32_t copy_size = static_cast(unconstrained_read_from_memory(copy_size_offset_resolved)); - if (tag_match) { + if (op_valid) { slice_trace_builder.create_calldata_copy_slice( calldata, clk, call_ptr, cd_offset, copy_size, dst_offset_resolved); mem_trace_builder.write_calldata_copy(calldata, clk, call_ptr, cd_offset, copy_size, dst_offset_resolved); @@ -1607,18 +1665,20 @@ void AvmTraceBuilder::op_calldata_copy(uint8_t indirect, .main_ib = copy_size, .main_internal_return_ptr = FF(internal_return_ptr), .main_mem_addr_c = dst_offset_resolved, + .main_op_err = static_cast(!op_valid), .main_pc = pc, .main_r_in_tag = static_cast(AvmMemoryTag::FF), .main_sel_op_calldata_copy = 1, - .main_sel_slice_gadget = static_cast(tag_match), + .main_sel_slice_gadget = static_cast(op_valid), .main_tag_err = static_cast(!tag_match), .main_w_in_tag = static_cast(AvmMemoryTag::FF), }); pc += Deserialization::get_pc_increment(OpCode::CALLDATACOPY); + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_returndata_size(uint8_t indirect, uint32_t dst_offset) +AvmError AvmTraceBuilder::op_returndata_size(uint8_t indirect, uint32_t dst_offset) { auto const clk = static_cast(main_trace.size()) + 1; // This boolean will not be a trivial constant anymore once we constrain address resolution. @@ -1644,12 +1704,13 @@ void AvmTraceBuilder::op_returndata_size(uint8_t indirect, uint32_t dst_offset) }); pc += Deserialization::get_pc_increment(OpCode::RETURNDATASIZE); + return tag_match ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_returndata_copy(uint8_t indirect, - uint32_t rd_offset_address, - uint32_t copy_size_offset, - uint32_t dst_offset) +AvmError AvmTraceBuilder::op_returndata_copy(uint8_t indirect, + uint32_t rd_offset_address, + uint32_t copy_size_offset, + uint32_t dst_offset) { auto clk = static_cast(main_trace.size()) + 1; @@ -1659,6 +1720,8 @@ void AvmTraceBuilder::op_returndata_copy(uint8_t indirect, // This boolean will not be a trivial constant anymore once we constrain address resolution. bool tag_match = true; + bool op_valid = tag_match && check_tag(AvmMemoryTag::U32, rd_offset_address) && + check_tag(AvmMemoryTag::U32, copy_size_offset_resolved); // TODO: constrain these. const uint32_t rd_offset = static_cast(unconstrained_read_from_memory(rd_offset_resolved)); @@ -1671,21 +1734,25 @@ void AvmTraceBuilder::op_returndata_copy(uint8_t indirect, main_trace.push_back(Row{ .main_clk = clk, .main_internal_return_ptr = FF(internal_return_ptr), + .main_op_err = static_cast(!op_valid), .main_pc = FF(pc), .main_sel_op_returndata_copy = FF(1), .main_tag_err = FF(static_cast(!tag_match)), }); - // Write the return data to memory - // TODO: validate bounds - auto returndata_slice = - std::vector(nested_returndata.begin() + rd_offset, nested_returndata.begin() + rd_offset + copy_size); + if (op_valid) { + // Write the return data to memory + // TODO: validate bounds + auto returndata_slice = + std::vector(nested_returndata.begin() + rd_offset, nested_returndata.begin() + rd_offset + copy_size); - pc += Deserialization::get_pc_increment(OpCode::RETURNDATACOPY); + pc += Deserialization::get_pc_increment(OpCode::RETURNDATACOPY); - // Crucial to perform this operation after having incremented pc because write_slice_to_memory - // is implemented with opcodes (SET and JUMP). - write_slice_to_memory(dst_offset_resolved, AvmMemoryTag::FF, returndata_slice); + // Crucial to perform this operation after having incremented pc because write_slice_to_memory + // is implemented with opcodes (SET and JUMP). + write_slice_to_memory(dst_offset_resolved, AvmMemoryTag::FF, returndata_slice); + } + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /************************************************************************************************** @@ -1695,7 +1762,7 @@ void AvmTraceBuilder::op_returndata_copy(uint8_t indirect, // Helper for "gas left" related opcodes void AvmTraceBuilder::execute_gasleft(EnvironmentVariable var, uint8_t indirect, uint32_t dst_offset) { - assert(var == EnvironmentVariable::L2GASLEFT || var == EnvironmentVariable::DAGASLEFT); + ASSERT(var == EnvironmentVariable::L2GASLEFT || var == EnvironmentVariable::DAGASLEFT); auto clk = static_cast(main_trace.size()) + 1; @@ -1758,7 +1825,7 @@ void AvmTraceBuilder::op_dagasleft(uint8_t indirect, uint32_t dst_offset) * * @param jmp_dest - The destination to jump to */ -void AvmTraceBuilder::op_jump(uint32_t jmp_dest, bool skip_gas) +AvmError AvmTraceBuilder::op_jump(uint32_t jmp_dest, bool skip_gas) { auto clk = static_cast(main_trace.size()) + 1; @@ -1778,6 +1845,7 @@ void AvmTraceBuilder::op_jump(uint32_t jmp_dest, bool skip_gas) // Adjust parameters for the next row pc = jmp_dest; + return AvmError::NO_ERROR; } /** @@ -1790,7 +1858,7 @@ void AvmTraceBuilder::op_jump(uint32_t jmp_dest, bool skip_gas) * @param jmp_dest The destination to jump to * @param cond_offset Offset of the condition */ -void AvmTraceBuilder::op_jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t cond_offset) +AvmError AvmTraceBuilder::op_jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t cond_offset) { auto clk = static_cast(main_trace.size()) + 1; @@ -1829,6 +1897,7 @@ void AvmTraceBuilder::op_jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t con // Adjust parameters for the next row pc = next_pc; + return tag_match ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /** @@ -1844,7 +1913,7 @@ void AvmTraceBuilder::op_jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t con * * @param jmp_dest - The destination to jump to */ -void AvmTraceBuilder::op_internal_call(uint32_t jmp_dest) +AvmError AvmTraceBuilder::op_internal_call(uint32_t jmp_dest) { auto clk = static_cast(main_trace.size()) + 1; const auto next_pc = pc + Deserialization::get_pc_increment(OpCode::INTERNALCALL); @@ -1877,6 +1946,7 @@ void AvmTraceBuilder::op_internal_call(uint32_t jmp_dest) // Adjust parameters for the next row pc = jmp_dest; internal_return_ptr++; + return AvmError::NO_ERROR; } /** @@ -1890,7 +1960,7 @@ void AvmTraceBuilder::op_internal_call(uint32_t jmp_dest) * TODO(https://github.com/AztecProtocol/aztec-packages/issues/3740): This function MUST come after a call * instruction. */ -void AvmTraceBuilder::op_internal_return() +AvmError AvmTraceBuilder::op_internal_return() { auto clk = static_cast(main_trace.size()) + 1; @@ -1918,6 +1988,7 @@ void AvmTraceBuilder::op_internal_return() pc = uint32_t(read_a.val); internal_return_ptr--; + return AvmError::NO_ERROR; } /************************************************************************************************** @@ -1938,7 +2009,7 @@ void AvmTraceBuilder::op_internal_return() * @param dst_offset Memory destination offset where val is written to * @param in_tag The instruction memory tag */ -void AvmTraceBuilder::op_set( +AvmError AvmTraceBuilder::op_set( uint8_t indirect, FF val_ff, uint32_t dst_offset, AvmMemoryTag in_tag, OpCode op_code, bool skip_gas) { auto const clk = static_cast(main_trace.size()) + 1; @@ -1973,6 +2044,7 @@ void AvmTraceBuilder::op_set( OpCode::SET_64, OpCode::SET_128, OpCode::SET_FF }; ASSERT(set_family.contains(op_code)); pc += Deserialization::get_pc_increment(op_code); + return write_c.tag_match ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /** @@ -1983,7 +2055,7 @@ void AvmTraceBuilder::op_set( * @param src_offset Offset of source memory cell * @param dst_offset Offset of destination memory cell */ -void AvmTraceBuilder::op_mov(uint8_t indirect, uint32_t src_offset, uint32_t dst_offset, OpCode op_code) +AvmError AvmTraceBuilder::op_mov(uint8_t indirect, uint32_t src_offset, uint32_t dst_offset, OpCode op_code) { auto const clk = static_cast(main_trace.size()) + 1; @@ -2024,6 +2096,7 @@ void AvmTraceBuilder::op_mov(uint8_t indirect, uint32_t src_offset, uint32_t dst ASSERT(op_code == OpCode::MOV_8 || op_code == OpCode::MOV_16); pc += Deserialization::get_pc_increment(op_code); + return tag_match ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /************************************************************************************************** @@ -2126,20 +2199,15 @@ Row AvmTraceBuilder::create_kernel_output_opcode_with_metadata(uint8_t indirect, * @return Row */ Row AvmTraceBuilder::create_kernel_output_opcode_with_set_metadata_output_from_hint( - uint8_t indirect, uint32_t clk, uint32_t data_offset, uint32_t address_offset, uint32_t metadata_offset) + uint32_t clk, uint32_t data_offset, [[maybe_unused]] uint32_t address_offset, uint32_t metadata_offset) { FF exists = execution_hints.get_side_effect_hints().at(side_effect_counter); - // TODO: resolved_address should be used - auto [resolved_data, resolved_address, resolved_metadata] = - Addressing<3>::fromWire(indirect, call_ptr) - .resolve({ data_offset, address_offset, metadata_offset }, mem_trace_builder); - auto read_a = constrained_read_from_memory( - call_ptr, clk, resolved_data, AvmMemoryTag::FF, AvmMemoryTag::U1, IntermRegister::IA); + call_ptr, clk, data_offset, AvmMemoryTag::FF, AvmMemoryTag::U1, IntermRegister::IA); auto write_b = constrained_write_to_memory( - call_ptr, clk, resolved_metadata, exists, AvmMemoryTag::FF, AvmMemoryTag::U1, IntermRegister::IB); + call_ptr, clk, metadata_offset, exists, AvmMemoryTag::FF, AvmMemoryTag::U1, IntermRegister::IB); bool tag_match = read_a.tag_match && write_b.tag_match; return Row{ @@ -2260,7 +2328,7 @@ Row AvmTraceBuilder::create_kernel_output_opcode_with_set_value_from_hint(uint8_ * WORLD STATE **************************************************************************************************/ -void AvmTraceBuilder::op_sload(uint8_t indirect, uint32_t slot_offset, uint32_t size, uint32_t dest_offset) +AvmError AvmTraceBuilder::op_sload(uint8_t indirect, uint32_t slot_offset, uint32_t size, uint32_t dest_offset) { auto clk = static_cast(main_trace.size()) + 1; @@ -2291,6 +2359,7 @@ void AvmTraceBuilder::op_sload(uint8_t indirect, uint32_t slot_offset, uint32_t // gas_trace_builder.constrain_gas(clk, OpCode::SLOAD); // clk++; + bool accumulated_tag_match = true; AddressWithMode write_dst = resolved_dest; // Loop over the size and write the hints to memory for (uint32_t i = 0; i < size; i++) { @@ -2316,6 +2385,7 @@ void AvmTraceBuilder::op_sload(uint8_t indirect, uint32_t slot_offset, uint32_t .main_w_in_tag = static_cast(AvmMemoryTag::FF), }; + accumulated_tag_match = accumulated_tag_match && write_a.tag_match; // Output storage read to kernel outputs (performs lookup) // Tuples of (slot, value) in the kernel lookup kernel_trace_builder.op_sload(clk, side_effect_counter, row.main_ib, row.main_ia); @@ -2335,9 +2405,10 @@ void AvmTraceBuilder::op_sload(uint8_t indirect, uint32_t slot_offset, uint32_t write_dst = AddressWithMode{ AddressingMode::DIRECT, write_a.direct_address + 1 }; } pc += Deserialization::get_pc_increment(OpCode::SLOAD); + return accumulated_tag_match ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t size, uint32_t slot_offset) +AvmError AvmTraceBuilder::op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t size, uint32_t slot_offset) { auto clk = static_cast(main_trace.size()) + 1; @@ -2369,6 +2440,7 @@ void AvmTraceBuilder::op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t // clk++; AddressWithMode read_src = resolved_src; + bool accumulated_tag_match = true; // This loop reads a _size_ number of elements from memory and places them into a tuple of (ele, slot) // in the kernel lookup. @@ -2393,6 +2465,7 @@ void AvmTraceBuilder::op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t }; row.main_sel_op_sstore = FF(1); kernel_trace_builder.op_sstore(clk, side_effect_counter, row.main_ib, row.main_ia); + accumulated_tag_match = accumulated_tag_match && read_a.tag_match; // Constrain gas cost // TODO: when/if we move this to its own gadget, and we have 1 row only, we should pass the size as @@ -2409,12 +2482,13 @@ void AvmTraceBuilder::op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t } pc += Deserialization::get_pc_increment(OpCode::SSTORE); + return accumulated_tag_match ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_note_hash_exists(uint8_t indirect, - uint32_t note_hash_offset, - uint32_t leaf_index_offset, - uint32_t dest_offset) +AvmError AvmTraceBuilder::op_note_hash_exists(uint8_t indirect, + uint32_t note_hash_offset, + uint32_t leaf_index_offset, + uint32_t dest_offset) { auto const clk = static_cast(main_trace.size()) + 1; @@ -2423,15 +2497,28 @@ void AvmTraceBuilder::op_note_hash_exists(uint8_t indirect, .resolve({ note_hash_offset, leaf_index_offset, dest_offset }, mem_trace_builder); const auto leaf_index = unconstrained_read_from_memory(resolved_leaf_index); - - Row row = create_kernel_output_opcode_for_leaf_index( - clk, resolved_note_hash, static_cast(leaf_index), resolved_dest); - - kernel_trace_builder.op_note_hash_exists(clk, - /*side_effect_counter*/ static_cast(leaf_index), - row.main_ia, - /*safe*/ static_cast(row.main_ib)); - row.main_sel_op_note_hash_exists = FF(1); + bool op_valid = check_tag(AvmMemoryTag::FF, resolved_leaf_index); + Row row; + + if (op_valid) { + row = create_kernel_output_opcode_for_leaf_index( + clk, resolved_note_hash, static_cast(leaf_index), resolved_dest); + + kernel_trace_builder.op_note_hash_exists(clk, + /*side_effect_counter*/ static_cast(leaf_index), + row.main_ia, + /*safe*/ static_cast(row.main_ib)); + row.main_sel_op_note_hash_exists = FF(1); + op_valid = op_valid && row.main_tag_err == FF(0); + } else { + row = Row{ + .main_clk = clk, + .main_internal_return_ptr = internal_return_ptr, + .main_op_err = FF(1), + .main_pc = pc, + .main_sel_op_note_hash_exists = FF(1), + }; + } // Constrain gas cost gas_trace_builder.constrain_gas(clk, OpCode::NOTEHASHEXISTS); @@ -2440,9 +2527,10 @@ void AvmTraceBuilder::op_note_hash_exists(uint8_t indirect, debug("note_hash_exists side-effect cnt: ", side_effect_counter); pc += Deserialization::get_pc_increment(OpCode::NOTEHASHEXISTS); + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_emit_note_hash(uint8_t indirect, uint32_t note_hash_offset) +AvmError AvmTraceBuilder::op_emit_note_hash(uint8_t indirect, uint32_t note_hash_offset) { auto const clk = static_cast(main_trace.size()) + 1; @@ -2459,20 +2547,40 @@ void AvmTraceBuilder::op_emit_note_hash(uint8_t indirect, uint32_t note_hash_off side_effect_counter++; pc += Deserialization::get_pc_increment(OpCode::EMITNOTEHASH); + return row.main_tag_err == FF(0) ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_nullifier_exists(uint8_t indirect, - uint32_t nullifier_offset, - uint32_t address_offset, - uint32_t dest_offset) +AvmError AvmTraceBuilder::op_nullifier_exists(uint8_t indirect, + uint32_t nullifier_offset, + uint32_t address_offset, + uint32_t dest_offset) { auto const clk = static_cast(main_trace.size()) + 1; - Row row = create_kernel_output_opcode_with_set_metadata_output_from_hint( - indirect, clk, nullifier_offset, address_offset, dest_offset); - kernel_trace_builder.op_nullifier_exists( - clk, side_effect_counter, row.main_ia, /*safe*/ static_cast(row.main_ib)); - row.main_sel_op_nullifier_exists = FF(1); + auto [resolved_nullifier_offset, resolved_address, resolved_dest] = + Addressing<3>::fromWire(indirect, call_ptr) + .resolve({ nullifier_offset, address_offset, dest_offset }, mem_trace_builder); + + bool op_valid = check_tag(AvmMemoryTag::FF, resolved_address); + + Row row; + + if (op_valid) { + row = create_kernel_output_opcode_with_set_metadata_output_from_hint( + clk, resolved_nullifier_offset, resolved_address, resolved_dest); + kernel_trace_builder.op_nullifier_exists( + clk, side_effect_counter, row.main_ia, /*safe*/ static_cast(row.main_ib)); + row.main_sel_op_nullifier_exists = FF(1); + op_valid = op_valid && row.main_tag_err == FF(0); + } else { + row = Row{ + .main_clk = clk, + .main_internal_return_ptr = internal_return_ptr, + .main_op_err = FF(1), + .main_pc = pc, + .main_sel_op_nullifier_exists = FF(1), + }; + } // Constrain gas cost gas_trace_builder.constrain_gas(clk, OpCode::NULLIFIEREXISTS); @@ -2483,9 +2591,10 @@ void AvmTraceBuilder::op_nullifier_exists(uint8_t indirect, side_effect_counter++; pc += Deserialization::get_pc_increment(OpCode::NULLIFIEREXISTS); + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_emit_nullifier(uint8_t indirect, uint32_t nullifier_offset) +AvmError AvmTraceBuilder::op_emit_nullifier(uint8_t indirect, uint32_t nullifier_offset) { auto const clk = static_cast(main_trace.size()) + 1; @@ -2502,12 +2611,13 @@ void AvmTraceBuilder::op_emit_nullifier(uint8_t indirect, uint32_t nullifier_off side_effect_counter++; pc += Deserialization::get_pc_increment(OpCode::EMITNULLIFIER); + return row.main_tag_err == FF(0) ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_l1_to_l2_msg_exists(uint8_t indirect, - uint32_t log_offset, - uint32_t leaf_index_offset, - uint32_t dest_offset) +AvmError AvmTraceBuilder::op_l1_to_l2_msg_exists(uint8_t indirect, + uint32_t log_offset, + uint32_t leaf_index_offset, + uint32_t dest_offset) { auto const clk = static_cast(main_trace.size()) + 1; @@ -2516,14 +2626,27 @@ void AvmTraceBuilder::op_l1_to_l2_msg_exists(uint8_t indirect, .resolve({ log_offset, leaf_index_offset, dest_offset }, mem_trace_builder); const auto leaf_index = unconstrained_read_from_memory(resolved_leaf_index); - - Row row = - create_kernel_output_opcode_for_leaf_index(clk, resolved_log, static_cast(leaf_index), resolved_dest); - kernel_trace_builder.op_l1_to_l2_msg_exists(clk, - static_cast(leaf_index) /*side_effect_counter*/, - row.main_ia, - /*safe*/ static_cast(row.main_ib)); - row.main_sel_op_l1_to_l2_msg_exists = FF(1); + bool op_valid = check_tag(AvmMemoryTag::FF, resolved_leaf_index); + Row row; + + if (op_valid) { + row = create_kernel_output_opcode_for_leaf_index( + clk, resolved_log, static_cast(leaf_index), resolved_dest); + kernel_trace_builder.op_l1_to_l2_msg_exists(clk, + static_cast(leaf_index) /*side_effect_counter*/, + row.main_ia, + /*safe*/ static_cast(row.main_ib)); + row.main_sel_op_l1_to_l2_msg_exists = FF(1); + op_valid = op_valid && row.main_tag_err == FF(0); + } else { + row = Row{ + .main_clk = clk, + .main_internal_return_ptr = internal_return_ptr, + .main_op_err = FF(1), + .main_pc = pc, + .main_sel_op_l1_to_l2_msg_exists = FF(1), + }; + } // Constrain gas cost gas_trace_builder.constrain_gas(clk, OpCode::L1TOL2MSGEXISTS); @@ -2533,9 +2656,10 @@ void AvmTraceBuilder::op_l1_to_l2_msg_exists(uint8_t indirect, debug("l1_to_l2_msg_exists side-effect cnt: ", side_effect_counter); pc += Deserialization::get_pc_increment(OpCode::L1TOL2MSGEXISTS); + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_get_contract_instance( +AvmError AvmTraceBuilder::op_get_contract_instance( uint8_t indirect, uint8_t member_enum, uint16_t address_offset, uint16_t dst_offset, uint16_t exists_offset) { auto clk = static_cast(main_trace.size()) + 1; @@ -2555,93 +2679,92 @@ void AvmTraceBuilder::op_get_contract_instance( }; main_trace.push_back(row); pc += Deserialization::get_pc_increment(OpCode::GETCONTRACTINSTANCE); - } else { - - ContractInstanceMember chosen_member = static_cast(member_enum); - - auto [resolved_address_offset, resolved_dst_offset, resolved_exists_offset] = - Addressing<3>::fromWire(indirect, call_ptr) - .resolve({ address_offset, dst_offset, exists_offset }, mem_trace_builder); - - auto read_address = constrained_read_from_memory( - call_ptr, clk, resolved_address_offset, AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::IA); - bool tag_match = read_address.tag_match; + return AvmError::CONTRACT_INST_MEM_UNKNOWN; + }; - // Read the contract instance - ContractInstanceHint instance = execution_hints.contract_instance_hints.at(read_address.val); + ContractInstanceMember chosen_member = static_cast(member_enum); - FF member_value; - switch (chosen_member) { - case ContractInstanceMember::DEPLOYER: - member_value = instance.deployer_addr; - break; - case ContractInstanceMember::CLASS_ID: - member_value = instance.contract_class_id; - break; - case ContractInstanceMember::INIT_HASH: - member_value = instance.initialisation_hash; - break; - default: - member_value = 0; - break; - } + auto [resolved_address_offset, resolved_dst_offset, resolved_exists_offset] = + Addressing<3>::fromWire(indirect, call_ptr) + .resolve({ address_offset, dst_offset, exists_offset }, mem_trace_builder); + + auto read_address = constrained_read_from_memory( + call_ptr, clk, resolved_address_offset, AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::IA); + bool tag_match = read_address.tag_match; + + // Read the contract instance + ContractInstanceHint instance = execution_hints.contract_instance_hints.at(read_address.val); + + FF member_value; + switch (chosen_member) { + case ContractInstanceMember::DEPLOYER: + member_value = instance.deployer_addr; + break; + case ContractInstanceMember::CLASS_ID: + member_value = instance.contract_class_id; + break; + case ContractInstanceMember::INIT_HASH: + member_value = instance.initialisation_hash; + break; + default: + member_value = 0; + break; + } - // TODO(8603): once instructions can have multiple different tags for writes, write dst as FF and exists as U1 - // auto write_dst = constrained_write_to_memory(call_ptr, clk, resolved_dst_offset, member_value, - // AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::IC); auto write_exists = - // constrained_write_to_memory(call_ptr, clk, resolved_exists_offset, instance.instance_found_in_address, - // AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::ID); + // TODO(8603): once instructions can have multiple different tags for writes, write dst as FF and exists as + // U1 auto write_dst = constrained_write_to_memory(call_ptr, clk, resolved_dst_offset, member_value, + // AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::IC); auto write_exists = + // constrained_write_to_memory(call_ptr, clk, resolved_exists_offset, instance.instance_found_in_address, + // AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::ID); - main_trace.push_back(Row{ - .main_clk = clk, - .main_call_ptr = call_ptr, - .main_ia = read_address.val, - // TODO(8603): uncomment this and below blocks once instructions can have multiple different tags for - // writes - //.main_ic = write_dst.val, - //.main_id = write_exists.val, - .main_ind_addr_a = FF(read_address.indirect_address), - //.main_ind_addr_c = FF(write_dst.indirect_address), - //.main_ind_addr_d = FF(write_exists.indirect_address), - .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(read_address.direct_address), - //.main_mem_addr_c = FF(write_dst.direct_address), - //.main_mem_addr_d = FF(write_exists.direct_address), - .main_pc = FF(pc), - .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), - .main_sel_mem_op_a = FF(1), - //.main_sel_mem_op_c = FF(1), - //.main_sel_mem_op_d = FF(1), - .main_sel_op_get_contract_instance = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(read_address.is_indirect)), - //.main_sel_resolve_ind_addr_c = FF(static_cast(write_dst.is_indirect)), - //.main_sel_resolve_ind_addr_d = FF(static_cast(write_exists.is_indirect)), - .main_tag_err = FF(static_cast(!tag_match)), - }); + main_trace.push_back(Row{ + .main_clk = clk, + .main_call_ptr = call_ptr, + .main_ia = read_address.val, + // TODO(8603): uncomment this and below blocks once instructions can have multiple different tags for + // writes + //.main_ic = write_dst.val, + //.main_id = write_exists.val, + .main_ind_addr_a = FF(read_address.indirect_address), + //.main_ind_addr_c = FF(write_dst.indirect_address), + //.main_ind_addr_d = FF(write_exists.indirect_address), + .main_internal_return_ptr = FF(internal_return_ptr), + .main_mem_addr_a = FF(read_address.direct_address), + //.main_mem_addr_c = FF(write_dst.direct_address), + //.main_mem_addr_d = FF(write_exists.direct_address), + .main_pc = FF(pc), + .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), + .main_sel_mem_op_a = FF(1), + //.main_sel_mem_op_c = FF(1), + //.main_sel_mem_op_d = FF(1), + .main_sel_op_get_contract_instance = FF(1), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_address.is_indirect)), + //.main_sel_resolve_ind_addr_c = FF(static_cast(write_dst.is_indirect)), + //.main_sel_resolve_ind_addr_d = FF(static_cast(write_exists.is_indirect)), + .main_tag_err = FF(static_cast(!tag_match)), + }); - pc += Deserialization::get_pc_increment(OpCode::GETCONTRACTINSTANCE); + pc += Deserialization::get_pc_increment(OpCode::GETCONTRACTINSTANCE); - // Crucial to perform this operation after having incremented pc because write_slice_to_memory - // is implemented with opcodes (SET and JUMP). - // TODO(8603): once instructions can have multiple different tags for writes, remove this and do a constrained - // writes - write_to_memory(resolved_dst_offset, member_value, AvmMemoryTag::FF); - write_to_memory(resolved_exists_offset, FF(static_cast(instance.exists)), AvmMemoryTag::U1); + // Crucial to perform this operation after having incremented pc because write_slice_to_memory + // is implemented with opcodes (SET and JUMP). + // TODO(8603): once instructions can have multiple different tags for writes, remove this and do a + // constrained writes + write_to_memory(resolved_dst_offset, member_value, AvmMemoryTag::FF); + write_to_memory(resolved_exists_offset, FF(static_cast(instance.exists)), AvmMemoryTag::U1); - // TODO(dbanks12): compute contract address nullifier from instance preimage and perform membership check + // TODO(dbanks12): compute contract address nullifier from instance preimage and perform membership check - debug("contract_instance cnt: ", side_effect_counter); - side_effect_counter++; - } + debug("contract_instance cnt: ", side_effect_counter); + side_effect_counter++; + return tag_match ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /************************************************************************************************** * ACCRUED SUBSTATE **************************************************************************************************/ -void AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, - uint32_t log_offset, - [[maybe_unused]] uint32_t log_size_offset) +AvmError AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, uint32_t log_offset, uint32_t log_size_offset) { std::vector bytes_to_hash; @@ -2652,7 +2775,7 @@ void AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, Addressing<2>::fromWire(indirect, call_ptr).resolve({ log_offset, log_size_offset }, mem_trace_builder); // This is a hack to get the contract address from the first contract instance - // Once we have 1-enqueued call and proper nested contexts, this should use that address of the current contextt + // Once we have 1-enqueued call and proper nested contexts, this should use that address of the current context FF contract_address = execution_hints.all_contract_bytecode.at(0).contract_instance.address; std::vector contract_address_bytes = contract_address.to_buffer(); @@ -2661,46 +2784,68 @@ void AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, std::make_move_iterator(contract_address_bytes.begin()), std::make_move_iterator(contract_address_bytes.end())); - uint32_t log_size = static_cast(unconstrained_read_from_memory(resolved_log_size_offset)); - // The size is in fields of 32 bytes, the length used for the hash is in terms of bytes - uint32_t num_bytes = log_size * 32; - std::vector log_size_bytes = to_buffer(num_bytes); - // Add the log size to the hash to bytes - bytes_to_hash.insert(bytes_to_hash.end(), - std::make_move_iterator(log_size_bytes.begin()), - std::make_move_iterator(log_size_bytes.end())); - - AddressWithMode direct_field_addr = AddressWithMode(static_cast(resolved_log_offset)); - // We need to read the rest of the log_size number of elements - std::vector log_value_bytes; - for (uint32_t i = 0; i < log_size; i++) { - FF log_value = unconstrained_read_from_memory(direct_field_addr + i); - std::vector log_value_byte = log_value.to_buffer(); + bool op_valid = + check_tag(AvmMemoryTag::FF, resolved_log_offset) && check_tag(AvmMemoryTag::U32, resolved_log_size_offset); + + Row row; + uint32_t log_size = 0; + AddressWithMode direct_field_addr; + uint32_t num_bytes = 0; + + if (op_valid) { + log_size = static_cast(unconstrained_read_from_memory(resolved_log_size_offset)); + + // The size is in fields of 32 bytes, the length used for the hash is in terms of bytes + num_bytes = log_size * 32; + std::vector log_size_bytes = to_buffer(num_bytes); + // Add the log size to the hash to bytes bytes_to_hash.insert(bytes_to_hash.end(), - std::make_move_iterator(log_value_byte.begin()), - std::make_move_iterator(log_value_byte.end())); - } - - std::array output = crypto::sha256(bytes_to_hash); - // Truncate the hash to 31 bytes so it will be a valid field element - FF trunc_hash = FF(from_buffer(output.data()) >> 8); - - // The + 32 here is for the contract_address in bytes, the +4 is for the extra 4 bytes that contain log_size and - // is prefixed to message see toBuffer in unencrypted_l2_log.ts - FF length_of_preimage = num_bytes + 32 + 4; - // The + 4 is because the kernels store the length of the - // processed log as 4 bytes; thus for this length value to match the log length stored in the kernels, we need - // to add four to the length here. [Copied from unencrypted_l2_log.ts] - FF metadata_log_length = length_of_preimage + 4; - Row row = Row{ - .main_clk = clk, - .main_ia = trunc_hash, - .main_ib = metadata_log_length, - .main_internal_return_ptr = internal_return_ptr, - .main_pc = pc, - }; - kernel_trace_builder.op_emit_unencrypted_log(clk, side_effect_counter, trunc_hash, metadata_log_length); - row.main_sel_op_emit_unencrypted_log = FF(1); + std::make_move_iterator(log_size_bytes.begin()), + std::make_move_iterator(log_size_bytes.end())); + + direct_field_addr = AddressWithMode(static_cast(resolved_log_offset)); + op_valid = op_valid && check_tag_range(AvmMemoryTag::FF, direct_field_addr, log_size); + } + + if (op_valid) { + // We need to read the rest of the log_size number of elements + for (uint32_t i = 0; i < log_size; i++) { + FF log_value = unconstrained_read_from_memory(direct_field_addr + i); + std::vector log_value_byte = log_value.to_buffer(); + bytes_to_hash.insert(bytes_to_hash.end(), + std::make_move_iterator(log_value_byte.begin()), + std::make_move_iterator(log_value_byte.end())); + } + + std::array output = crypto::sha256(bytes_to_hash); + // Truncate the hash to 31 bytes so it will be a valid field element + FF trunc_hash = FF(from_buffer(output.data()) >> 8); + + // The + 32 here is for the contract_address in bytes, the +4 is for the extra 4 bytes that contain log_size + // and is prefixed to message see toBuffer in unencrypted_l2_log.ts + FF length_of_preimage = num_bytes + 32 + 4; + // The + 4 is because the kernels store the length of the + // processed log as 4 bytes; thus for this length value to match the log length stored in the kernels, we + // need to add four to the length here. [Copied from unencrypted_l2_log.ts] + FF metadata_log_length = length_of_preimage + 4; + row = Row{ + .main_clk = clk, + .main_ia = trunc_hash, + .main_ib = metadata_log_length, + .main_internal_return_ptr = internal_return_ptr, + .main_pc = pc, + }; + kernel_trace_builder.op_emit_unencrypted_log(clk, side_effect_counter, trunc_hash, metadata_log_length); + row.main_sel_op_emit_unencrypted_log = FF(1); + } else { + row = Row{ + .main_clk = clk, + .main_internal_return_ptr = internal_return_ptr, + .main_op_err = FF(1), + .main_pc = pc, + .main_sel_op_emit_unencrypted_log = FF(1), + }; + } // Constrain gas cost gas_trace_builder.constrain_gas(clk, OpCode::EMITUNENCRYPTEDLOG, static_cast(log_size)); @@ -2710,9 +2855,10 @@ void AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, debug("emit_unencrypted_log side-effect cnt: ", side_effect_counter); side_effect_counter++; pc += Deserialization::get_pc_increment(OpCode::EMITUNENCRYPTEDLOG); + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } -void AvmTraceBuilder::op_emit_l2_to_l1_msg(uint8_t indirect, uint32_t recipient_offset, uint32_t content_offset) +AvmError AvmTraceBuilder::op_emit_l2_to_l1_msg(uint8_t indirect, uint32_t recipient_offset, uint32_t content_offset) { auto const clk = static_cast(main_trace.size()) + 1; @@ -2731,6 +2877,7 @@ void AvmTraceBuilder::op_emit_l2_to_l1_msg(uint8_t indirect, uint32_t recipient_ side_effect_counter++; pc += Deserialization::get_pc_increment(OpCode::SENDL2TOL1MSG); + return row.main_tag_err == FF(0) ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /************************************************************************************************** @@ -2738,13 +2885,13 @@ void AvmTraceBuilder::op_emit_l2_to_l1_msg(uint8_t indirect, uint32_t recipient_ **************************************************************************************************/ // Helper/implementation for CALL and STATICCALL -void AvmTraceBuilder::constrain_external_call(OpCode opcode, - uint16_t indirect, - uint32_t gas_offset, - uint32_t addr_offset, - uint32_t args_offset, - uint32_t args_size_offset, - uint32_t success_offset) +AvmError AvmTraceBuilder::constrain_external_call(OpCode opcode, + uint16_t indirect, + uint32_t gas_offset, + uint32_t addr_offset, + uint32_t args_offset, + uint32_t args_size_offset, + uint32_t success_offset) { ASSERT(opcode == OpCode::CALL || opcode == OpCode::STATICCALL); auto clk = static_cast(main_trace.size()) + 1; @@ -2769,8 +2916,10 @@ void AvmTraceBuilder::constrain_external_call(OpCode opcode, call_ptr, clk, resolved_args_offset, AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::ID); bool tag_match = read_gas_l2.tag_match && read_gas_da.tag_match && read_addr.tag_match && read_args.tag_match; + bool op_valid = check_tag(AvmMemoryTag::U32, resolved_args_size_offset); + // TODO: constrain this - auto args_size = static_cast(unconstrained_read_from_memory(resolved_args_size_offset)); + auto args_size = op_valid ? static_cast(unconstrained_read_from_memory(resolved_args_size_offset)) : 0; gas_trace_builder.constrain_gas(clk, opcode, @@ -2792,6 +2941,7 @@ void AvmTraceBuilder::constrain_external_call(OpCode opcode, .main_mem_addr_b = FF(read_gas_l2.direct_address + 1), .main_mem_addr_c = FF(read_addr.direct_address), .main_mem_addr_d = FF(read_args.direct_address), + .main_op_err = FF(static_cast(!op_valid)), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), .main_sel_mem_op_a = FF(1), @@ -2821,6 +2971,7 @@ void AvmTraceBuilder::constrain_external_call(OpCode opcode, if (opcode == OpCode::CALL) { side_effect_counter = static_cast(hint.end_side_effect_counter); } + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /** @@ -2836,12 +2987,12 @@ void AvmTraceBuilder::constrain_external_call(OpCode opcode, * @param success_offset An index in memory pointing to where the success flag (U1) of the external call should be * stored */ -void AvmTraceBuilder::op_call(uint16_t indirect, - uint32_t gas_offset, - uint32_t addr_offset, - uint32_t args_offset, - uint32_t args_size_offset, - uint32_t success_offset) +AvmError AvmTraceBuilder::op_call(uint16_t indirect, + uint32_t gas_offset, + uint32_t addr_offset, + uint32_t args_offset, + uint32_t args_size_offset, + uint32_t success_offset) { return constrain_external_call( OpCode::CALL, indirect, gas_offset, addr_offset, args_offset, args_size_offset, success_offset); @@ -2860,12 +3011,12 @@ void AvmTraceBuilder::op_call(uint16_t indirect, * @param success_offset An index in memory pointing to where the success flag (U8) of the static call should be * stored */ -void AvmTraceBuilder::op_static_call(uint16_t indirect, - uint32_t gas_offset, - uint32_t addr_offset, - uint32_t args_offset, - uint32_t args_size_offset, - uint32_t success_offset) +AvmError AvmTraceBuilder::op_static_call(uint16_t indirect, + uint32_t gas_offset, + uint32_t addr_offset, + uint32_t args_offset, + uint32_t args_size_offset, + uint32_t success_offset) { return constrain_external_call( OpCode::STATICCALL, indirect, gas_offset, addr_offset, args_offset, args_size_offset, success_offset); @@ -2886,9 +3037,20 @@ void AvmTraceBuilder::op_static_call(uint16_t indirect, * @param ret_size The number of elements to be returned. * @return The returned memory region as a std::vector. */ -std::vector AvmTraceBuilder::op_return(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size) +ReturnDataError AvmTraceBuilder::op_return(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size_offset) { auto clk = static_cast(main_trace.size()) + 1; + + // This boolean will not be a trivial constant once we re-enable constraining address resolution + bool tag_match = true; + + // Resolve operands + auto [resolved_ret_offset, resolved_ret_size_offset] = + Addressing<2>::fromWire(indirect, call_ptr).resolve({ ret_offset, ret_size_offset }, mem_trace_builder); + + bool op_valid = tag_match && check_tag(AvmMemoryTag::U32, resolved_ret_size_offset); + const auto ret_size = static_cast(unconstrained_read_from_memory(resolved_ret_size_offset)); + gas_trace_builder.constrain_gas(clk, OpCode::RETURN, ret_size); if (ret_size == 0) { @@ -2897,18 +3059,18 @@ std::vector AvmTraceBuilder::op_return(uint8_t indirect, uint32_t ret_offset .main_call_ptr = call_ptr, .main_ib = ret_size, .main_internal_return_ptr = FF(internal_return_ptr), + .main_op_err = static_cast(!op_valid), .main_pc = pc, .main_sel_op_external_return = 1, }); pc = UINT32_MAX; // This ensures that no subsequent opcode will be executed. - return {}; - } - // This boolean will not be a trivial constant once we re-enable constraining address resolution - bool tag_match = true; - - auto [resolved_ret_offset] = Addressing<1>::fromWire(indirect, call_ptr).resolve({ ret_offset }, mem_trace_builder); + return ReturnDataError{ + .return_data = {}, + .error = op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR, + }; + } // The only memory operation performed from the main trace is a possible indirect load for resolving the // direct destination offset stored in main_mem_addr_c. @@ -2925,6 +3087,7 @@ std::vector AvmTraceBuilder::op_return(uint8_t indirect, uint32_t ret_offset .main_ib = ret_size, .main_internal_return_ptr = FF(internal_return_ptr), .main_mem_addr_c = resolved_ret_offset, + .main_op_err = static_cast(!op_valid), .main_pc = pc, .main_r_in_tag = static_cast(AvmMemoryTag::FF), .main_sel_op_external_return = 1, @@ -2934,10 +3097,14 @@ std::vector AvmTraceBuilder::op_return(uint8_t indirect, uint32_t ret_offset }); pc = UINT32_MAX; // This ensures that no subsequent opcode will be executed. - return returndata; + + return ReturnDataError{ + .return_data = returndata, + .error = op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR, + }; } -std::vector AvmTraceBuilder::op_revert(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size_offset) +ReturnDataError AvmTraceBuilder::op_revert(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size_offset) { // TODO: This opcode is still masquerading as RETURN. auto clk = static_cast(main_trace.size()) + 1; @@ -2947,7 +3114,10 @@ std::vector AvmTraceBuilder::op_revert(uint8_t indirect, uint32_t ret_offset auto [resolved_ret_offset, resolved_ret_size_offset] = Addressing<2>::fromWire(indirect, call_ptr).resolve({ ret_offset, ret_size_offset }, mem_trace_builder); - const auto ret_size = static_cast(unconstrained_read_from_memory(resolved_ret_size_offset)); + + bool op_valid = check_tag(AvmMemoryTag::U32, ret_size_offset); + const auto ret_size = + op_valid ? static_cast(unconstrained_read_from_memory(resolved_ret_size_offset)) : 0; gas_trace_builder.constrain_gas(clk, OpCode::REVERT_8, ret_size); @@ -2958,12 +3128,16 @@ std::vector AvmTraceBuilder::op_revert(uint8_t indirect, uint32_t ret_offset .main_call_ptr = call_ptr, .main_ib = ret_size, .main_internal_return_ptr = FF(internal_return_ptr), + .main_op_err = FF(static_cast(!op_valid)), .main_pc = pc, .main_sel_op_external_return = 1, }); pc = UINT32_MAX; // This ensures that no subsequent opcode will be executed. - return {}; + return ReturnDataError{ + .return_data = {}, + .error = op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR, + }; } // The only memory operation performed from the main trace is a possible indirect load for resolving the @@ -2974,6 +3148,7 @@ std::vector AvmTraceBuilder::op_revert(uint8_t indirect, uint32_t ret_offset slice_trace_builder.create_return_slice(returndata, clk, call_ptr, resolved_ret_offset, ret_size); } + // TODO: fix and set sel_op_revert main_trace.push_back(Row{ .main_clk = clk, .main_call_ptr = call_ptr, @@ -2989,7 +3164,55 @@ std::vector AvmTraceBuilder::op_revert(uint8_t indirect, uint32_t ret_offset }); pc = UINT32_MAX; // This ensures that no subsequent opcode will be executed. - return returndata; + + // op_valid == true otherwise, ret_size == 0 and we would have returned above. + return ReturnDataError{ + .return_data = returndata, + .error = tag_match ? AvmError::NO_ERROR : AvmError::TAG_ERROR, + }; +} + +/************************************************************************************************** + * MISC + **************************************************************************************************/ + +AvmError AvmTraceBuilder::op_debug_log(uint8_t indirect, + uint32_t message_offset, + uint32_t message_size, + uint32_t fields_offset, + uint32_t fields_size_offset) +{ + auto clk = static_cast(main_trace.size()) + 1; + + auto [resolved_message_offset, resolved_fields_offset, resolved_fields_size_offset] = + Addressing<3>::fromWire(indirect, call_ptr) + .resolve({ message_offset, fields_offset, fields_size_offset }, mem_trace_builder); + + // Tags checking + bool op_valid = check_tag(AvmMemoryTag::U32, resolved_fields_size_offset); + + const uint32_t fields_size = + op_valid ? static_cast(unconstrained_read_from_memory(resolved_fields_size_offset)) : 0; + + // Constrain gas cost + gas_trace_builder.constrain_gas(clk, OpCode::DEBUGLOG, message_size + fields_size); + + if (op_valid) { + op_valid = op_valid && check_tag_range(AvmMemoryTag::U8, resolved_message_offset, message_size) && + check_tag_range(AvmMemoryTag::FF, resolved_fields_offset, fields_size); + } + + main_trace.push_back(Row{ + .main_clk = clk, + .main_call_ptr = call_ptr, + .main_internal_return_ptr = FF(internal_return_ptr), + .main_op_err = FF(static_cast(!op_valid)), + .main_pc = FF(pc), + .main_sel_op_debug_log = FF(1), + }); + + pc += Deserialization::get_pc_increment(OpCode::DEBUGLOG); + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /************************************************************************************************** @@ -3005,7 +3228,7 @@ std::vector AvmTraceBuilder::op_revert(uint8_t indirect, uint32_t ret_offset * @param output_offset An index in memory pointing to where the first Field value of the output array should be * stored. */ -void AvmTraceBuilder::op_poseidon2_permutation(uint8_t indirect, uint32_t input_offset, uint32_t output_offset) +AvmError AvmTraceBuilder::op_poseidon2_permutation(uint8_t indirect, uint32_t input_offset, uint32_t output_offset) { auto clk = static_cast(main_trace.size()) + 1; @@ -3020,16 +3243,6 @@ void AvmTraceBuilder::op_poseidon2_permutation(uint8_t indirect, uint32_t input_ // Constrain gas cost gas_trace_builder.constrain_gas(clk, OpCode::POSEIDON2PERM); - // Main trace contains on operand values from the bytecode and resolved indirects - main_trace.push_back(Row{ - .main_clk = clk, - .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = resolved_input_offset, - .main_mem_addr_b = resolved_output_offset, - .main_pc = FF(pc), - .main_sel_op_poseidon2 = FF(1), - }); - // These read patterns will be refactored - we perform them here instead of in the poseidon gadget trace // even though they are "performed" by the gadget. AddressWithMode direct_src_offset = { AddressingMode::DIRECT, resolved_input_offset }; @@ -3063,51 +3276,70 @@ void AvmTraceBuilder::op_poseidon2_permutation(uint8_t indirect, uint32_t input_ IntermRegister::ID, AvmMemTraceBuilder::POSEIDON2); - std::array input = { read_a.val, read_b.val, read_c.val, read_d.val }; - std::array result = poseidon2_trace_builder.poseidon2_permutation( - input, call_ptr, clk, resolved_input_offset, resolved_output_offset); + bool op_valid = read_a.tag_match && read_b.tag_match && read_c.tag_match && read_d.tag_match; - std::vector ff_result; - for (uint32_t i = 0; i < 4; i++) { - ff_result.emplace_back(result[i]); + if (op_valid) { + std::array input = { read_a.val, read_b.val, read_c.val, read_d.val }; + std::array result = poseidon2_trace_builder.poseidon2_permutation( + input, call_ptr, clk, resolved_input_offset, resolved_output_offset); + + std::vector ff_result; + for (uint32_t i = 0; i < 4; i++) { + ff_result.emplace_back(result[i]); + } + // Write the result to memory after, see the comments at read to understand why this happens here. + AddressWithMode direct_dst_offset = { AddressingMode::DIRECT, resolved_output_offset }; + auto write_a = constrained_write_to_memory(call_ptr, + clk, + direct_dst_offset, + ff_result[0], + AvmMemoryTag::FF, + AvmMemoryTag::FF, + IntermRegister::IA, + AvmMemTraceBuilder::POSEIDON2); + auto write_b = constrained_write_to_memory(call_ptr, + clk, + direct_dst_offset + 1, + ff_result[1], + AvmMemoryTag::FF, + AvmMemoryTag::FF, + IntermRegister::IB, + AvmMemTraceBuilder::POSEIDON2); + auto write_c = constrained_write_to_memory(call_ptr, + clk, + direct_dst_offset + 2, + ff_result[2], + AvmMemoryTag::FF, + AvmMemoryTag::FF, + IntermRegister::IC, + AvmMemTraceBuilder::POSEIDON2); + + auto write_d = constrained_write_to_memory(call_ptr, + clk, + direct_dst_offset + 3, + ff_result[3], + AvmMemoryTag::FF, + AvmMemoryTag::FF, + IntermRegister::ID, + AvmMemTraceBuilder::POSEIDON2); + + op_valid = write_a.tag_match && write_b.tag_match && write_c.tag_match && write_d.tag_match; } - // Write the result to memory after, see the comments at read to understand why this happens here. - AddressWithMode direct_dst_offset = { AddressingMode::DIRECT, resolved_output_offset }; - constrained_write_to_memory(call_ptr, - clk, - direct_dst_offset, - ff_result[0], - AvmMemoryTag::FF, - AvmMemoryTag::FF, - IntermRegister::IA, - AvmMemTraceBuilder::POSEIDON2); - constrained_write_to_memory(call_ptr, - clk, - direct_dst_offset + 1, - ff_result[1], - AvmMemoryTag::FF, - AvmMemoryTag::FF, - IntermRegister::IB, - AvmMemTraceBuilder::POSEIDON2); - constrained_write_to_memory(call_ptr, - clk, - direct_dst_offset + 2, - ff_result[2], - AvmMemoryTag::FF, - AvmMemoryTag::FF, - IntermRegister::IC, - AvmMemTraceBuilder::POSEIDON2); - - constrained_write_to_memory(call_ptr, - clk, - direct_dst_offset + 3, - ff_result[3], - AvmMemoryTag::FF, - AvmMemoryTag::FF, - IntermRegister::ID, - AvmMemTraceBuilder::POSEIDON2); + + // Main trace contains on operand values from the bytecode and resolved indirects + main_trace.push_back(Row{ + .main_clk = clk, + .main_internal_return_ptr = FF(internal_return_ptr), + .main_mem_addr_a = resolved_input_offset, + .main_mem_addr_b = resolved_output_offset, + .main_op_err = FF(static_cast(!op_valid)), + .main_pc = FF(pc), + .main_sel_op_poseidon2 = FF(1), + }); pc += Deserialization::get_pc_increment(OpCode::POSEIDON2PERM); + + return op_valid ? AvmError::NO_ERROR : AvmError::TAG_ERROR; } /** @@ -3121,11 +3353,14 @@ void AvmTraceBuilder::op_poseidon2_permutation(uint8_t indirect, uint32_t input_ * @param output_offset An index in memory pointing to where the first U32 value of the output array should be * stored. */ -void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, - uint32_t output_offset, - uint32_t state_offset, - uint32_t inputs_offset) +AvmError AvmTraceBuilder::op_sha256_compression(uint8_t indirect, + uint32_t output_offset, + uint32_t state_offset, + uint32_t inputs_offset) { + const uint32_t STATE_SIZE = 8; + const uint32_t INPUTS_SIZE = 16; + // The clk plays a crucial role in this function as we attempt to write across multiple lines in the main trace. auto clk = static_cast(main_trace.size()) + 1; @@ -3141,6 +3376,9 @@ void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, call_ptr, clk, resolved_inputs_offset, AvmMemoryTag::U32, AvmMemoryTag::FF, IntermRegister::IB); bool tag_match = read_a.tag_match && read_b.tag_match; + bool op_valid = tag_match && check_tag_range(AvmMemoryTag::U32, resolved_state_offset, STATE_SIZE) && + check_tag_range(AvmMemoryTag::U32, resolved_inputs_offset, INPUTS_SIZE); + // Constrain gas cost gas_trace_builder.constrain_gas(clk, OpCode::SHA256COMPRESSION); @@ -3161,6 +3399,7 @@ void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, .main_internal_return_ptr = FF(internal_return_ptr), .main_mem_addr_a = FF(read_a.direct_address), .main_mem_addr_b = FF(read_b.direct_address), + .main_op_err = FF(static_cast(!op_valid)), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(AvmMemoryTag::U32)), .main_sel_mem_op_a = FF(1), @@ -3170,6 +3409,11 @@ void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), }); + + if (!op_valid) { + return AvmError::TAG_ERROR; + } + // We store the current clk this main trace row occurred so that we can line up the sha256 gadget operation at // the same clk later. auto sha_op_clk = clk; @@ -3202,6 +3446,8 @@ void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, // Crucial to perform this operation after having incremented pc because write_slice_to_memory // is implemented with opcodes (SET and JUMP). write_slice_to_memory(resolved_output_offset, AvmMemoryTag::U32, ff_result); + + return AvmError::NO_ERROR; } /** @@ -3212,39 +3458,39 @@ void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, * @param input_offset An index in memory pointing to the first u64 value of the input array to be used in the next * instance of keccakf1600. */ -void AvmTraceBuilder::op_keccakf1600(uint8_t indirect, uint32_t output_offset, uint32_t input_offset) +AvmError AvmTraceBuilder::op_keccakf1600(uint8_t indirect, uint32_t output_offset, uint32_t input_offset) { auto clk = static_cast(main_trace.size()) + 1; auto [resolved_output_offset, resolved_input_offset] = Addressing<2>::fromWire(indirect, call_ptr).resolve({ output_offset, input_offset }, mem_trace_builder); auto input_read = constrained_read_from_memory( call_ptr, clk, resolved_input_offset, AvmMemoryTag::U64, AvmMemoryTag::FF, IntermRegister::IA); - auto output_read = constrained_read_from_memory( - call_ptr, clk, resolved_output_offset, AvmMemoryTag::U64, AvmMemoryTag::FF, IntermRegister::IC); - bool tag_match = input_read.tag_match && output_read.tag_match; + bool tag_match = input_read.tag_match; + + bool op_valid = tag_match && check_tag_range(AvmMemoryTag::U64, resolved_input_offset, KECCAKF1600_INPUT_SIZE); // Constrain gas cost gas_trace_builder.constrain_gas(clk, OpCode::KECCAKF1600); main_trace.push_back(Row{ .main_clk = clk, - .main_ia = input_read.val, // First element of input - .main_ic = output_read.val, // First element of output + .main_ia = input_read.val, // First element of input .main_ind_addr_a = FF(input_read.indirect_address), - .main_ind_addr_c = FF(output_read.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), .main_mem_addr_a = FF(input_read.direct_address), - .main_mem_addr_c = FF(output_read.direct_address), + .main_op_err = FF(static_cast(!op_valid)), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(AvmMemoryTag::U64)), .main_sel_mem_op_a = FF(1), - .main_sel_mem_op_c = FF(1), .main_sel_op_keccak = FF(1), .main_sel_resolve_ind_addr_a = FF(static_cast(input_read.is_indirect)), - .main_sel_resolve_ind_addr_c = FF(static_cast(output_read.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), }); + if (!op_valid) { + return AvmError::TAG_ERROR; + } + // Array input is fixed to 1600 bits std::vector input_vec; // Read results are written to input array @@ -3261,16 +3507,18 @@ void AvmTraceBuilder::op_keccakf1600(uint8_t indirect, uint32_t output_offset, u // Crucial to perform this operation after having incremented pc because write_slice_to_memory // is implemented with opcodes (SET and JUMP). write_slice_to_memory(resolved_output_offset, AvmMemoryTag::U64, result); + + return AvmError::NO_ERROR; } -void AvmTraceBuilder::op_ec_add(uint16_t indirect, - uint32_t lhs_x_offset, - uint32_t lhs_y_offset, - uint32_t lhs_is_inf_offset, - uint32_t rhs_x_offset, - uint32_t rhs_y_offset, - uint32_t rhs_is_inf_offset, - uint32_t output_offset) +AvmError AvmTraceBuilder::op_ec_add(uint16_t indirect, + uint32_t lhs_x_offset, + uint32_t lhs_y_offset, + uint32_t lhs_is_inf_offset, + uint32_t rhs_x_offset, + uint32_t rhs_y_offset, + uint32_t rhs_is_inf_offset, + uint32_t output_offset) { auto clk = static_cast(main_trace.size()) + 1; auto [resolved_lhs_x_offset, @@ -3289,6 +3537,25 @@ void AvmTraceBuilder::op_ec_add(uint16_t indirect, output_offset }, mem_trace_builder); + // Tag checking + bool op_valid = + check_tag(AvmMemoryTag::FF, resolved_lhs_x_offset) && check_tag(AvmMemoryTag::FF, resolved_lhs_y_offset) && + check_tag(AvmMemoryTag::U1, resolved_lhs_is_inf_offset) && check_tag(AvmMemoryTag::FF, resolved_rhs_x_offset) && + check_tag(AvmMemoryTag::FF, resolved_rhs_y_offset) && check_tag(AvmMemoryTag::U1, resolved_rhs_is_inf_offset); + + gas_trace_builder.constrain_gas(clk, OpCode::ECADD); + + if (!op_valid) { + main_trace.push_back(Row{ + .main_clk = clk, + .main_internal_return_ptr = FF(internal_return_ptr), + .main_op_err = FF(1), + .main_pc = FF(pc), + .main_sel_op_ecadd = 1, + }); + return AvmError::TAG_ERROR; + } + // Load lhs point auto lhs_x_read = unconstrained_read_from_memory(resolved_lhs_x_offset); auto lhs_y_read = unconstrained_read_from_memory(resolved_lhs_y_offset); @@ -3315,8 +3582,6 @@ void AvmTraceBuilder::op_ec_add(uint16_t indirect, .main_tag_err = FF(0), }); - gas_trace_builder.constrain_gas(clk, OpCode::ECADD); - pc += Deserialization::get_pc_increment(OpCode::ECADD); // Crucial to perform this operation after having incremented pc because write_slice_to_memory @@ -3324,29 +3589,58 @@ void AvmTraceBuilder::op_ec_add(uint16_t indirect, // Write point coordinates write_to_memory(resolved_output_offset, result.x, AvmMemoryTag::FF); write_to_memory(resolved_output_offset + 1, result.y, AvmMemoryTag::FF); - write_to_memory(resolved_output_offset + 2, result.is_point_at_infinity(), AvmMemoryTag::U8); + write_to_memory(resolved_output_offset + 2, result.is_point_at_infinity(), AvmMemoryTag::U1); + + return AvmError::NO_ERROR; } -void AvmTraceBuilder::op_variable_msm(uint8_t indirect, - uint32_t points_offset, - uint32_t scalars_offset, - uint32_t output_offset, - uint32_t point_length_offset) +AvmError AvmTraceBuilder::op_variable_msm(uint8_t indirect, + uint32_t points_offset, + uint32_t scalars_offset, + uint32_t output_offset, + uint32_t point_length_offset) { auto clk = static_cast(main_trace.size()) + 1; auto [resolved_points_offset, resolved_scalars_offset, resolved_output_offset, resolved_point_length_offset] = Addressing<4>::fromWire(indirect, call_ptr) .resolve({ points_offset, scalars_offset, output_offset, point_length_offset }, mem_trace_builder); - auto points_length = unconstrained_read_from_memory(resolved_point_length_offset); + bool op_valid = check_tag(AvmMemoryTag::U32, resolved_point_length_offset); + const FF points_length = op_valid ? unconstrained_read_from_memory(resolved_point_length_offset) : 0; // Points are stored as [x1, y1, inf1, x2, y2, inf2, ...] with the types [FF, FF, U8, FF, FF, U8, ...] - uint32_t num_points = uint32_t(points_length) / 3; // 3 elements per point + const uint32_t num_points = uint32_t(points_length) / 3; // 3 elements per point // We need to split up the reads due to the memory tags, std::vector points_coords_vec; std::vector points_inf_vec; std::vector scalars_vec; + for (uint32_t i = 0; i < num_points; i++) { + op_valid = op_valid && check_tag_range(AvmMemoryTag::FF, resolved_points_offset + 3 * i, 2) && + check_tag(AvmMemoryTag::U1, resolved_points_offset + 3 * i + 2); + } + + // Scalar read length is num_points* 2 since scalars are stored as lo and hi limbs + uint32_t scalar_read_length = num_points * 2; + + op_valid = op_valid && check_tag_range(AvmMemoryTag::FF, resolved_scalars_offset, scalar_read_length); + + // TODO(dbanks12): length needs to fit into u32 here or it will certainly + // run out of gas. Casting/truncating here is not secure. + gas_trace_builder.constrain_gas(clk, OpCode::MSM, static_cast(points_length)); + + if (!op_valid) { + main_trace.push_back(Row{ + .main_clk = clk, + .main_internal_return_ptr = FF(internal_return_ptr), + .main_op_err = FF(static_cast(!op_valid)), + .main_pc = FF(pc), + .main_sel_op_msm = 1, + }); + + return AvmError::TAG_ERROR; + } + // Loading the points is a bit more complex since we need to read the coordinates and the infinity flags // separately The current circuit constraints does not allow for multiple memory tags to be loaded from within // the same row. If we could we would be able to replace the following loops with a single read_slice_to_memory @@ -3361,8 +3655,7 @@ void AvmTraceBuilder::op_variable_msm(uint8_t indirect, points_coords_vec.insert(points_coords_vec.end(), { point_x1, point_y1 }); points_inf_vec.emplace_back(infty); } - // Scalar read length is num_points* 2 since scalars are stored as lo and hi limbs - uint32_t scalar_read_length = num_points * 2; + // Scalars are easy to read since they are stored as [lo1, hi1, lo2, hi2, ...] with the types [FF, FF, FF,FF, // ...] read_slice_from_memory(resolved_scalars_offset, scalar_read_length, scalars_vec); @@ -3400,10 +3693,6 @@ void AvmTraceBuilder::op_variable_msm(uint8_t indirect, .main_tag_err = FF(0), }); - // TODO(dbanks12): length needs to fit into u32 here or it will certainly - // run out of gas. Casting/truncating here is not secure. - gas_trace_builder.constrain_gas(clk, OpCode::MSM, static_cast(points_length)); - pc += Deserialization::get_pc_increment(OpCode::MSM); // Crucial to perform this operation after having incremented pc because write_slice_to_memory @@ -3411,7 +3700,9 @@ void AvmTraceBuilder::op_variable_msm(uint8_t indirect, // Write the result back to memory [x, y, inf] with tags [FF, FF, U8] write_to_memory(resolved_output_offset, result.x, AvmMemoryTag::FF); write_to_memory(resolved_output_offset + 1, result.y, AvmMemoryTag::FF); - write_to_memory(resolved_output_offset + 2, result.is_point_at_infinity(), AvmMemoryTag::U8); + write_to_memory(resolved_output_offset + 2, result.is_point_at_infinity(), AvmMemoryTag::U1); + + return AvmError::NO_ERROR; } /************************************************************************************************** @@ -3424,17 +3715,17 @@ void AvmTraceBuilder::op_variable_msm(uint8_t indirect, * @param indirect A byte encoding information about indirect/direct memory access. * @param src_offset An index in memory pointing to the input of the To_Radix_BE conversion. * @param dst_offset An index in memory pointing to the output of the To_Radix_BE conversion. - * @param radix_offset An index in memory pointing to the strict upper bound of each converted limb, i.e., 0 <= limb < - * radix. + * @param radix_offset An index in memory pointing to the strict upper bound of each converted limb, i.e., 0 <= limb + * < radix. * @param num_limbs The number of limbs to the value into. * @param output_bits Should the output be U1s instead of U8s? */ -void AvmTraceBuilder::op_to_radix_be(uint8_t indirect, - uint32_t src_offset, - uint32_t dst_offset, - uint32_t radix_offset, - uint32_t num_limbs, - uint8_t output_bits) +AvmError AvmTraceBuilder::op_to_radix_be(uint8_t indirect, + uint32_t src_offset, + uint32_t dst_offset, + uint32_t radix_offset, + uint32_t num_limbs, + uint8_t output_bits) { auto clk = static_cast(main_trace.size()) + 1; @@ -3446,12 +3737,18 @@ void AvmTraceBuilder::op_to_radix_be(uint8_t indirect, Addressing<3>::fromWire(indirect, call_ptr) .resolve({ src_offset, dst_offset, radix_offset }, mem_trace_builder); + // Constrain gas cost + gas_trace_builder.constrain_gas(clk, OpCode::TORADIXBE, num_limbs); + auto read_src = constrained_read_from_memory( call_ptr, clk, resolved_src_offset, AvmMemoryTag::FF, w_in_tag, IntermRegister::IA); // TODO(8603): once instructions can have multiple different tags for reads, constrain the radix's read // TODO(9497): if simulator fails tag check here, witgen will not. Raise error flag! // auto read_radix = constrained_read_from_memory( // call_ptr, clk, resolved_radix_offset, AvmMemoryTag::U32, AvmMemoryTag::U32, IntermRegister::IB); + + bool op_valid = check_tag(AvmMemoryTag::U32, resolved_radix_offset); + auto read_radix = unconstrained_read_from_memory(resolved_radix_offset); FF input = read_src.val; @@ -3460,7 +3757,7 @@ void AvmTraceBuilder::op_to_radix_be(uint8_t indirect, uint32_t radix = static_cast(read_radix); bool radix_out_of_bounds = radix > 256; - bool error = radix_out_of_bounds || !read_src.tag_match; // || !read_radix.tag_match; + bool error = !op_valid || radix_out_of_bounds || !read_src.tag_match; // || !read_radix.tag_match; // In case of an error, we do not perform the computation. // Therefore, we do not create any entry in gadget table and we return a vector of 0. @@ -3468,9 +3765,6 @@ void AvmTraceBuilder::op_to_radix_be(uint8_t indirect, ? std::vector(num_limbs, 0) : conversion_trace_builder.op_to_radix_be(input, radix, num_limbs, output_bits, clk); - // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::TORADIXBE, num_limbs); - // This is the row that contains the selector to trigger the sel_op_radix_be // In this row, we read the input value and the destination address into register A and B respectively main_trace.push_back(Row{ @@ -3487,7 +3781,7 @@ void AvmTraceBuilder::op_to_radix_be(uint8_t indirect, .main_mem_addr_a = read_src.direct_address, // TODO(8603): uncomment //.main_mem_addr_b = read_radix.direct_address, - .main_op_err = error ? FF(1) : FF(0), + .main_op_err = FF(static_cast(error)), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), .main_sel_mem_op_a = FF(1), @@ -3505,6 +3799,7 @@ void AvmTraceBuilder::op_to_radix_be(uint8_t indirect, // Crucial to perform this operation after having incremented pc because write_slice_to_memory // is implemented with opcodes (SET and JUMP). write_slice_to_memory(resolved_dst_offset, w_in_tag, res); + return error ? AvmError::TAG_ERROR : AvmError::NO_ERROR; } /************************************************************************************************** @@ -3607,7 +3902,7 @@ std::vector AvmTraceBuilder::finalize() dest.incl_mem_tag_err_counts = FF(static_cast(src.m_tag_err_count_relevant)); - // TODO: Should be a cleaner way to do this in the future. Perhaps an "into_canoncal" function in + // TODO: Should be a cleaner way to do this in the future. Perhaps an "into_canonical" function in // mem_trace_builder if (!src.m_sel_op_slice) { switch (src.m_sub_clk) { @@ -3775,16 +4070,6 @@ std::vector AvmTraceBuilder::finalize() **********************************************************************************************/ gas_trace_builder.finalize(main_trace); - // We need to assert here instead of finalize until we figure out inter-trace threading - for (size_t i = 0; i < main_trace_size; i++) { - auto& row = main_trace.at(i); - if (row.main_is_gas_accounted) { - range_check_builder.assert_range( - uint128_t(row.main_abs_l2_rem_gas), 32, EventEmitter::GAS_L2, uint64_t(row.main_clk)); - range_check_builder.assert_range( - uint128_t(row.main_abs_da_rem_gas), 32, EventEmitter::GAS_DA, uint64_t(row.main_clk)); - } - } /********************************************************************************************** * KERNEL TRACE INCLUSION @@ -3839,17 +4124,22 @@ std::vector AvmTraceBuilder::finalize() auto new_trace_size = range_check_required ? old_trace_size - : finalize_rng_chks_for_testing(main_trace, alu_trace_builder, mem_trace_builder, range_check_builder); + : finalize_rng_chks_for_testing( + main_trace, alu_trace_builder, mem_trace_builder, range_check_builder, gas_trace_builder); for (size_t i = 0; i < new_trace_size; i++) { auto& r = main_trace.at(i); + if (r.main_tag_err == FF(1)) { + r.main_op_err = FF(1); // Consolidation of errors into main_op_err + } + if ((r.main_sel_op_add == FF(1) || r.main_sel_op_sub == FF(1) || r.main_sel_op_mul == FF(1) || r.main_sel_op_eq == FF(1) || r.main_sel_op_not == FF(1) || r.main_sel_op_lt == FF(1) || r.main_sel_op_lte == FF(1) || r.main_sel_op_cast == FF(1) || r.main_sel_op_shr == FF(1) || r.main_sel_op_shl == FF(1) || r.main_sel_op_div == FF(1)) && - r.main_tag_err == FF(0) && r.main_op_err == FF(0)) { - r.main_sel_alu = FF(1); + r.main_op_err == FF(0)) { + r.main_sel_alu = FF(1); // From error consolidation, this is set only if tag_err == 0. } if (r.main_sel_op_internal_call == FF(1) || r.main_sel_op_internal_return == FF(1)) { @@ -3888,6 +4178,10 @@ std::vector AvmTraceBuilder::finalize() r.lookup_rng_chk_diff_counts = range_check_builder.dyn_diff_counts[uint16_t(counter)]; r.lookup_mem_rng_chk_0_counts = mem_trace_builder.mem_rng_chk_u16_0_counts[uint16_t(counter)]; r.lookup_mem_rng_chk_1_counts = mem_trace_builder.mem_rng_chk_u16_1_counts[uint16_t(counter)]; + r.lookup_l2_gas_rng_chk_0_counts = gas_trace_builder.rem_gas_rng_check_counts[0][uint16_t(counter)]; + r.lookup_l2_gas_rng_chk_1_counts = gas_trace_builder.rem_gas_rng_check_counts[1][uint16_t(counter)]; + r.lookup_da_gas_rng_chk_0_counts = gas_trace_builder.rem_gas_rng_check_counts[2][uint16_t(counter)]; + r.lookup_da_gas_rng_chk_1_counts = gas_trace_builder.rem_gas_rng_check_counts[3][uint16_t(counter)]; r.main_sel_rng_16 = FF(1); } } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp index 76a7162ecb0..cfe330881df 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp @@ -23,6 +23,11 @@ namespace bb::avm_trace { using Row = bb::AvmFullRow; +struct ReturnDataError { + std::vector return_data; + AvmError error; +}; + // This is the internal context that we keep along the lifecycle of bytecode execution // to iteratively build the whole trace. This is effectively performing witness generation. // At the end of circuit building, mainTrace can be moved to AvmCircuitBuilder by calling @@ -40,47 +45,47 @@ class AvmTraceBuilder { uint32_t get_da_gas_left() const { return gas_trace_builder.get_da_gas_left(); } // Compute - Arithmetic - void op_add( + AvmError op_add( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code = OpCode::ADD_16); - void op_sub( + AvmError op_sub( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code = OpCode::SUB_16); - void op_mul( + AvmError op_mul( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code = OpCode::MUL_16); - void op_div( + AvmError op_div( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code = OpCode::DIV_16); - void op_fdiv( + AvmError op_fdiv( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code = OpCode::FDIV_16); // Compute - Comparators - void op_eq( + AvmError op_eq( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code = OpCode::EQ_16); - void op_lt( + AvmError op_lt( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code = OpCode::LT_16); - void op_lte( + AvmError op_lte( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code = OpCode::LTE_16); // Compute - Bitwise - void op_and( + AvmError op_and( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code = OpCode::AND_16); - void op_or( + AvmError op_or( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code = OpCode::OR_16); - void op_xor( + AvmError op_xor( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code = OpCode::XOR_16); - void op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, OpCode op_code = OpCode::NOT_16); - void op_shl( + AvmError op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, OpCode op_code = OpCode::NOT_16); + AvmError op_shl( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code = OpCode::SHL_16); - void op_shr( + AvmError op_shr( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, OpCode op_code = OpCode::SHR_16); // Compute - Type Conversions - void op_cast(uint8_t indirect, - uint32_t a_offset, - uint32_t dst_offset, - AvmMemoryTag dst_tag, - OpCode op_code = OpCode::CAST_16); + AvmError op_cast(uint8_t indirect, + uint32_t a_offset, + uint32_t dst_offset, + AvmMemoryTag dst_tag, + OpCode op_code = OpCode::CAST_16); // Execution Environment - void op_get_env_var(uint8_t indirect, uint8_t env_var, uint32_t dst_offset); + AvmError op_get_env_var(uint8_t indirect, uint8_t env_var, uint32_t dst_offset); void op_address(uint8_t indirect, uint32_t dst_offset); void op_sender(uint8_t indirect, uint32_t dst_offset); void op_function_selector(uint8_t indirect, uint32_t dst_offset); @@ -96,12 +101,15 @@ class AvmTraceBuilder { void op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset); // Execution Environment - Calldata - void op_calldata_copy(uint8_t indirect, uint32_t cd_offset_address, uint32_t copy_size_offset, uint32_t dst_offset); - void op_returndata_size(uint8_t indirect, uint32_t dst_offset); - void op_returndata_copy(uint8_t indirect, - uint32_t rd_offset_address, - uint32_t copy_size_offset, - uint32_t dst_offset); + AvmError op_calldata_copy(uint8_t indirect, + uint32_t cd_offset_address, + uint32_t copy_size_offset, + uint32_t dst_offset); + AvmError op_returndata_size(uint8_t indirect, uint32_t dst_offset); + AvmError op_returndata_copy(uint8_t indirect, + uint32_t rd_offset_address, + uint32_t copy_size_offset, + uint32_t dst_offset); // Machine State - Gas void op_l2gasleft(uint8_t indirect, uint32_t dst_offset); @@ -109,89 +117,97 @@ class AvmTraceBuilder { // Machine State - Internal Control Flow // TODO(8945): skip_gas boolean is temporary and should be removed once all fake rows are removed - void op_jump(uint32_t jmp_dest, bool skip_gas = false); - void op_jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t cond_offset); - // TODO(md): this program counter MUST be an operand to the OPCODE. - void op_internal_call(uint32_t jmp_dest); - void op_internal_return(); + AvmError op_jump(uint32_t jmp_dest, bool skip_gas = false); + AvmError op_jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t cond_offset); + AvmError op_internal_call(uint32_t jmp_dest); + AvmError op_internal_return(); // Machine State - Memory // TODO(8945): skip_gas boolean is temporary and should be removed once all fake rows are removed - void op_set(uint8_t indirect, - FF val, - uint32_t dst_offset, - AvmMemoryTag in_tag, - OpCode op_code = OpCode::SET_FF, - bool skip_gas = false); - void op_mov(uint8_t indirect, uint32_t src_offset, uint32_t dst_offset, OpCode op_code = OpCode::MOV_16); + AvmError op_set(uint8_t indirect, + FF val, + uint32_t dst_offset, + AvmMemoryTag in_tag, + OpCode op_code = OpCode::SET_FF, + bool skip_gas = false); + AvmError op_mov(uint8_t indirect, uint32_t src_offset, uint32_t dst_offset, OpCode op_code = OpCode::MOV_16); // World State - void op_sload(uint8_t indirect, uint32_t slot_offset, uint32_t size, uint32_t dest_offset); - void op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t size, uint32_t slot_offset); - void op_note_hash_exists(uint8_t indirect, - uint32_t note_hash_offset, - uint32_t leaf_index_offset, - uint32_t dest_offset); - void op_emit_note_hash(uint8_t indirect, uint32_t note_hash_offset); - void op_nullifier_exists(uint8_t indirect, - uint32_t nullifier_offset, - uint32_t address_offset, - uint32_t dest_offset); - void op_emit_nullifier(uint8_t indirect, uint32_t nullifier_offset); - void op_l1_to_l2_msg_exists(uint8_t indirect, - uint32_t log_offset, - uint32_t leaf_index_offset, - uint32_t dest_offset); - void op_get_contract_instance( + AvmError op_sload(uint8_t indirect, uint32_t slot_offset, uint32_t size, uint32_t dest_offset); + AvmError op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t size, uint32_t slot_offset); + AvmError op_note_hash_exists(uint8_t indirect, + uint32_t note_hash_offset, + uint32_t leaf_index_offset, + uint32_t dest_offset); + AvmError op_emit_note_hash(uint8_t indirect, uint32_t note_hash_offset); + AvmError op_nullifier_exists(uint8_t indirect, + uint32_t nullifier_offset, + uint32_t address_offset, + uint32_t dest_offset); + AvmError op_emit_nullifier(uint8_t indirect, uint32_t nullifier_offset); + AvmError op_l1_to_l2_msg_exists(uint8_t indirect, + uint32_t log_offset, + uint32_t leaf_index_offset, + uint32_t dest_offset); + AvmError op_get_contract_instance( uint8_t indirect, uint8_t member_enum, uint16_t address_offset, uint16_t dst_offset, uint16_t exists_offset); // Accrued Substate - void op_emit_unencrypted_log(uint8_t indirect, uint32_t log_offset, uint32_t log_size_offset); - void op_emit_l2_to_l1_msg(uint8_t indirect, uint32_t recipient_offset, uint32_t content_offset); + AvmError op_emit_unencrypted_log(uint8_t indirect, uint32_t log_offset, uint32_t log_size_offset); + AvmError op_emit_l2_to_l1_msg(uint8_t indirect, uint32_t recipient_offset, uint32_t content_offset); // Control Flow - Contract Calls - void op_call(uint16_t indirect, - uint32_t gas_offset, - uint32_t addr_offset, - uint32_t args_offset, - uint32_t args_size, - uint32_t success_offset); - void op_static_call(uint16_t indirect, - uint32_t gas_offset, - uint32_t addr_offset, - uint32_t args_offset, - uint32_t args_size, - uint32_t success_offset); - std::vector op_return(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size); + AvmError op_call(uint16_t indirect, + uint32_t gas_offset, + uint32_t addr_offset, + uint32_t args_offset, + uint32_t args_size, + uint32_t success_offset); + AvmError op_static_call(uint16_t indirect, + uint32_t gas_offset, + uint32_t addr_offset, + uint32_t args_offset, + uint32_t args_size, + uint32_t success_offset); + ReturnDataError op_return(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size_offset); // REVERT Opcode (that just call return under the hood for now) - std::vector op_revert(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size_offset); + ReturnDataError op_revert(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size_offset); + + // Misc + AvmError op_debug_log(uint8_t indirect, + uint32_t message_offset, + uint32_t message_size, + uint32_t fields_offset, + uint32_t fields_size_offset); // Gadgets - void op_poseidon2_permutation(uint8_t indirect, uint32_t input_offset, uint32_t output_offset); - void op_ec_add(uint16_t indirect, - uint32_t lhs_x_offset, - uint32_t lhs_y_offset, - uint32_t lhs_is_inf_offset, - uint32_t rhs_x_offset, - uint32_t rhs_y_offset, - uint32_t rhs_is_inf_offset, - uint32_t output_offset); - void op_variable_msm(uint8_t indirect, - uint32_t points_offset, - uint32_t scalars_offset, - uint32_t output_offset, - uint32_t point_length_offset); + AvmError op_poseidon2_permutation(uint8_t indirect, uint32_t input_offset, uint32_t output_offset); + AvmError op_sha256_compression(uint8_t indirect, + uint32_t output_offset, + uint32_t state_offset, + uint32_t inputs_offset); + AvmError op_keccakf1600(uint8_t indirect, uint32_t output_offset, uint32_t input_offset); + + AvmError op_ec_add(uint16_t indirect, + uint32_t lhs_x_offset, + uint32_t lhs_y_offset, + uint32_t lhs_is_inf_offset, + uint32_t rhs_x_offset, + uint32_t rhs_y_offset, + uint32_t rhs_is_inf_offset, + uint32_t output_offset); + AvmError op_variable_msm(uint8_t indirect, + uint32_t points_offset, + uint32_t scalars_offset, + uint32_t output_offset, + uint32_t point_length_offset); // Conversions - void op_to_radix_be(uint8_t indirect, - uint32_t src_offset, - uint32_t dst_offset, - uint32_t radix_offset, - uint32_t num_limbs, - uint8_t output_bits); - - // Future Gadgets -- pending changes in noir - void op_sha256_compression(uint8_t indirect, uint32_t output_offset, uint32_t state_offset, uint32_t inputs_offset); - void op_keccakf1600(uint8_t indirect, uint32_t output_offset, uint32_t input_offset); + AvmError op_to_radix_be(uint8_t indirect, + uint32_t src_offset, + uint32_t dst_offset, + uint32_t radix_offset, + uint32_t num_limbs, + uint8_t output_bits); std::vector finalize(); void reset(); @@ -260,8 +276,10 @@ class AvmTraceBuilder { uint32_t metadata_offset, AvmMemoryTag metadata_r_tag); - Row create_kernel_output_opcode_with_set_metadata_output_from_hint( - uint8_t indirect, uint32_t clk, uint32_t data_offset, uint32_t address_offset, uint32_t metadata_offset); + Row create_kernel_output_opcode_with_set_metadata_output_from_hint(uint32_t clk, + uint32_t data_offset, + uint32_t address_offset, + uint32_t metadata_offset); Row create_kernel_output_opcode_for_leaf_index(uint32_t clk, uint32_t data_offset, @@ -273,13 +291,13 @@ class AvmTraceBuilder { uint32_t data_offset, uint32_t metadata_offset); - void constrain_external_call(OpCode opcode, - uint16_t indirect, - uint32_t gas_offset, - uint32_t addr_offset, - uint32_t args_offset, - uint32_t args_size_offset, - uint32_t success_offset); + AvmError constrain_external_call(OpCode opcode, + uint16_t indirect, + uint32_t gas_offset, + uint32_t addr_offset, + uint32_t args_offset, + uint32_t args_size_offset, + uint32_t success_offset); void execute_gasleft(EnvironmentVariable var, uint8_t indirect, uint32_t dst_offset); @@ -308,6 +326,8 @@ class AvmTraceBuilder { // TODO: remove these once everything is constrained. AvmMemoryTag unconstrained_get_memory_tag(AddressWithMode addr); + bool check_tag(AvmMemoryTag tag, AddressWithMode addr); + bool check_tag_range(AvmMemoryTag tag, AddressWithMode start_offset, uint32_t size); FF unconstrained_read_from_memory(AddressWithMode addr); template void read_slice_from_memory(AddressWithMode addr, size_t slice_len, std::vector& slice); void write_to_memory(AddressWithMode addr, FF val, AvmMemoryTag w_tag); diff --git a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp index c1a003ea75b..52df3243076 100644 --- a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp @@ -36,8 +36,9 @@ #define PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH 866 #define PUBLIC_CONTEXT_INPUTS_LENGTH 41 #define AVM_ACCUMULATED_DATA_LENGTH 318 +#define AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH 1006 #define AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS 86 -#define AVM_PROOF_LENGTH_IN_FIELDS 4211 +#define AVM_PROOF_LENGTH_IN_FIELDS 4291 #define AVM_PUBLIC_COLUMN_MAX_SIZE 1024 #define AVM_PUBLIC_INPUTS_FLATTENED_SIZE 2914 #define MEM_TAG_FF 0 @@ -112,6 +113,7 @@ #define AVM_RETURN_BASE_L2_GAS 28 #define AVM_REVERT_BASE_L2_GAS 28 #define AVM_DEBUGLOG_BASE_L2_GAS 12 +#define AVM_DEBUGLOG_DYN_L2_GAS 3 #define AVM_POSEIDON2_BASE_L2_GAS 78 #define AVM_SHA256COMPRESSION_BASE_L2_GAS 261 #define AVM_KECCAKF1600_BASE_L2_GAS 300 diff --git a/barretenberg/ts/src/barretenberg/backend.ts b/barretenberg/ts/src/barretenberg/backend.ts index 4d8e89116b3..db292c1a926 100644 --- a/barretenberg/ts/src/barretenberg/backend.ts +++ b/barretenberg/ts/src/barretenberg/backend.ts @@ -125,12 +125,20 @@ export class UltraPlonkBackend { return await this.api.acirVerifyProof(this.acirComposer, proof); } + /** @description Returns the verification key */ async getVerificationKey(): Promise { await this.instantiate(); await this.api.acirInitVerificationKey(this.acirComposer); return await this.api.acirGetVerificationKey(this.acirComposer); } + /** @description Returns a solidity verifier */ + async getSolidityVerifier(): Promise { + await this.instantiate(); + await this.api.acirInitVerificationKey(this.acirComposer); + return await this.api.acirGetSolidityVerifier(this.acirComposer); + } + async destroy(): Promise { if (!this.api) { return; @@ -218,6 +226,13 @@ export class UltraHonkBackend { return await this.api.acirWriteVkUltraHonk(this.acirUncompressedBytecode, this.circuitOptions.recursive); } + /** @description Returns a solidity verifier */ + async getSolidityVerifier(): Promise { + await this.instantiate(); + await this.api.acirWriteVkUltraHonk(this.acirUncompressedBytecode, this.circuitOptions.recursive); + return await this.api.getHonkSolidityVerifier(this.acirUncompressedBytecode, this.circuitOptions.recursive); + } + // TODO(https://github.com/noir-lang/noir/issues/5661): Update this to handle Honk recursive aggregation in the browser once it is ready in the backend itself async generateRecursiveProofArtifacts( // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/barretenberg/ts/src/barretenberg_api/index.ts b/barretenberg/ts/src/barretenberg_api/index.ts index 4d95dfa1887..202239039dc 100644 --- a/barretenberg/ts/src/barretenberg_api/index.ts +++ b/barretenberg/ts/src/barretenberg_api/index.ts @@ -593,6 +593,18 @@ export class BarretenbergApi { return out[0]; } + async getHonkSolidityVerifier(acirVec: Uint8Array, recursive: boolean): Promise { + const inArgs = [acirVec, recursive].map(serializeBufferable); + const outTypes: OutputType[] = [BufferDeserializer()]; + const result = await this.wasm.callWasmExport( + 'get_honk_solidity_verifier_vk', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return out[0]; + } + async acirProofAsFieldsUltraHonk(proofBuf: Uint8Array): Promise { const inArgs = [proofBuf].map(serializeBufferable); const outTypes: OutputType[] = [VectorDeserializer(Fr)]; diff --git a/docs/docs/guides/developer_guides/getting_started.md b/docs/docs/guides/developer_guides/getting_started.md index f665739c8d9..ce015ba29db 100644 --- a/docs/docs/guides/developer_guides/getting_started.md +++ b/docs/docs/guides/developer_guides/getting_started.md @@ -139,12 +139,12 @@ In the next step, let's mint some tokens! Call the public mint function like this: ```bash -aztec-wallet send mint_public --from accounts:my-wallet --contract-address contracts:testtoken --args accounts:my-wallet 100 +aztec-wallet send mint_to_public --from accounts:my-wallet --contract-address contracts:testtoken --args accounts:my-wallet 100 ``` This takes -- the function name as the argument, which is `mint_public` +- the function name as the argument, which is `mint_to_public` - the `from` account (caller) which is `accounts:my-wallet` - the contract address, which is aliased as `contracts:testtoken` (or simply `testtoken`) - the args that the function takes, which is the account to mint the tokens into (`my-wallet`), and `amount` (`100`). @@ -165,7 +165,7 @@ Transaction has been mined Status: success Block number: 17 Block hash: 1e27d200600bc45ab94d467c230490808d1e7d64f5ee6cee5e94a08ee9580809 -Transaction hash stored in database with aliases last & mint_public-9044 +Transaction hash stored in database with aliases last & mint_to_public-9044 ``` You can double-check by calling the function that checks your public account balance: diff --git a/docs/docs/guides/developer_guides/js_apps/authwit.md b/docs/docs/guides/developer_guides/js_apps/authwit.md index d4db5d8c5cd..92dd49dc677 100644 --- a/docs/docs/guides/developer_guides/js_apps/authwit.md +++ b/docs/docs/guides/developer_guides/js_apps/authwit.md @@ -68,9 +68,9 @@ Then create the message hash by hashing the inner hash with the authwit receiver ## Create the authwit -There are slightly different interfaces depending on whether your contract is checking the authwit in private or public. +There are slightly different interfaces depending on whether your contract is checking the authwit in private or public. -Public authwits are stored in the account contract and batched with the authwit action call, so a user must send a transaction to update their account contract, authorizing an action before the authorized contract's public call will succeed. +Public authwits are stored in the account contract and batched with the authwit action call, so a user must send a transaction to update their account contract, authorizing an action before the authorized contract's public call will succeed. Private execution uses oracles and are executed locally by the PXE, so the authwit needs to be created by the authwit giver and then added to the authwit receiver's PXE. @@ -107,7 +107,7 @@ Set a public authwit like this: Remember it is a transaction and calls a method in the account contract. In this example, - `wallets[0]` is the authwit giver -- `wallets[1]` is the authwit reciever and caller of the function +- `wallets[1]` is the authwit receiver and caller of the function - `action` was [defined previously](#define-the-action) - `true` sets the `authorized` boolean (`false` would revoke this authwit) diff --git a/docs/docs/guides/developer_guides/smart_contracts/how_to_compile_contract.md b/docs/docs/guides/developer_guides/smart_contracts/how_to_compile_contract.md index c356ddb1544..902230fa304 100644 --- a/docs/docs/guides/developer_guides/smart_contracts/how_to_compile_contract.md +++ b/docs/docs/guides/developer_guides/smart_contracts/how_to_compile_contract.md @@ -199,8 +199,8 @@ export class TokenContract extends ContractBase { /** Type-safe wrappers for the public methods exposed by the contract. */ public override methods!: { - /** transfer_public(from: struct, to: struct, amount: field, nonce: field) */ - transfer_public: (( + /** transfer_in_public(from: struct, to: struct, amount: field, nonce: field) */ + transfer_in_public: (( from: AztecAddressLike, to: AztecAddressLike, amount: FieldLike, diff --git a/docs/docs/guides/developer_guides/smart_contracts/testing_contracts/testing.md b/docs/docs/guides/developer_guides/smart_contracts/testing_contracts/testing.md index 2449195013b..86d470de664 100644 --- a/docs/docs/guides/developer_guides/smart_contracts/testing_contracts/testing.md +++ b/docs/docs/guides/developer_guides/smart_contracts/testing_contracts/testing.md @@ -118,13 +118,13 @@ Our test environment is capable of utilizing the autogenerated contract interfac For example, to call the private `transfer` function on the token contract: -#include_code txe_test_transfer_private /noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_private.nr rust +#include_code txe_test_transfer_private /noir-projects/noir-contracts/contracts/token_contract/src/test/transfer.nr rust #### Public -To call the public `transfer_public` function: +To call the public `transfer_in_public` function: -#include_code call_public /noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_public.nr rust +#include_code call_public /noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_in_public.nr rust #### Unconstrained @@ -178,11 +178,11 @@ Reading notes: You can add [authwits](../writing_contracts/authwit.md) to the TXE. Here is an example of testing a private token transfer using authwits: -#include_code private_authwit /noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_private.nr rust +#include_code private_authwit /noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_in_private.nr rust #### Public -#include_code public_authwit /noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_public.nr rust +#include_code public_authwit /noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_in_public.nr rust ### Storing notes in cache @@ -206,7 +206,7 @@ You can test functions that you expect to fail generically, with the `#[test(sho For example: -#include_code fail_with_message /noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_private.nr rust +#include_code fail_with_message /noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_in_private.nr rust You can also use the `assert_public_call_fails` or `assert_private_call_fails` methods on the `TestEnvironment` to check that a call fails. diff --git a/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/authwit.md b/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/authwit.md index fb288b5ef3d..ac40dbc36c0 100644 --- a/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/authwit.md +++ b/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/authwit.md @@ -141,7 +141,7 @@ Then you will be able to import it into your contracts as follows. Based on the diagram earlier on this page let's take a look at how we can implement the `transfer` function such that it checks if the tokens are to be transferred `from` the caller or needs to be authenticated with an authentication witness. -#include_code transfer_from /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust +#include_code transfer_in_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust The first thing we see in the snippet above, is that if `from` is not the call we are calling the `assert_current_call_valid_authwit` function from [earlier](#private-functions). If the call is not throwing, we are all good and can continue with the transfer. @@ -151,7 +151,7 @@ In the snippet we are constraining the `else` case such that only `nonce = 0` is Cool, so we have a function that checks if the current call is authenticated, but how do we actually authenticate it? Well, assuming that we use a wallet that is following the spec, we import `computeAuthWitMessageHash` from `aztec.js` to help us compute the hash, and then we simply `addAuthWitness` to the wallet. Behind the scenes this will make the witness available to the oracle. -#include_code authwit_transfer_example /yarn-project/end-to-end/src/e2e_token_contract/transfer_private.test.ts typescript +#include_code authwit_transfer_example /yarn-project/end-to-end/src/e2e_token_contract/transfer_in_private.test.ts typescript Learn more about authwits in Aztec.js by [following this guide](../../js_apps/authwit.md). @@ -161,7 +161,7 @@ With private functions covered, how can we use this in a public function? Well, #### Checking if the current call is authenticated -#include_code transfer_public /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust +#include_code transfer_in_public /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust #### Authenticating an action in TypeScript @@ -169,7 +169,7 @@ Authenticating an action in the public domain is slightly different from the pri In the snippet below, this is done as a separate contract call, but can also be done as part of a batch as mentioned in the [Accounts concepts](../../../../aztec/concepts/accounts/authwit.md#what-about-public). -#include_code authwit_public_transfer_example /yarn-project/end-to-end/src/e2e_token_contract/transfer_public.test.ts typescript +#include_code authwit_public_transfer_example /yarn-project/end-to-end/src/e2e_token_contract/transfer_in_public.test.ts typescript #### Updating approval state in Noir diff --git a/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/common_patterns/index.md b/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/common_patterns/index.md index 848fffa0e1f..0e601ef307b 100644 --- a/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/common_patterns/index.md +++ b/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/common_patterns/index.md @@ -21,7 +21,7 @@ We call this the "authentication witness" pattern or authwit for short. Here you approve a contract to burn funds on your behalf. - Approve in public domain: - #include_code authwit_public_transfer_example /yarn-project/end-to-end/src/e2e_token_contract/transfer_public.test.ts typescript + #include_code authwit_public_transfer_example /yarn-project/end-to-end/src/e2e_token_contract/transfer_in_public.test.ts typescript Here you approve someone to transfer funds publicly on your behalf @@ -84,8 +84,6 @@ Let's say you have some storage in public and want to move them into the private So you have to create a custom note in the public domain that is not encrypted by some owner - we call such notes a "TransparentNote" since it is created in public, anyone can see the amount and the note is not encrypted by some owner. -This pattern is discussed in detail in [the codealong token tutorial in the shield() method](../../../../../tutorials/codealong/contract_tutorials/token_contract.md#redeem_shield). - ### Discovering my notes When you send someone a note, the note hash gets added to the note hash tree. To spend the note, the receiver needs to get the note itself (the note hash preimage). There are two ways you can get a hold of your notes: diff --git a/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/portals/communicate_with_portal.md b/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/portals/communicate_with_portal.md index 8c497e3f41c..d08078b0aec 100644 --- a/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/portals/communicate_with_portal.md +++ b/docs/docs/guides/developer_guides/smart_contracts/writing_contracts/portals/communicate_with_portal.md @@ -53,7 +53,7 @@ The `content_hash` is a sha256 truncated to a field element (~ 254 bits). In Azt ### Token portal hash library -#include_code mint_public_content_hash_nr /noir-projects/noir-contracts/contracts/token_portal_content_hash_lib/src/lib.nr rust +#include_code mint_to_public_content_hash_nr /noir-projects/noir-contracts/contracts/token_portal_content_hash_lib/src/lib.nr rust ### Token Portal contract diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index 4e44286b40c..9a7adc06ad1 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -6,6 +6,21 @@ keywords: [sandbox, aztec, notes, migration, updating, upgrading] Aztec is in full-speed development. Literally every version breaks compatibility with the previous ones. This page attempts to target errors and difficulties you might encounter when upgrading, and how to resolve them. +## 0.63.0 +### [Token contract] Partial notes related refactor +We've decided to replace the old "shield" flow with one leveraging partial notes. +This led to a removal of `shield` and `redeem_shield` functions and an introduction of `transfer_to_private`. +An advantage of the new approach is that only 1 tx is required and the API of partial notes is generally nicer. +For more information on partial notes refer to docs. + +### [Token contract] Function naming changes +There have been a few naming changes done for improved consistency. +These are the renamings: +`transfer_public` --> `transfer_in_public` +`transfer_from` --> `transfer_in_private` +`mint_public` --> `mint_to_public` +`burn` --> `burn_private` + ## 0.62.0 ### [TXE] Single execution environment Thanks to recent advancements in Brillig TXE performs every single call as if it was a nested call, spawning a new ACVM or AVM simulator without performance loss. diff --git a/docs/docs/reference/developer_references/sandbox_reference/cli_wallet_reference.md b/docs/docs/reference/developer_references/sandbox_reference/cli_wallet_reference.md index 593415d21d9..12a837c227a 100644 --- a/docs/docs/reference/developer_references/sandbox_reference/cli_wallet_reference.md +++ b/docs/docs/reference/developer_references/sandbox_reference/cli_wallet_reference.md @@ -104,10 +104,10 @@ The authwit management in private is a two-step process: create and add. It's no #### Example -An example for authorizing an operator (ex. a DeFi protocol) to call the transfer_from action (transfer on the user's behalf): +An example for authorizing an operator (ex. a DeFi protocol) to call the transfer_in_private action (transfer on the user's behalf): ```bash -aztec-wallet create-authwit transfer_from accounts:coruscant_trader -ca contracts:token --args accounts:jedi_master accounts:coruscant_trader 20 secrets:auth_nonce -f accounts:jedi_master -a secret_trade +aztec-wallet create-authwit transfer_in_private accounts:coruscant_trader -ca contracts:token --args accounts:jedi_master accounts:coruscant_trader 20 secrets:auth_nonce -f accounts:jedi_master -a secret_trade aztec-wallet add-authwit authwits:secret_trade accounts:jedi_master -f accounts:coruscant_trader ``` @@ -117,7 +117,7 @@ aztec-wallet add-authwit authwits:secret_trade accounts:jedi_master -f accounts: A similar call to the above, but in public: ```bash -aztec-wallet authorize-action transfer_public accounts:coruscant_trader -ca contracts:token --args accounts:jedi_master accounts:coruscant_trader 20 secrets:auth_nonce -f accounts:jedi_master +aztec-wallet authorize-action transfer_in_public accounts:coruscant_trader -ca contracts:token --args accounts:jedi_master accounts:coruscant_trader 20 secrets:auth_nonce -f accounts:jedi_master ``` ### Simulate diff --git a/docs/docs/reference/developer_references/smart_contract_reference/storage/private_state.md b/docs/docs/reference/developer_references/smart_contract_reference/storage/private_state.md index dfd7d5530ef..cfe794984f6 100644 --- a/docs/docs/reference/developer_references/smart_contract_reference/storage/private_state.md +++ b/docs/docs/reference/developer_references/smart_contract_reference/storage/private_state.md @@ -210,8 +210,6 @@ The `insert_from_public` allow public function to insert notes into private stor The usage is similar to using the `insert` method with the difference that this one is called in public functions. -#include_code insert_from_public /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust - ### `pop_notes` This function pops (gets, removes and returns) the notes the account has access to based on the provided filter. diff --git a/docs/docs/tutorials/codealong/aztecjs-getting-started.md b/docs/docs/tutorials/codealong/aztecjs-getting-started.md index e0f03f62b9b..72168fc5da5 100644 --- a/docs/docs/tutorials/codealong/aztecjs-getting-started.md +++ b/docs/docs/tutorials/codealong/aztecjs-getting-started.md @@ -283,7 +283,7 @@ Our output should now look like this: Here, we used the same contract abstraction as was previously used for reading Alice's balance. But this time we called `send()` generating and sending a transaction to the network. After waiting for the transaction to settle we were able to check the new balance values. Finally, the contract has 2 `mint` functions that can be used to generate new tokens for an account. -We will focus only on `mint_private`. +We will focus only on `mint_to_private`. This function is public but it mints tokens privately. This function takes: diff --git a/docs/docs/tutorials/codealong/cli_wallet/faceid_wallet.md b/docs/docs/tutorials/codealong/cli_wallet/faceid_wallet.md index 73d04e960b9..fc9b89d6b24 100644 --- a/docs/docs/tutorials/codealong/cli_wallet/faceid_wallet.md +++ b/docs/docs/tutorials/codealong/cli_wallet/faceid_wallet.md @@ -103,9 +103,9 @@ You should get a prompt to sign this transaction. You can now mint, transfer, an ```bash aztec-wallet create-account -a new_recipient # creating a schnorr account -aztec-wallet send mint_public -ca last --args accounts:my-wallet 10 -f accounts:my-wallet # minting some tokens in public +aztec-wallet send mint_to_public -ca last --args accounts:my-wallet 10 -f accounts:my-wallet # minting some tokens in public aztec-wallet simulate balance_of_public -ca contracts:devtoken --args accounts:my-wallet -f my-wallet # checking that my-wallet has 10 tokens -aztec-wallet send transfer_public -ca contracts:devtoken --args accounts:my-wallet accounts:new_recipient 10 0 -f accounts:my-wallet # transferring some tokens in public +aztec-wallet send transfer_in_public -ca contracts:devtoken --args accounts:my-wallet accounts:new_recipient 10 0 -f accounts:my-wallet # transferring some tokens in public aztec-wallet simulate balance_of_public -ca contracts:devtoken --args accounts:new_recipient -f my-wallet # checking that new_recipient has 10 tokens ``` diff --git a/docs/docs/tutorials/codealong/contract_tutorials/advanced/token_bridge/1_depositing_to_aztec.md b/docs/docs/tutorials/codealong/contract_tutorials/advanced/token_bridge/1_depositing_to_aztec.md index 0d7632cc1bc..cb426b2ef98 100644 --- a/docs/docs/tutorials/codealong/contract_tutorials/advanced/token_bridge/1_depositing_to_aztec.md +++ b/docs/docs/tutorials/codealong/contract_tutorials/advanced/token_bridge/1_depositing_to_aztec.md @@ -57,7 +57,7 @@ Here is an explanation of what it is doing: - The content is limited to a single field (~254 bits). So if the content is larger, we have to hash it and the hash can be passed along. - We use our utility method that creates a sha256 hash but truncates it to fit into a field - Since we want to mint tokens on Aztec publicly, the content here is the amount to mint and the address on Aztec who will receive the tokens. - - We encode this message as a mint_public function call, to specify the exact intentions and parameters we want to execute on L2. + - We encode this message as a mint_to_public function call, to specify the exact intentions and parameters we want to execute on L2. - In reality the content can be constructed in any manner as long as the sister contract on L2 can also create it. But for clarity, we are constructing the content like an ABI encoded function call. - It is good practice to include all parameters used by L2 into this content (like the amount and to) so that a malicious actor can’t change the to to themselves when consuming the message. 3. The tokens are transferred from the user to the portal using `underlying.safeTransferFrom()`. This puts the funds under the portal's control. @@ -78,8 +78,7 @@ Let’s do the similar for the private flow: Here we want to send a message to mint tokens privately on Aztec! Some key differences from the previous method are: -- The content hash uses a different function name - `mint_private`. This is done to make it easy to separate concerns. If the contentHash between the public and private message was the same, then an attacker could consume a private message publicly! -- Since we want to mint tokens privately, we shouldn’t specify a `to` Aztec address (remember that Ethereum is completely public). Instead, we will use a secret hash - `secretHashForRedeemingMintedNotes`. Only he who knows the preimage to the secret hash can actually mint the notes. This is similar to the mechanism we use for message consumption on L2 +- The content hash uses a different function name - `mint_to_private`. This is done to make it easy to separate concerns. If the contentHash between the public and private message was the same, then an attacker could consume a private message publicly! - Like with the public flow, we move the user’s funds to the portal - We now send the message to the inbox with the `recipient` (the sister contract on L2 along with the version of aztec the message is intended for) and the `secretHashForL2MessageConsumption` (such that on L2, the consumption of the message can be private). diff --git a/docs/docs/tutorials/codealong/contract_tutorials/advanced/token_bridge/2_minting_on_aztec.md b/docs/docs/tutorials/codealong/contract_tutorials/advanced/token_bridge/2_minting_on_aztec.md index 7316793ec39..8effc323e74 100644 --- a/docs/docs/tutorials/codealong/contract_tutorials/advanced/token_bridge/2_minting_on_aztec.md +++ b/docs/docs/tutorials/codealong/contract_tutorials/advanced/token_bridge/2_minting_on_aztec.md @@ -28,15 +28,15 @@ The `claim_public` function enables anyone to consume the message on the user's **What’s happening here?** -1. We first recompute the L1->L2 message content by calling `get_mint_public_content_hash()`. Note that the method does exactly the same as what the TokenPortal contract does in `depositToAztecPublic()` to create the content hash. +1. We first recompute the L1->L2 message content by calling `get_mint_to_public_content_hash()`. Note that the method does exactly the same as what the TokenPortal contract does in `depositToAztecPublic()` to create the content hash. 2. We then attempt to consume the L1->L2 message. Since we are depositing to Aztec publicly, all of the inputs are public. - `context.consume_l1_to_l2_message()` takes in the few parameters: - - `content_hash`: The content - which is reconstructed in the `get_mint_public_content_hash()` + - `content_hash`: The content - which is reconstructed in the `get_mint_to_public_content_hash()` - `secret`: The secret used for consumption, often 0 for public messages - `sender`: Who on L1 sent the message. Which should match the stored `portal_address` in our case as we only want to allow messages from a specific sender. - `message_leaf_index`: The index in the message tree of the message. - Note that the `content_hash` requires `to` and `amount`. If a malicious user tries to mint tokens to their address by changing the to address, the content hash will be different to what the token portal had calculated on L1 and thus not be in the tree, failing the consumption. This is why we add these parameters into the content. -3. Then we call `Token::at(storage.token.read()).mint_public()` to mint the tokens to the to address. +3. Then we call `Token::at(storage.token.read()).mint_to_public()` to mint the tokens to the to address. ## Private flow @@ -46,12 +46,12 @@ Now we will create a function to mint the amount privately. Paste this into your #include_code call_mint_on_token /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr rust -The `get_mint_private_content_hash` function is imported from the `token_portal_content_hash_lib`. +The `get_mint_to_private_content_hash` function is imported from the `token_portal_content_hash_lib`. -If the content hashes were constructed similarly for `mint_private` and `mint_publicly`, then content intended for private execution could have been consumed by calling the `claim_public` method. By making these two content hashes distinct, we prevent this scenario. +If the content hashes were constructed similarly for `mint_to_private` and `mint_to_public`, then content intended for private execution could have been consumed by calling the `claim_public` method. By making these two content hashes distinct, we prevent this scenario. While we mint the tokens on L2, we _still don’t actually mint them to a certain address_. Instead we continue to pass the `secret_hash_for_redeeming_minted_notes` like we did on L1. This means that a user could reveal their secret for L2 message consumption for anyone to mint tokens on L2 but they can redeem these notes at a later time. **This enables a paradigm where an app can manage user’s secrets for L2 message consumption on their behalf**. **The app or any external party can also mint tokens on the user’s behalf should they be comfortable with leaking the secret for L2 Message consumption.** This doesn’t leak any new information to the app because their smart contract on L1 knew that a user wanted to move some amount of tokens to L2. The app still doesn’t know which address on L2 the user wants these notes to be in, but they can mint tokens nevertheless on their behalf. -To mint tokens privately, `claim_private` calls an internal function `_call_mint_on_token()` which then calls [token.mint_private()](../../token_contract.md#mint_private). +To mint tokens privately, `claim_private` calls an internal function `_call_mint_on_token()` which then calls [token.mint_to_private()](../../token_contract.md#mint_to_private). In the next step we will see how we can cancel a message. diff --git a/docs/docs/tutorials/codealong/contract_tutorials/token_contract.md b/docs/docs/tutorials/codealong/contract_tutorials/token_contract.md index c9b9410d416..c94c39534e7 100644 --- a/docs/docs/tutorials/codealong/contract_tutorials/token_contract.md +++ b/docs/docs/tutorials/codealong/contract_tutorials/token_contract.md @@ -67,20 +67,18 @@ These are functions that have transparent logic, will execute in a publicly veri - `set_admin` enables the admin to be updated - `set_minter` enables accounts to be added / removed from the approved minter list -- `mint_public` enables tokens to be minted to the public balance of an account -- `mint_private` enables tokens to be minted to the private balance of an account (with some caveats we will dig into) -- `shield` enables tokens to be moved from a public balance to a private balance, not necessarily the same account (step 1 of a 2 step process) -- `transfer_public` enables users to transfer tokens from one account's public balance to another account's public balance +- `mint_to_public` enables tokens to be minted to the public balance of an account +- `mint_to_private` enables tokens to be minted to the private balance of an account (with some caveats we will dig into) +- `transfer_to_public` enables tokens to be moved from a public balance to a private balance, not necessarily the same account (step 1 of a 2 step process) +- `transfer_in_public` enables users to transfer tokens from one account's public balance to another account's public balance - `burn_public` enables users to burn tokens ### Private functions These are functions that have private logic and will be executed on user devices to maintain privacy. The only data that is submitted to the network is a proof of correct execution, new data commitments and nullifiers, so users will not reveal which contract they are interacting with or which function they are executing. The only information that will be revealed publicly is that someone executed a private transaction on Aztec. -- `redeem_shield` enables accounts to claim tokens that have been made private via `mint_private` or `shield` by providing the secret -- `transfer_to_public` enables an account to send tokens from their private balance to any other account's public balance - `transfer` enables an account to send tokens from their private balance to another account's private balance -- `transfer_from` enables an account to send tokens from another account's private balance to another account's private balance +- `transfer_in_private` enables an account to send tokens from another account's private balance to another account's private balance - `cancel_authwit` enables an account to cancel an authorization to spend tokens - `burn` enables tokens to be burned privately @@ -160,7 +158,6 @@ Reading through the storage variables: - `minters` is a mapping of Aztec addresses in public state. This will store whether an account is an approved minter on the contract. - `balances` is a mapping of private balances. Private balances are stored in a `PrivateSet` of `UintNote`s. The balance is the sum of all of an account's `UintNote`s. - `total_supply` is an unsigned integer (max 128 bit value) stored in public state and represents the total number of tokens minted. -- `pending_shields` is a `PrivateSet` of `TransparentNote`s stored in private state. What is stored publicly is a set of commitments to `TransparentNote`s. - `public_balances` is a mapping of Aztec addresses in public state and represents the publicly viewable balances of accounts. - `symbol`, `name`, and `decimals` are similar in meaning to ERC20 tokens on Ethereum. @@ -178,7 +175,7 @@ This function sets the creator of the contract (passed as `msg_sender` from the Public functions are declared with the `#[public]` macro above the function name. -As described in the [execution contexts section above](#execution-contexts), public function logic and transaction information is transparent to the world. Public functions update public state, but can be used to prepare data to be used in a private context, as we will go over below (e.g. see the [shield](#shield) function). +As described in the [execution contexts section above](#execution-contexts), public function logic and transaction information is transparent to the world. Public functions update public state, but can be used to finalize prepared in a private context (partial notes flow). Storage is referenced as `storage.variable`. @@ -194,27 +191,33 @@ This function allows the `admin` to add or a remove a `minter` from the public ` #include_code set_minter /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust -#### `mint_public` +#### `mint_to_public` This function allows an account approved in the public `minters` mapping to create new public tokens owned by the provided `to` address. First, storage is initialized. Then the function checks that the `msg_sender` is approved to mint in the `minters` mapping. If it is, a new `U128` value is created of the `amount` provided. The function reads the recipients public balance and then adds the amount to mint, saving the output as `new_balance`, then reads to total supply and adds the amount to mint, saving the output as `supply`. `new_balance` and `supply` are then written to storage. -#include_code mint_public /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust +#include_code mint_to_public /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust -#### `mint_private` +#### `mint_to_private` -This public function allows an account approved in the public `minters` mapping to create new private tokens that can be claimed by anyone that has the pre-image to the `secret_hash`. +This public function allows an account approved in the public `minters` mapping to create new private tokens. -First, public storage is initialized. Then it checks that the `msg_sender` is an approved minter. Then a new `TransparentNote` is created with the specified `amount` and `secret_hash`. You can read the details of the `TransparentNote` in the `types.nr` file [here (GitHub link)](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/noir-contracts/contracts/token_contract/src/types.nr#L61). The `amount` is added to the existing public `total_supply` and the storage value is updated. Then the new `TransparentNote` is added to the `pending_shields` using the `insert_from_public` function, which is accessible on the `PrivateSet` type. Then it's ready to be claimed by anyone with the `secret_hash` pre-image using the `redeem_shield` function. +First, partial note is prepared by the call to `_prepare_private_balance_increase` for the minted tokens recipient. Then a public call to `_finalize_mint_to_private_unsafe` is enqueued while `msg_sender`, `amount` and the `hiding_point_slot` are passed in via arguments. Since we set `from` to `msg_sender` here the usage of the unsafe function is safe. The enqueued call then checks the minter permissions of `from` and it finalizes the partial note for `to`. -#include_code mint_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust +#include_code mint_to_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust -#### `shield` +#### `transfer_to_private` -This public function enables an account to stage tokens from it's `public_balance` to be claimed as a private `TransparentNote` by any account that has the pre-image to the `secret_hash`. +This public function enables an account to send tokens from its `public_balance` to a private balance of an arbitrary recipient. -First, storage is initialized. Then it checks whether the calling contract (`context.msg_sender`) matches the account that the funds will be debited from. +First a partial note is prepared then a call to `_finalize_transfer_to_private_unsafe` is enqueued. The enqueued public call subtracts the `amount` from public balance of `msg_sender` and finalizes the partial note with the `amount`. + +#include_code transfer_to_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust + +#### `transfer_in_public` + +This public function enables public transfers between Aztec accounts. The sender's public balance will be debited the specified `amount` and the recipient's public balances will be credited with that amount. ##### Authorizing token spends @@ -224,15 +227,7 @@ If the `msg_sender` is the same as the account to debit tokens from, the authori It returns `1` to indicate successful execution. -#include_code shield /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust - -#### `transfer_public` - -This public function enables public transfers between Aztec accounts. The sender's public balance will be debited the specified `amount` and the recipient's public balances will be credited with that amount. - -After storage is initialized, the [authorization flow specified above](#authorizing-token-spends) is checked. Then the sender and recipient's balances are updated and saved to storage. - -#include_code transfer_public /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust +#include_code transfer_in_public /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust #### `burn_public` @@ -248,26 +243,16 @@ Private functions are declared with the `#[private]` macro above the function na ```rust #[private] - fn redeem_shield( + fn transfer_to_public( ``` As described in the [execution contexts section above](#execution-contexts), private function logic and transaction information is hidden from the world and is executed on user devices. Private functions update private state, but can pass data to the public execution context (e.g. see the [`transfer_to_public`](#transfer_to_public) function). Storage is referenced as `storage.variable`. -#### `redeem_shield` - -This private function enables an account to move tokens from a `TransparentNote` in the `pending_shields` mapping to a `UintNote` in private `balances`. The `UintNote` will be associated with a nullifier key, so any account that knows this key can spend this note. - -Going through the function logic, first the `secret_hash` is generated from the given secret. This ensures that only the entity possessing the secret can use it to redeem the note. Following this, a `TransparentNote` is retrieved from the set, using the provided amount and secret. The note is subsequently removed from the set, allowing it to be redeemed only once. The recipient's private balance is then increased using the `increment` helper function from the `value_note` [library (GitHub link)](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/value-note/src/utils.nr). - -The function returns `1` to indicate successful execution. - -#include_code redeem_shield /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust - #### `transfer_to_public` -This private function enables un-shielding of private `UintNote`s stored in `balances` to any Aztec account's `public_balance`. +This private function enables transferring of private balance (`UintNote` stored in `balances`) to any Aztec account's `public_balance`. After initializing storage, the function checks that the `msg_sender` is authorized to spend tokens. See [the Authorizing token spends section](#authorizing-token-spends) above for more detail--the only difference being that `assert_valid_message_for` is modified to work specifically in the private context. After the authorization check, the sender's private balance is decreased using the `decrement` helper function for the `value_note` library. Then it stages a public function call on this contract ([`_increase_public_balance`](#_increase_public_balance)) to be executed in the [public execution phase](#execution-contexts) of transaction execution. `_increase_public_balance` is marked as an `internal` function, so can only be called by this token contract. @@ -283,19 +268,19 @@ After initializing storage, the function checks that the `msg_sender` is authori #include_code transfer /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust -#### `transfer_from` +#### `transfer_in_private` This private function enables an account to transfer tokens on behalf of another account. The account that tokens are being debited from must have authorized the `msg_sender` to spend tokens on its behalf. -#include_code transfer_from /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust +#include_code transfer_in_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust -#### `burn` +#### `burn_private` This private function enables accounts to privately burn (destroy) tokens. After initializing storage, the function checks that the `msg_sender` is authorized to spend tokens. Then it gets the sender's current balance and decrements it. Finally it stages a public function call to [`_reduce_total_supply`](#_reduce_total_supply). -#include_code burn /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust +#include_code burn_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust ### Internal function implementations @@ -303,7 +288,7 @@ Internal functions are functions that can only be called by this contract. The f #### `_increase_public_balance` -This function is called from [`transfer_to_public`](#transfer_to_public). The account's private balance is decremented in `shield` and the public balance is increased in this function. +This function is called from [`transfer_to_public`](#transfer_to_public). The account's private balance is decremented in `transfer_to_public` and the public balance is increased in this function. #include_code increase_public_balance /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust diff --git a/docs/docs/tutorials/examples/uniswap/l2_contract.md b/docs/docs/tutorials/examples/uniswap/l2_contract.md index b8f9101e7a1..f1f31104325 100644 --- a/docs/docs/tutorials/examples/uniswap/l2_contract.md +++ b/docs/docs/tutorials/examples/uniswap/l2_contract.md @@ -47,7 +47,7 @@ This uses a util function `compute_swap_private_content_hash()` - find that [her This flow works similarly to the public flow with a few notable changes: - Notice how in the `swap_private()`, user has to pass in `token` address which they didn't in the public flow? Since `swap_private()` is a private method, it can't read what token is publicly stored on the token bridge, so instead the user passes a token address, and `_assert_token_is_same()` checks that this user provided address is same as the one in storage. Note that because public functions are executed by the sequencer while private methods are executed locally, all public calls are always done after all private calls are done. So first the burn would happen and only later the sequencer asserts that the token is same. Note that the sequencer just sees a request to `execute_assert_token_is_same` and therefore has no context on what the appropriate private method was. If the assertion fails, then the kernel circuit will fail to create a proof and hence the transaction will be dropped. -- In the public flow, the user calls `transfer_public()`. Here instead, the user calls `transfer_to_public()`. Why? The user can't directly transfer their private tokens (their notes) to the uniswap contract, because later the Uniswap contract has to approve the bridge to burn these notes and withdraw to L1. The authwit flow for the private domain requires a signature from the `sender`, which in this case would be the Uniswap contract. For the contract to sign, it would need a private key associated to it. But who would operate this key? +- In the public flow, the user calls `transfer_in_public()`. Here instead, the user calls `transfer_to_public()`. Why? The user can't directly transfer their private tokens (their notes) to the uniswap contract, because later the Uniswap contract has to approve the bridge to burn these notes and withdraw to L1. The authwit flow for the private domain requires a signature from the `sender`, which in this case would be the Uniswap contract. For the contract to sign, it would need a private key associated to it. But who would operate this key? - To work around this, the user can transfer to public their private tokens into Uniswap L2 contract. Transferring to public would convert user's private notes to public balance. It is a private method on the token contract that reduces a user’s private balance and then calls a public method to increase the recipient’s (ie Uniswap) public balance. **Remember that first all private methods are executed and then later all public methods will be - so the Uniswap contract won’t have the funds until public execution begins.** - Now uniswap has public balance (like with the public flow). Hence, `swap_private()` calls the internal public method which approves the input token bridge to burn Uniswap’s tokens and calls `exit_to_l1_public` to create an L2 → L1 message to exit to L1. - Constructing the message content for swapping works exactly as the public flow except instead of specifying who would be the Aztec address that receives the swapped funds, we specify a secret hash (`secret_hash_for_redeeming_minted_notes`). Only those who know the preimage to the secret can later redeem the minted notes to themselves. diff --git a/l1-contracts/foundry.toml b/l1-contracts/foundry.toml index dbf806aecb9..5a630c1ae5f 100644 --- a/l1-contracts/foundry.toml +++ b/l1-contracts/foundry.toml @@ -17,6 +17,7 @@ fs_permissions = [ {access = "read", path = "./test/fixtures/mixed_block_2.json"}, {access = "read", path = "./test/fixtures/empty_block_1.json"}, {access = "read", path = "./test/fixtures/empty_block_2.json"}, + {access = "read", path = "./test/fixtures/fee_data_points.json"} ] [fmt] diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index ba1a1e96261..2f9ba8e4d62 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -31,6 +31,7 @@ library Constants { uint256 internal constant MAX_NOTE_ENCRYPTED_LOGS_PER_CALL = 16; uint256 internal constant MAX_ENCRYPTED_LOGS_PER_CALL = 4; uint256 internal constant MAX_UNENCRYPTED_LOGS_PER_CALL = 4; + uint256 internal constant MAX_CONTRACT_CLASS_LOGS_PER_CALL = 1; uint256 internal constant ARCHIVE_HEIGHT = 29; uint256 internal constant VK_TREE_HEIGHT = 6; uint256 internal constant PROTOCOL_CONTRACT_TREE_HEIGHT = 3; @@ -70,6 +71,7 @@ library Constants { uint256 internal constant MAX_NOTE_ENCRYPTED_LOGS_PER_TX = 64; uint256 internal constant MAX_ENCRYPTED_LOGS_PER_TX = 8; uint256 internal constant MAX_UNENCRYPTED_LOGS_PER_TX = 8; + uint256 internal constant MAX_CONTRACT_CLASS_LOGS_PER_TX = 1; uint256 internal constant MAX_PUBLIC_DATA_HINTS = 128; uint256 internal constant NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP = 16; uint256 internal constant EMPTY_NESTED_INDEX = 0; @@ -97,7 +99,7 @@ library Constants { uint256 internal constant AZTEC_MAX_EPOCH_DURATION = 32; uint256 internal constant GENESIS_ARCHIVE_ROOT = 19007378675971183768036762391356802220352606103602592933942074152320327194720; - uint256 internal constant FEE_JUICE_INITIAL_MINT = 20000000000; + uint256 internal constant FEE_JUICE_INITIAL_MINT = 200000000000000; uint256 internal constant PUBLIC_DISPATCH_SELECTOR = 3578010381; uint256 internal constant MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 3000; uint256 internal constant MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS = 3000; @@ -116,7 +118,6 @@ library Constants { uint256 internal constant DEFAULT_TEARDOWN_GAS_LIMIT = 12000000; uint256 internal constant MAX_L2_GAS_PER_ENQUEUED_CALL = 12000000; uint256 internal constant DEFAULT_MAX_FEE_PER_GAS = 10; - uint256 internal constant DEFAULT_INCLUSION_FEE = 0; uint256 internal constant DA_BYTES_PER_FIELD = 32; uint256 internal constant DA_GAS_PER_BYTE = 16; uint256 internal constant FIXED_DA_GAS = 512; @@ -160,7 +161,7 @@ library Constants { uint256 internal constant AZTEC_ADDRESS_LENGTH = 1; uint256 internal constant GAS_FEES_LENGTH = 2; uint256 internal constant GAS_LENGTH = 2; - uint256 internal constant GAS_SETTINGS_LENGTH = 7; + uint256 internal constant GAS_SETTINGS_LENGTH = 6; uint256 internal constant CALL_CONTEXT_LENGTH = 4; uint256 internal constant CONTENT_COMMITMENT_LENGTH = 4; uint256 internal constant CONTRACT_INSTANCE_LENGTH = 16; @@ -199,13 +200,13 @@ library Constants { uint256 internal constant ROLLUP_VALIDATION_REQUESTS_LENGTH = 2; uint256 internal constant STATE_REFERENCE_LENGTH = 8; uint256 internal constant TREE_SNAPSHOTS_LENGTH = 8; - uint256 internal constant TX_CONTEXT_LENGTH = 9; - uint256 internal constant TX_REQUEST_LENGTH = 13; + uint256 internal constant TX_CONTEXT_LENGTH = 8; + uint256 internal constant TX_REQUEST_LENGTH = 12; uint256 internal constant TOTAL_FEES_LENGTH = 1; uint256 internal constant HEADER_LENGTH = 24; - uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 500; + uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 490; uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 866; - uint256 internal constant PRIVATE_CONTEXT_INPUTS_LENGTH = 38; + uint256 internal constant PRIVATE_CONTEXT_INPUTS_LENGTH = 37; uint256 internal constant PUBLIC_CONTEXT_INPUTS_LENGTH = 41; uint256 internal constant FEE_RECIPIENT_LENGTH = 2; uint256 internal constant AGGREGATION_OBJECT_LENGTH = 16; @@ -215,20 +216,20 @@ library Constants { uint256 internal constant NUM_PUBLIC_VALIDATION_REQUEST_ARRAYS = 5; uint256 internal constant PUBLIC_VALIDATION_REQUESTS_LENGTH = 834; uint256 internal constant PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; - uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = 547; - uint256 internal constant TX_CONSTANT_DATA_LENGTH = 35; - uint256 internal constant COMBINED_CONSTANT_DATA_LENGTH = 44; - uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = 1064; - uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1878; + uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = 550; + uint256 internal constant TX_CONSTANT_DATA_LENGTH = 34; + uint256 internal constant COMBINED_CONSTANT_DATA_LENGTH = 43; + uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = 1036; + uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1849; uint256 internal constant PUBLIC_ACCUMULATED_DATA_LENGTH = 1023; uint256 internal constant NUM_PUBLIC_ACCUMULATED_DATA_ARRAYS = 8; - uint256 internal constant PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH = 578; + uint256 internal constant PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH = 548; uint256 internal constant PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH = 160; uint256 internal constant NUM_PRIVATE_TO_AVM_ACCUMULATED_DATA_ARRAYS = 3; - uint256 internal constant PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1199; - uint256 internal constant PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2932; - uint256 internal constant VM_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2341; - uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 601; + uint256 internal constant PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1140; + uint256 internal constant PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2931; + uint256 internal constant VM_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2340; + uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 605; uint256 internal constant CONSTANT_ROLLUP_DATA_LENGTH = 13; uint256 internal constant BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 30; uint256 internal constant BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 90; diff --git a/l1-contracts/src/core/libraries/Errors.sol b/l1-contracts/src/core/libraries/Errors.sol index 6e8454bfe33..a53b8c10f62 100644 --- a/l1-contracts/src/core/libraries/Errors.sol +++ b/l1-contracts/src/core/libraries/Errors.sol @@ -109,4 +109,8 @@ library Errors { error ProofCommitmentEscrow__InsufficientBalance(uint256 balance, uint256 requested); // 0x09b8b789 error ProofCommitmentEscrow__NotOwner(address caller); // 0x2ac332c1 error ProofCommitmentEscrow__WithdrawRequestNotReady(uint256 current, Timestamp readyAt); // 0xb32ab8a7 + + // FeeMath + error FeeMath__InvalidProvingCostModifier(); // 0x8b9d62ac + error FeeMath__InvalidFeeAssetPriceModifier(); // 0xf2fb32ad } diff --git a/l1-contracts/src/core/libraries/FeeMath.sol b/l1-contracts/src/core/libraries/FeeMath.sol new file mode 100644 index 00000000000..1ffddbc170c --- /dev/null +++ b/l1-contracts/src/core/libraries/FeeMath.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Aztec Labs. +pragma solidity >=0.8.27; + +import {Math} from "@oz/utils/math/Math.sol"; +import {SafeCast} from "@oz/utils/math/SafeCast.sol"; +import {SignedMath} from "@oz/utils/math/SignedMath.sol"; + +import {Errors} from "./Errors.sol"; + +struct OracleInput { + int256 provingCostModifier; + int256 feeAssetPriceModifier; +} + +library FeeMath { + using Math for uint256; + using SafeCast for int256; + using SafeCast for uint256; + using SignedMath for int256; + + // These values are taken from the model, but mostly pulled out of the ass + uint256 internal constant MINIMUM_PROVING_COST_PER_MANA = 5415357955; + uint256 internal constant MAX_PROVING_COST_MODIFIER = 1000000000; + uint256 internal constant PROVING_UPDATE_FRACTION = 100000000000; + + uint256 internal constant MINIMUM_FEE_ASSET_PRICE = 10000000000; + uint256 internal constant MAX_FEE_ASSET_PRICE_MODIFIER = 1000000000; + uint256 internal constant FEE_ASSET_PRICE_UPDATE_FRACTION = 100000000000; + + function assertValid(OracleInput memory _self) internal pure returns (bool) { + require( + SignedMath.abs(_self.provingCostModifier) <= MAX_PROVING_COST_MODIFIER, + Errors.FeeMath__InvalidProvingCostModifier() + ); + require( + SignedMath.abs(_self.feeAssetPriceModifier) <= MAX_FEE_ASSET_PRICE_MODIFIER, + Errors.FeeMath__InvalidFeeAssetPriceModifier() + ); + return true; + } + + function clampedAdd(uint256 _a, int256 _b) internal pure returns (uint256) { + if (_b >= 0) { + return _a + _b.toUint256(); + } + + uint256 sub = SignedMath.abs(_b); + + if (_a > sub) { + return _a - sub; + } + + return 0; + } + + function provingCostPerMana(uint256 _numerator) internal pure returns (uint256) { + return fakeExponential(MINIMUM_PROVING_COST_PER_MANA, _numerator, PROVING_UPDATE_FRACTION); + } + + function feeAssetPriceModifier(uint256 _numerator) internal pure returns (uint256) { + return fakeExponential(MINIMUM_FEE_ASSET_PRICE, _numerator, FEE_ASSET_PRICE_UPDATE_FRACTION); + } + + function fakeExponential(uint256 _factor, uint256 _numerator, uint256 _denominator) + private + pure + returns (uint256) + { + uint256 i = 1; + uint256 output = 0; + uint256 numeratorAccumulator = _factor * _denominator; + while (numeratorAccumulator > 0) { + output += numeratorAccumulator; + numeratorAccumulator = (numeratorAccumulator * _numerator) / (_denominator * i); + i += 1; + } + return output / _denominator; + } +} diff --git a/l1-contracts/src/core/libraries/TxsDecoder.sol b/l1-contracts/src/core/libraries/TxsDecoder.sol index 287491a8ec5..9bf8ef5329e 100644 --- a/l1-contracts/src/core/libraries/TxsDecoder.sol +++ b/l1-contracts/src/core/libraries/TxsDecoder.sol @@ -56,6 +56,7 @@ library TxsDecoder { uint256 noteEncryptedLogsLength; uint256 encryptedLogsLength; uint256 unencryptedLogsLength; + uint256 contractClassLogsLength; } struct Counts { @@ -72,9 +73,11 @@ library TxsDecoder { uint256 kernelNoteEncryptedLogsLength; uint256 kernelEncryptedLogsLength; uint256 kernelUnencryptedLogsLength; + uint256 kernelContractClassLogsLength; bytes32 noteEncryptedLogsHash; bytes32 encryptedLogsHash; bytes32 unencryptedLogsHash; + bytes32 contractClassLogsHash; bytes32 txOutHash; } @@ -166,8 +169,12 @@ library TxsDecoder { offsets.unencryptedLogsLength = offset; offset += 0x20; + // CONTRACT CLASS LOGS LENGTH + offsets.contractClassLogsLength = offset; + offset += 0x20; + /** - * Compute note, encrypted and unencrypted logs hashes corresponding to the current leaf. + * Compute note, encrypted, unencrypted, and contract class logs hashes corresponding to the current leaf. * Note: will advance offsets by the number of bytes processed. */ // NOTE ENCRYPTED LOGS HASH @@ -178,7 +185,11 @@ library TxsDecoder { computeKernelEncryptedLogsHash(offset, _body); // UNENCRYPTED LOGS HASH (vars.unencryptedLogsHash, offset, vars.kernelUnencryptedLogsLength) = - computeKernelUnencryptedLogsHash(offset, _body); + computeKernelUnencryptedLogsHash(offset, _body, false); + // CONTRACT CLASS LOGS HASH + // Note: the logic for unenc. and contract class logs hashing is the same: + (vars.contractClassLogsHash, offset, vars.kernelContractClassLogsLength) = + computeKernelUnencryptedLogsHash(offset, _body, true); // TX LEVEL OUT HASH (vars.txOutHash) = computeTxOutHash(offsets.l2ToL1Msgs, _body); @@ -208,6 +219,14 @@ library TxsDecoder { vars.kernelUnencryptedLogsLength ) ); + require( + uint256(bytes32(slice(_body, offsets.contractClassLogsLength, 0x20))) + == vars.kernelContractClassLogsLength, + Errors.TxsDecoder__InvalidLogsLength( + uint256(bytes32(slice(_body, offsets.contractClassLogsLength, 0x20))), + vars.kernelContractClassLogsLength + ) + ); // Insertions are split into multiple `bytes.concat` to work around stack too deep. vars.baseLeaf = bytes.concat( @@ -239,10 +258,18 @@ library TxsDecoder { ), bytes.concat( slice(_body, offsets.noteEncryptedLogsLength, 0x20), - slice(_body, offsets.encryptedLogsLength, 0x20), - slice(_body, offsets.unencryptedLogsLength, 0x20) + slice(_body, offsets.encryptedLogsLength, 0x20) + ), + bytes.concat( + slice(_body, offsets.unencryptedLogsLength, 0x20), + slice(_body, offsets.contractClassLogsLength, 0x20) ), - bytes.concat(vars.noteEncryptedLogsHash, vars.encryptedLogsHash, vars.unencryptedLogsHash) + bytes.concat( + vars.noteEncryptedLogsHash, + vars.encryptedLogsHash, + vars.unencryptedLogsHash, + vars.contractClassLogsHash + ) ); vars.baseLeaves[i] = Hash.sha256ToField(vars.baseLeaf); @@ -251,7 +278,7 @@ library TxsDecoder { // We pad base leaves with hashes of empty tx effect. for (uint256 i = numTxEffects; i < vars.baseLeaves.length; i++) { // Value taken from tx_effect.test.ts "hash of empty tx effect matches snapshot" test case - vars.baseLeaves[i] = hex"00f0aa51fc81f8242316fcf2cb3b28196241ed3fa26dd320a959bce6c529b270"; + vars.baseLeaves[i] = hex"00c2dece9c9f14c67b8aafabdcb80793f1cffe95a801e15d648fd214a0522ee8"; } } @@ -421,18 +448,18 @@ library TxsDecoder { } /** - * @notice Computes unencrypted logs hash as is done in the kernel circuits. + * @notice Computes unencrypted or contract class logs hash as is done in the kernel circuits. * @param _offsetInBlock - The offset of kernel's logs in a block. * @param _body - The L2 block calldata. * @return The hash of the logs and offset in a block after processing the logs. - * @dev See above for details. The only difference here is that unencrypted logs are + * @dev See above for details. The only difference here is that unencrypted and contract class logs are * siloed with their contract address. */ - function computeKernelUnencryptedLogsHash(uint256 _offsetInBlock, bytes calldata _body) - internal - pure - returns (bytes32, uint256, uint256) - { + function computeKernelUnencryptedLogsHash( + uint256 _offsetInBlock, + bytes calldata _body, + bool _contractClassLogs + ) internal pure returns (bytes32, uint256, uint256) { uint256 offset = _offsetInBlock; uint256 remainingLogsLength = read4(_body, offset); uint256 kernelLogsLength = remainingLogsLength; @@ -473,10 +500,17 @@ library TxsDecoder { } // padded to MAX_LOGS * 32 bytes - flattenedLogHashes = bytes.concat( - flattenedLogHashes, - new bytes(Constants.MAX_UNENCRYPTED_LOGS_PER_TX * 32 - flattenedLogHashes.length) - ); + if (_contractClassLogs) { + flattenedLogHashes = bytes.concat( + flattenedLogHashes, + new bytes(Constants.MAX_CONTRACT_CLASS_LOGS_PER_TX * 32 - flattenedLogHashes.length) + ); + } else { + flattenedLogHashes = bytes.concat( + flattenedLogHashes, + new bytes(Constants.MAX_UNENCRYPTED_LOGS_PER_TX * 32 - flattenedLogHashes.length) + ); + } bytes32 kernelPublicInputsLogsHash = Hash.sha256ToField(flattenedLogHashes); diff --git a/l1-contracts/test/fee_portal/depositToAztecPublic.t.sol b/l1-contracts/test/fee_portal/depositToAztecPublic.t.sol index db038cfe772..fc68df1a444 100644 --- a/l1-contracts/test/fee_portal/depositToAztecPublic.t.sol +++ b/l1-contracts/test/fee_portal/depositToAztecPublic.t.sol @@ -81,6 +81,8 @@ contract DepositToAztecPublic is Test { uint256 amount = 100 ether; uint256 expectedIndex = 2 ** Constants.L1_TO_L2_MSG_SUBTREE_HEIGHT; + // The purpose of including the function selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. DataStructures.L1ToL2Msg memory message = DataStructures.L1ToL2Msg({ sender: DataStructures.L1Actor(address(feeJuicePortal), block.chainid), recipient: DataStructures.L2Actor(feeJuicePortal.L2_TOKEN_ADDRESS(), 1 + numberOfRollups), diff --git a/l1-contracts/test/fees/FeeModelTestPoints.t.sol b/l1-contracts/test/fees/FeeModelTestPoints.t.sol new file mode 100644 index 00000000000..1bd2c6f48f4 --- /dev/null +++ b/l1-contracts/test/fees/FeeModelTestPoints.t.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Aztec Labs. +// solhint-disable var-name-mixedcase +pragma solidity >=0.8.27; + +import {Test} from "forge-std/Test.sol"; + +// Remember that foundry json parsing is alphabetically done, so you MUST +// sort the struct fields alphabetically or prepare for a headache. + +struct L1Fees { + uint256 base_fee; + uint256 blob_fee; +} + +struct Header { + uint256 excess_mana; + uint256 fee_asset_price_numerator; + uint256 mana_used; + uint256 proving_cast_per_mana_numerator; +} + +struct OracleInput { + int256 fee_asset_price_modifier; + int256 proving_cost_modifier; +} + +struct ManaBaseFeeComponents { + uint256 congestion_cost; + uint256 congestion_multiplier; + uint256 data_cost; + uint256 gas_cost; + uint256 proving_cost; +} + +struct TestPointOutputs { + uint256 fee_asset_price_at_execution; + ManaBaseFeeComponents mana_base_fee_components_in_fee_asset; + ManaBaseFeeComponents mana_base_fee_components_in_wei; +} + +struct TestPoint { + uint256 l1_block_number; + L1Fees l1_fees; + Header header; + OracleInput oracle_input; + TestPointOutputs outputs; + Header parent_header; +} + +contract FeeModelTestPoints is Test { + TestPoint[] public points; + + constructor() { + string memory root = vm.projectRoot(); + string memory path = string.concat(root, "/test/fixtures/fee_data_points.json"); + string memory json = vm.readFile(path); + bytes memory jsonBytes = vm.parseJson(json); + TestPoint[] memory dataPoints = abi.decode(jsonBytes, (TestPoint[])); + + for (uint256 i = 0; i < dataPoints.length; i++) { + points.push(dataPoints[i]); + } + } +} diff --git a/l1-contracts/test/fees/MinimalFeeModel.sol b/l1-contracts/test/fees/MinimalFeeModel.sol new file mode 100644 index 00000000000..d0e8b649f77 --- /dev/null +++ b/l1-contracts/test/fees/MinimalFeeModel.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Aztec Labs. +pragma solidity >=0.8.27; + +import {FeeMath, OracleInput} from "@aztec/core/libraries/FeeMath.sol"; + +contract MinimalFeeModel { + using FeeMath for OracleInput; + using FeeMath for uint256; + + struct DataPoint { + uint256 provingCostNumerator; + uint256 feeAssetPriceNumerator; + } + + uint256 public populatedThrough = 0; + mapping(uint256 _slotNumber => DataPoint _dataPoint) public dataPoints; + + constructor() { + dataPoints[0] = DataPoint({provingCostNumerator: 0, feeAssetPriceNumerator: 0}); + } + + // See the `add_slot` function in the `fee-model.ipynb` notebook for more context. + function addSlot(OracleInput memory _oracleInput) public { + _oracleInput.assertValid(); + + DataPoint memory parent = dataPoints[populatedThrough]; + + dataPoints[++populatedThrough] = DataPoint({ + provingCostNumerator: parent.provingCostNumerator.clampedAdd(_oracleInput.provingCostModifier), + feeAssetPriceNumerator: parent.feeAssetPriceNumerator.clampedAdd( + _oracleInput.feeAssetPriceModifier + ) + }); + } + + function getFeeAssetPrice(uint256 _slotNumber) public view returns (uint256) { + return FeeMath.feeAssetPriceModifier(dataPoints[_slotNumber].feeAssetPriceNumerator); + } + + function getProvingCost(uint256 _slotNumber) public view returns (uint256) { + return FeeMath.provingCostPerMana(dataPoints[_slotNumber].provingCostNumerator); + } +} diff --git a/l1-contracts/test/fees/MinimalFeeModel.t.sol b/l1-contracts/test/fees/MinimalFeeModel.t.sol new file mode 100644 index 00000000000..2cf0b787235 --- /dev/null +++ b/l1-contracts/test/fees/MinimalFeeModel.t.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.27; + +import {OracleInput, FeeMath} from "@aztec/core/libraries/FeeMath.sol"; +import {FeeModelTestPoints} from "./FeeModelTestPoints.t.sol"; +import {MinimalFeeModel} from "./MinimalFeeModel.sol"; +import {Errors} from "@aztec/core/libraries/Errors.sol"; + +contract MinimalFeeModelTest is FeeModelTestPoints { + MinimalFeeModel internal feeContract; + + function setUp() public { + feeContract = new MinimalFeeModel(); + + for (uint256 i = 0; i < points.length; i++) { + feeContract.addSlot( + OracleInput({ + provingCostModifier: points[i].oracle_input.proving_cost_modifier, + feeAssetPriceModifier: points[i].oracle_input.fee_asset_price_modifier + }) + ); + } + } + + function test_computeProvingCost() public { + for (uint256 i = 0; i < points.length; i++) { + assertEq( + feeContract.getProvingCost(i), + points[i].outputs.mana_base_fee_components_in_wei.proving_cost, + "Computed proving cost does not match expected value" + ); + } + } + + function test_computeFeeAssetPrice() public { + for (uint256 i = 0; i < points.length; i++) { + assertEq( + feeContract.getFeeAssetPrice(i), + points[i].outputs.fee_asset_price_at_execution, + "Computed fee asset price does not match expected value" + ); + } + } + + function test_invalidOracleInput() public { + uint256 provingBoundary = FeeMath.MAX_PROVING_COST_MODIFIER + 1; + uint256 feeAssetPriceBoundary = FeeMath.MAX_FEE_ASSET_PRICE_MODIFIER + 1; + + vm.expectRevert(abi.encodeWithSelector(Errors.FeeMath__InvalidProvingCostModifier.selector)); + feeContract.addSlot( + OracleInput({provingCostModifier: int256(provingBoundary), feeAssetPriceModifier: 0}) + ); + + vm.expectRevert(abi.encodeWithSelector(Errors.FeeMath__InvalidProvingCostModifier.selector)); + feeContract.addSlot( + OracleInput({provingCostModifier: -int256(provingBoundary), feeAssetPriceModifier: 0}) + ); + + vm.expectRevert(abi.encodeWithSelector(Errors.FeeMath__InvalidFeeAssetPriceModifier.selector)); + feeContract.addSlot( + OracleInput({provingCostModifier: 0, feeAssetPriceModifier: int256(feeAssetPriceBoundary)}) + ); + + vm.expectRevert(abi.encodeWithSelector(Errors.FeeMath__InvalidFeeAssetPriceModifier.selector)); + feeContract.addSlot( + OracleInput({provingCostModifier: 0, feeAssetPriceModifier: -int256(feeAssetPriceBoundary)}) + ); + } +} diff --git a/l1-contracts/test/fixtures/empty_block_1.json b/l1-contracts/test/fixtures/empty_block_1.json index 3502a5f7b9e..0070d3ebdd8 100644 --- a/l1-contracts/test/fixtures/empty_block_1.json +++ b/l1-contracts/test/fixtures/empty_block_1.json @@ -8,25 +8,25 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x01c96319c544c46399dcc0f48c344210ae5bf846507a202512d3aaa4768aad7f", - "blockHash": "0x1e273844400064424f4b091fd7944446a32bb7a96d8bf69a05e32f01a1a40cde", + "archive": "0x1f80d0f24457c066a8b752a2c424ee0c8bd61143db120fa0841d0f4233f7e21d", + "blockHash": "0x267f79fe7e757b20e924fac9f78264a0d1c8c4b481fea21d0bbe74650d87a1f1", "body": "0x00000000", - "txsEffectsHash": "0x00e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d6", + "txsEffectsHash": "0x002dcd61493c9a7f3ce4605573ee657e6ced4a3dd10bfb216f44a796b3d585c9", "decodedHeader": { "contentCommitment": { "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb", "numTxs": 2, - "txsEffectsHash": "0x00e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d6" + "txsEffectsHash": "0x002dcd61493c9a7f3ce4605573ee657e6ced4a3dd10bfb216f44a796b3d585c9" }, "globalVariables": { "blockNumber": 1, "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000012", "chainId": 31337, - "timestamp": 1731107199, + "timestamp": 1731434785, "version": 1, - "coinbase": "0x8a914126f71d7c294a01833665b9a9019347d6a2", - "feeRecipient": "0x1d2bd70d60e15b1148d6c5590d5ed3dd0427419f862ee389b12abf25481ffd26", + "coinbase": "0x4f6cd865d580ac0011a4776d8dc51db519c2318a", + "feeRecipient": "0x1ae8b5e1d9882013ea5271b1e71b307bc48c191549588587a227c8a118834864", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -57,8 +57,8 @@ } } }, - "header": "0x2a05cb8aeefe9b9797f90650eae072f5ab7437807e62f9724ce190046777986000000001000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6000000101fd848aa69e1633722fe249a5b7f53b094f1c9cef9f5c694b073fd1cc5850dfb000000800c499b373a1f0fe1b510a63563546d2d39e206895056a5af0143c5f30d6390730000010023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000672e997f8a914126f71d7c294a01833665b9a9019347d6a21d2bd70d60e15b1148d6c5590d5ed3dd0427419f862ee389b12abf25481ffd26000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00fc461dff8a8b9e2397bb5d40053b87281dd9fd28e77834a2749bfc5f32bfb9", + "header": "0x2a05cb8aeefe9b9797f90650eae072f5ab7437807e62f9724ce1900467779860000000010000000000000000000000000000000000000000000000000000000000000002002dcd61493c9a7f3ce4605573ee657e6ced4a3dd10bfb216f44a796b3d585c900089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6000000101fd848aa69e1633722fe249a5b7f53b094f1c9cef9f5c694b073fd1cc5850dfb000000800c499b373a1f0fe1b510a63563546d2d39e206895056a5af0143c5f30d6390730000010023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000673399214f6cd865d580ac0011a4776d8dc51db519c2318a1ae8b5e1d9882013ea5271b1e71b307bc48c191549588587a227c8a118834864000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00f45c9ec73df38136aa1fed90362a5df796817e37a36d02df4700f80bc356b2", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/empty_block_2.json b/l1-contracts/test/fixtures/empty_block_2.json index 4c6c504350e..447934f005b 100644 --- a/l1-contracts/test/fixtures/empty_block_2.json +++ b/l1-contracts/test/fixtures/empty_block_2.json @@ -8,25 +8,25 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x19b0447418d0e86728db9266ecf57b26b3e4a47388c4241e16f5f9e4b2d20492", - "blockHash": "0x07effa5ee44661e8167d238e02729e739543aa4cfbf619878850a440e021ce72", + "archive": "0x1120ec22c3dd3dd6904b9520f086189726776a41c75c53f8f4cea4a53bc45844", + "blockHash": "0x2d48eea4aa6c13eea47df326e22cd76e74ecc24ee272d6b4207eb5f494f891d3", "body": "0x00000000", - "txsEffectsHash": "0x00e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d6", + "txsEffectsHash": "0x002dcd61493c9a7f3ce4605573ee657e6ced4a3dd10bfb216f44a796b3d585c9", "decodedHeader": { "contentCommitment": { "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb", "numTxs": 2, - "txsEffectsHash": "0x00e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d6" + "txsEffectsHash": "0x002dcd61493c9a7f3ce4605573ee657e6ced4a3dd10bfb216f44a796b3d585c9" }, "globalVariables": { "blockNumber": 2, "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000013", "chainId": 31337, - "timestamp": 1731107223, + "timestamp": 1731434809, "version": 1, - "coinbase": "0x8a914126f71d7c294a01833665b9a9019347d6a2", - "feeRecipient": "0x1d2bd70d60e15b1148d6c5590d5ed3dd0427419f862ee389b12abf25481ffd26", + "coinbase": "0x4f6cd865d580ac0011a4776d8dc51db519c2318a", + "feeRecipient": "0x1ae8b5e1d9882013ea5271b1e71b307bc48c191549588587a227c8a118834864", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -34,7 +34,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x01c96319c544c46399dcc0f48c344210ae5bf846507a202512d3aaa4768aad7f" + "root": "0x1f80d0f24457c066a8b752a2c424ee0c8bd61143db120fa0841d0f4233f7e21d" }, "stateReference": { "l1ToL2MessageTree": { @@ -57,8 +57,8 @@ } } }, - "header": "0x01c96319c544c46399dcc0f48c344210ae5bf846507a202512d3aaa4768aad7f00000002000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6000000201fd848aa69e1633722fe249a5b7f53b094f1c9cef9f5c694b073fd1cc5850dfb000001000c499b373a1f0fe1b510a63563546d2d39e206895056a5af0143c5f30d6390730000018023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000672e99978a914126f71d7c294a01833665b9a9019347d6a21d2bd70d60e15b1148d6c5590d5ed3dd0427419f862ee389b12abf25481ffd26000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x006d28d243077e67b4570884f2b6d0b30aba890a326b21308690d5f279e47ab9", + "header": "0x1f80d0f24457c066a8b752a2c424ee0c8bd61143db120fa0841d0f4233f7e21d000000020000000000000000000000000000000000000000000000000000000000000002002dcd61493c9a7f3ce4605573ee657e6ced4a3dd10bfb216f44a796b3d585c900089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6000000201fd848aa69e1633722fe249a5b7f53b094f1c9cef9f5c694b073fd1cc5850dfb000001000c499b373a1f0fe1b510a63563546d2d39e206895056a5af0143c5f30d6390730000018023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001300000000000000000000000000000000000000000000000000000000673399394f6cd865d580ac0011a4776d8dc51db519c2318a1ae8b5e1d9882013ea5271b1e71b307bc48c191549588587a227c8a118834864000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x0050ad1c615efe79df6f8ed137584b719b7043725a87ff1b1e2a29f22f0827c8", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/fee_data_points.json b/l1-contracts/test/fixtures/fee_data_points.json new file mode 100644 index 00000000000..82228b4288d --- /dev/null +++ b/l1-contracts/test/fixtures/fee_data_points.json @@ -0,0 +1,26682 @@ +[ + { + "l1_block_number": 20973164, + "l1_fees": { + "blob_fee": 23, + "base_fee": 14402849460 + }, + "parent_header": { + "excess_mana": 0, + "mana_used": 0, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 0, + "mana_used": 199990283, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 669375682 + }, + "oracle_input": { + "proving_cost_modifier": -59048622, + "fee_asset_price_modifier": 669375682 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 47709438, + "proving_cost": 5415357955, + "congestion_cost": 0, + "congestion_multiplier": 1000000000 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 477094380, + "proving_cost": 54153579550, + "congestion_cost": 0, + "congestion_multiplier": 1000000000 + } + } + }, + { + "l1_block_number": 20973167, + "l1_fees": { + "blob_fee": 25, + "base_fee": 14415907878 + }, + "parent_header": { + "excess_mana": 0, + "mana_used": 199990283, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 669375682 + }, + "header": { + "excess_mana": 99990283, + "mana_used": 199990996, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1462908027 + }, + "oracle_input": { + "proving_cost_modifier": -178362315, + "fee_asset_price_modifier": 793532345 + }, + "outputs": { + "fee_asset_price_at_execution": 10067162100, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 47752694, + "proving_cost": 5415357955, + "congestion_cost": 678008355, + "congestion_multiplier": 1124106649 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 480734111, + "proving_cost": 54517286362, + "congestion_cost": 6825620014, + "congestion_multiplier": 1124106649 + } + } + }, + { + "l1_block_number": 20973170, + "l1_fees": { + "blob_fee": 31, + "base_fee": 13994212243 + }, + "parent_header": { + "excess_mana": 99990283, + "mana_used": 199990996, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1462908027 + }, + "header": { + "excess_mana": 199981279, + "mana_used": 199997039, + "proving_cost_per_mana_numerator": 17455936, + "fee_asset_price_numerator": 1631363588 + }, + "oracle_input": { + "proving_cost_modifier": 17455936, + "fee_asset_price_modifier": 168455561 + }, + "outputs": { + "fee_asset_price_at_execution": 10147366089, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 46355828, + "proving_cost": 5415357955, + "congestion_cost": 1439799586, + "congestion_multiplier": 1263616814 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 470389557, + "proving_cost": 54951619672, + "congestion_cost": 14610173493, + "congestion_multiplier": 1263616814 + } + } + }, + { + "l1_block_number": 20973173, + "l1_fees": { + "blob_fee": 29, + "base_fee": 14784230064 + }, + "parent_header": { + "excess_mana": 199981279, + "mana_used": 199997039, + "proving_cost_per_mana_numerator": 17455936, + "fee_asset_price_numerator": 1631363588 + }, + "header": { + "excess_mana": 299978318, + "mana_used": 199997697, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1040346471 + }, + "oracle_input": { + "proving_cost_modifier": -99066077, + "fee_asset_price_modifier": -591017117 + }, + "outputs": { + "fee_asset_price_at_execution": 10164474298, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 48972762, + "proving_cost": 5416303338, + "congestion_cost": 2297882391, + "congestion_multiplier": 1420451291 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 497782380, + "proving_cost": 55053876069, + "congestion_cost": 23356766503, + "congestion_multiplier": 1420451291 + } + } + }, + { + "l1_block_number": 20973176, + "l1_fees": { + "blob_fee": 32, + "base_fee": 15016479747 + }, + "parent_header": { + "excess_mana": 299978318, + "mana_used": 199997697, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1040346471 + }, + "header": { + "excess_mana": 399976015, + "mana_used": 199996235, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1412024221 + }, + "oracle_input": { + "proving_cost_modifier": -142153798, + "fee_asset_price_modifier": 371677750 + }, + "outputs": { + "fee_asset_price_at_execution": 10104577689, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 49742089, + "proving_cost": 5415357955, + "congestion_cost": 3261312622, + "congestion_multiplier": 1596752593 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 502622802, + "proving_cost": 54719905170, + "congestion_cost": 32954186757, + "congestion_multiplier": 1596752593 + } + } + }, + { + "l1_block_number": 20973179, + "l1_fees": { + "blob_fee": 35, + "base_fee": 14552539238 + }, + "parent_header": { + "excess_mana": 399976015, + "mana_used": 199996235, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1412024221 + }, + "header": { + "excess_mana": 499972250, + "mana_used": 199997933, + "proving_cost_per_mana_numerator": 40177098, + "fee_asset_price_numerator": 1893950162 + }, + "oracle_input": { + "proving_cost_modifier": 40177098, + "fee_asset_price_modifier": 481925941 + }, + "outputs": { + "fee_asset_price_at_execution": 10142204037, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 48205286, + "proving_cost": 5415357955, + "congestion_cost": 4343165122, + "congestion_multiplier": 1794932708 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 488907846, + "proving_cost": 54923665313, + "congestion_cost": 44049266833, + "congestion_multiplier": 1794932708 + } + } + }, + { + "l1_block_number": 20973182, + "l1_fees": { + "blob_fee": 50, + "base_fee": 14547546861 + }, + "parent_header": { + "excess_mana": 499972250, + "mana_used": 199997933, + "proving_cost_per_mana_numerator": 40177098, + "fee_asset_price_numerator": 1893950162 + }, + "header": { + "excess_mana": 599970183, + "mana_used": 199994817, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1856798629 + }, + "oracle_input": { + "proving_cost_modifier": -60537230, + "fee_asset_price_modifier": -37151533 + }, + "outputs": { + "fee_asset_price_at_execution": 10191199916, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 48188748, + "proving_cost": 5417534125, + "congestion_cost": 5562541884, + "congestion_multiplier": 2017713853 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 491101164, + "proving_cost": 55211173319, + "congestion_cost": 56688976380, + "congestion_multiplier": 2017713853 + } + } + }, + { + "l1_block_number": 20973185, + "l1_fees": { + "blob_fee": 72, + "base_fee": 14232502274 + }, + "parent_header": { + "excess_mana": 599970183, + "mana_used": 199994817, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1856798629 + }, + "header": { + "excess_mana": 699965000, + "mana_used": 199996278, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1582709589 + }, + "oracle_input": { + "proving_cost_modifier": -50166503, + "fee_asset_price_modifier": -274089040 + }, + "outputs": { + "fee_asset_price_at_execution": 10187414432, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 47145163, + "proving_cost": 5415357955, + "congestion_cost": 6927205544, + "congestion_multiplier": 2268137591 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 480287313, + "proving_cost": 55168495785, + "congestion_cost": 70570313732, + "congestion_multiplier": 2268137591 + } + } + }, + { + "l1_block_number": 20973188, + "l1_fees": { + "blob_fee": 98, + "base_fee": 14127655188 + }, + "parent_header": { + "excess_mana": 699965000, + "mana_used": 199996278, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1582709589 + }, + "header": { + "excess_mana": 799961278, + "mana_used": 199984012, + "proving_cost_per_mana_numerator": 33783426, + "fee_asset_price_numerator": 1246258072 + }, + "oracle_input": { + "proving_cost_modifier": 33783426, + "fee_asset_price_modifier": -336451517 + }, + "outputs": { + "fee_asset_price_at_execution": 10159530077, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 46797857, + "proving_cost": 5415357955, + "congestion_cost": 8464410270, + "congestion_multiplier": 2549646433 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 475444235, + "proving_cost": 55017492021, + "congestion_cost": 85994430722, + "congestion_multiplier": 2549646433 + } + } + }, + { + "l1_block_number": 20973191, + "l1_fees": { + "blob_fee": 115, + "base_fee": 14102980851 + }, + "parent_header": { + "excess_mana": 799961278, + "mana_used": 199984012, + "proving_cost_per_mana_numerator": 33783426, + "fee_asset_price_numerator": 1246258072 + }, + "header": { + "excess_mana": 899945290, + "mana_used": 199999674, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 954592539 + }, + "oracle_input": { + "proving_cost_modifier": -106484723, + "fee_asset_price_modifier": -291665533 + }, + "outputs": { + "fee_asset_price_at_execution": 10125405622, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 46716124, + "proving_cost": 5417187757, + "congestion_cost": 10195936862, + "congestion_multiplier": 2866053482 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 473019704, + "proving_cost": 54851223370, + "congestion_cost": 103237996424, + "congestion_multiplier": 2866053482 + } + } + }, + { + "l1_block_number": 20973194, + "l1_fees": { + "blob_fee": 120, + "base_fee": 14702466429 + }, + "parent_header": { + "excess_mana": 899945290, + "mana_used": 199999674, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 954592539 + }, + "header": { + "excess_mana": 999944964, + "mana_used": 199996424, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1071432807 + }, + "oracle_input": { + "proving_cost_modifier": -52977520, + "fee_asset_price_modifier": 116840268 + }, + "outputs": { + "fee_asset_price_at_execution": 10095916330, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 48701920, + "proving_cost": 5415357955, + "congestion_cost": 12139967236, + "congestion_multiplier": 3221785177 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 491690509, + "proving_cost": 54673000810, + "congestion_cost": 122564093463, + "congestion_multiplier": 3221785177 + } + } + }, + { + "l1_block_number": 20973197, + "l1_fees": { + "blob_fee": 106, + "base_fee": 14850593518 + }, + "parent_header": { + "excess_mana": 999944964, + "mana_used": 199996424, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1071432807 + }, + "header": { + "excess_mana": 1099941388, + "mana_used": 177366071, + "proving_cost_per_mana_numerator": 60087242, + "fee_asset_price_numerator": 758010157 + }, + "oracle_input": { + "proving_cost_modifier": 60087242, + "fee_asset_price_modifier": -313422650 + }, + "outputs": { + "fee_asset_price_at_execution": 10107719320, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 49192591, + "proving_cost": 5415357955, + "congestion_cost": 14326172616, + "congestion_multiplier": 3621656163 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 497224902, + "proving_cost": 54736918226, + "congestion_cost": 144804931732, + "congestion_multiplier": 3621656163 + } + } + }, + { + "l1_block_number": 20973200, + "l1_fees": { + "blob_fee": 87, + "base_fee": 15618137990 + }, + "parent_header": { + "excess_mana": 1099941388, + "mana_used": 177366071, + "proving_cost_per_mana_numerator": 60087242, + "fee_asset_price_numerator": 758010157 + }, + "header": { + "excess_mana": 1177307459, + "mana_used": 105632955, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1098791969 + }, + "oracle_input": { + "proving_cost_modifier": -134258021, + "fee_asset_price_modifier": 340781812 + }, + "outputs": { + "fee_asset_price_at_execution": 10076089032, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 51735082, + "proving_cost": 5418612872, + "congestion_cost": 16218364323, + "congestion_multiplier": 3964777462 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 521287292, + "proving_cost": 54598425728, + "congestion_cost": 163417682871, + "congestion_multiplier": 3964777462 + } + } + }, + { + "l1_block_number": 20973203, + "l1_fees": { + "blob_fee": 98, + "base_fee": 15809788248 + }, + "parent_header": { + "excess_mana": 1177307459, + "mana_used": 105632955, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1098791969 + }, + "header": { + "excess_mana": 1182940414, + "mana_used": 199957829, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1670588844 + }, + "oracle_input": { + "proving_cost_modifier": -46759887, + "fee_asset_price_modifier": 571796875 + }, + "outputs": { + "fee_asset_price_at_execution": 10110485085, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 52369923, + "proving_cost": 5415357955, + "congestion_cost": 16353940462, + "congestion_multiplier": 3990993851 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 529485325, + "proving_cost": 54751895833, + "congestion_cost": 165346271122, + "congestion_multiplier": 3990993851 + } + } + }, + { + "l1_block_number": 20973206, + "l1_fees": { + "blob_fee": 130, + "base_fee": 16615048160 + }, + "parent_header": { + "excess_mana": 1182940414, + "mana_used": 199957829, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1670588844 + }, + "header": { + "excess_mana": 1282898243, + "mana_used": 120218002, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1430564163 + }, + "oracle_input": { + "proving_cost_modifier": -30308858, + "fee_asset_price_modifier": -240024681 + }, + "outputs": { + "fee_asset_price_at_execution": 10168462121, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 55037347, + "proving_cost": 5415357955, + "congestion_cost": 19070522199, + "congestion_multiplier": 4486132381 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 559645178, + "proving_cost": 55065862237, + "congestion_cost": 193917882608, + "congestion_multiplier": 4486132381 + } + } + }, + { + "l1_block_number": 20973209, + "l1_fees": { + "blob_fee": 164, + "base_fee": 17184203834 + }, + "parent_header": { + "excess_mana": 1282898243, + "mana_used": 120218002, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1430564163 + }, + "header": { + "excess_mana": 1303116245, + "mana_used": 108663083, + "proving_cost_per_mana_numerator": 42974511, + "fee_asset_price_numerator": 1398913434 + }, + "oracle_input": { + "proving_cost_modifier": 42974511, + "fee_asset_price_modifier": -31650729 + }, + "outputs": { + "fee_asset_price_at_execution": 10144084570, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 56922675, + "proving_cost": 5415357955, + "congestion_cost": 19664734632, + "congestion_multiplier": 4593517212 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 577428429, + "proving_cost": 54933849072, + "congestion_cost": 199480731153, + "congestion_multiplier": 4593517212 + } + } + }, + { + "l1_block_number": 20973212, + "l1_fees": { + "blob_fee": 164, + "base_fee": 19878985864 + }, + "parent_header": { + "excess_mana": 1303116245, + "mana_used": 108663083, + "proving_cost_per_mana_numerator": 42974511, + "fee_asset_price_numerator": 1398913434 + }, + "header": { + "excess_mana": 1311779328, + "mana_used": 98368116, + "proving_cost_per_mana_numerator": 65600657, + "fee_asset_price_numerator": 1496985754 + }, + "oracle_input": { + "proving_cost_modifier": 22626146, + "fee_asset_price_modifier": 98072320 + }, + "outputs": { + "fee_asset_price_at_execution": 10140874401, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 65849140, + "proving_cost": 5417685678, + "congestion_cost": 19961782930, + "congestion_multiplier": 4640312972 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 667767858, + "proving_cost": 54940070004, + "congestion_cost": 202429933513, + "congestion_multiplier": 4640312972 + } + } + }, + { + "l1_block_number": 20973215, + "l1_fees": { + "blob_fee": 200, + "base_fee": 18840462804 + }, + "parent_header": { + "excess_mana": 1311779328, + "mana_used": 98368116, + "proving_cost_per_mana_numerator": 65600657, + "fee_asset_price_numerator": 1496985754 + }, + "header": { + "excess_mana": 1310147444, + "mana_used": 105469376, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 954626605 + }, + "oracle_input": { + "proving_cost_modifier": -66070337, + "fee_asset_price_modifier": -542359149 + }, + "outputs": { + "fee_asset_price_at_execution": 10150824670, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 62409033, + "proving_cost": 5418911630, + "congestion_cost": 19905205811, + "congestion_multiplier": 4631461656 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 633503151, + "proving_cost": 55006421858, + "congestion_cost": 202054254207, + "congestion_multiplier": 4631461656 + } + } + }, + { + "l1_block_number": 20973218, + "l1_fees": { + "blob_fee": 216, + "base_fee": 17587430794 + }, + "parent_header": { + "excess_mana": 1310147444, + "mana_used": 105469376, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 954626605 + }, + "header": { + "excess_mana": 1315616820, + "mana_used": 105844331, + "proving_cost_per_mana_numerator": 141121635, + "fee_asset_price_numerator": 1612884691 + }, + "oracle_input": { + "proving_cost_modifier": 141121635, + "fee_asset_price_modifier": 658258086 + }, + "outputs": { + "fee_asset_price_at_execution": 10095919769, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 58258364, + "proving_cost": 5415357955, + "congestion_cost": 20039972298, + "congestion_multiplier": 4661194196 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 588171768, + "proving_cost": 54673019434, + "congestion_cost": 202321952493, + "congestion_multiplier": 4661194196 + } + } + }, + { + "l1_block_number": 20973221, + "l1_fees": { + "blob_fee": 192, + "base_fee": 18240173510 + }, + "parent_header": { + "excess_mana": 1315616820, + "mana_used": 105844331, + "proving_cost_per_mana_numerator": 141121635, + "fee_asset_price_numerator": 1612884691 + }, + "header": { + "excess_mana": 1321461151, + "mana_used": 98446274, + "proving_cost_per_mana_numerator": 96693946, + "fee_asset_price_numerator": 1167331383 + }, + "oracle_input": { + "proving_cost_modifier": -44427689, + "fee_asset_price_modifier": -445553308 + }, + "outputs": { + "fee_asset_price_at_execution": 10162596188, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 60420574, + "proving_cost": 5423005591, + "congestion_cost": 20251258146, + "congestion_multiplier": 4693176043 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 614029895, + "proving_cost": 55111815946, + "congestion_cost": 205805358836, + "congestion_multiplier": 4693176043 + } + } + }, + { + "l1_block_number": 20973224, + "l1_fees": { + "blob_fee": 171, + "base_fee": 21493716770 + }, + "parent_header": { + "excess_mana": 1321461151, + "mana_used": 98446274, + "proving_cost_per_mana_numerator": 96693946, + "fee_asset_price_numerator": 1167331383 + }, + "header": { + "excess_mana": 1319907425, + "mana_used": 84600050, + "proving_cost_per_mana_numerator": 224636242, + "fee_asset_price_numerator": 1265476079 + }, + "oracle_input": { + "proving_cost_modifier": 127942296, + "fee_asset_price_modifier": 98144696 + }, + "outputs": { + "fee_asset_price_at_execution": 10117417128, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 71197936, + "proving_cost": 5420596810, + "congestion_cost": 20235353911, + "congestion_multiplier": 4684652258 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 720339217, + "proving_cost": 54842439009, + "congestion_cost": 204729516250, + "congestion_multiplier": 4684652258 + } + } + }, + { + "l1_block_number": 20973227, + "l1_fees": { + "blob_fee": 152, + "base_fee": 21129802751 + }, + "parent_header": { + "excess_mana": 1319907425, + "mana_used": 84600050, + "proving_cost_per_mana_numerator": 224636242, + "fee_asset_price_numerator": 1265476079 + }, + "header": { + "excess_mana": 1304507475, + "mana_used": 110635621, + "proving_cost_per_mana_numerator": 289339939, + "fee_asset_price_numerator": 1664231361 + }, + "oracle_input": { + "proving_cost_modifier": 64703697, + "fee_asset_price_modifier": 398755282 + }, + "outputs": { + "fee_asset_price_at_execution": 10127351711, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 69992471, + "proving_cost": 5427536485, + "congestion_cost": 19796603683, + "congestion_multiplier": 4601000348 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 708838370, + "proving_cost": 54966570907, + "congestion_cost": 200487168181, + "congestion_multiplier": 4601000348 + } + } + }, + { + "l1_block_number": 20973230, + "l1_fees": { + "blob_fee": 216, + "base_fee": 19428171353 + }, + "parent_header": { + "excess_mana": 1304507475, + "mana_used": 110635621, + "proving_cost_per_mana_numerator": 289339939, + "fee_asset_price_numerator": 1664231361 + }, + "header": { + "excess_mana": 1315143096, + "mana_used": 107193381, + "proving_cost_per_mana_numerator": 203772621, + "fee_asset_price_numerator": 2266740945 + }, + "oracle_input": { + "proving_cost_modifier": -85567318, + "fee_asset_price_modifier": 602509584 + }, + "outputs": { + "fee_asset_price_at_execution": 10167815683, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 64355817, + "proving_cost": 5431049438, + "congestion_cost": 20105552379, + "congestion_multiplier": 4658611412 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 654358085, + "proving_cost": 55221909650, + "congestion_cost": 204429550794, + "congestion_multiplier": 4658611412 + } + } + }, + { + "l1_block_number": 20973233, + "l1_fees": { + "blob_fee": 243, + "base_fee": 20070480259 + }, + "parent_header": { + "excess_mana": 1315143096, + "mana_used": 107193381, + "proving_cost_per_mana_numerator": 203772621, + "fee_asset_price_numerator": 2266740945 + }, + "header": { + "excess_mana": 1322336477, + "mana_used": 101466733, + "proving_cost_per_mana_numerator": 34521604, + "fee_asset_price_numerator": 2167173930 + }, + "oracle_input": { + "proving_cost_modifier": -169251017, + "fee_asset_price_modifier": -99567015 + }, + "outputs": { + "fee_asset_price_at_execution": 10229262673, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 66483465, + "proving_cost": 5426404222, + "congestion_cost": 20312615910, + "congestion_multiplier": 4697984934 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 680076826, + "proving_cost": 55508114156, + "congestion_cost": 207783083719, + "congestion_multiplier": 4697984934 + } + } + }, + { + "l1_block_number": 20973236, + "l1_fees": { + "blob_fee": 333, + "base_fee": 18248910855 + }, + "parent_header": { + "excess_mana": 1322336477, + "mana_used": 101466733, + "proving_cost_per_mana_numerator": 34521604, + "fee_asset_price_numerator": 2167173930 + }, + "header": { + "excess_mana": 1323803210, + "mana_used": 91541959, + "proving_cost_per_mana_numerator": 76429561, + "fee_asset_price_numerator": 1301363172 + }, + "oracle_input": { + "proving_cost_modifier": 41907957, + "fee_asset_price_modifier": -865810758 + }, + "outputs": { + "fee_asset_price_at_execution": 10219082770, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 60449517, + "proving_cost": 5417227746, + "congestion_cost": 20300567526, + "congestion_multiplier": 4706053962 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 617738617, + "proving_cost": 55359098720, + "congestion_cost": 207453179826, + "congestion_multiplier": 4706053962 + } + } + }, + { + "l1_block_number": 20973239, + "l1_fees": { + "blob_fee": 347, + "base_fee": 20770060420 + }, + "parent_header": { + "excess_mana": 1323803210, + "mana_used": 91541959, + "proving_cost_per_mana_numerator": 76429561, + "fee_asset_price_numerator": 1301363172 + }, + "header": { + "excess_mana": 1315345169, + "mana_used": 122131829, + "proving_cost_per_mana_numerator": 262665832, + "fee_asset_price_numerator": 335413966 + }, + "oracle_input": { + "proving_cost_modifier": 186236271, + "fee_asset_price_modifier": -965949206 + }, + "outputs": { + "fee_asset_price_at_execution": 10130986775, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 68800825, + "proving_cost": 5419498471, + "congestion_cost": 20085600043, + "congestion_multiplier": 4659712956 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 697020248, + "proving_cost": 54904867336, + "congestion_cost": 203486948403, + "congestion_multiplier": 4659712956 + } + } + }, + { + "l1_block_number": 20973242, + "l1_fees": { + "blob_fee": 263, + "base_fee": 20083364753 + }, + "parent_header": { + "excess_mana": 1315345169, + "mana_used": 122131829, + "proving_cost_per_mana_numerator": 262665832, + "fee_asset_price_numerator": 335413966 + }, + "header": { + "excess_mana": 1337476998, + "mana_used": 94686801, + "proving_cost_per_mana_numerator": 285649568, + "fee_asset_price_numerator": 522653958 + }, + "oracle_input": { + "proving_cost_modifier": 22983736, + "fee_asset_price_modifier": 187239992 + }, + "outputs": { + "fee_asset_price_at_execution": 10033597710, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 66526145, + "proving_cost": 5429600947, + "congestion_cost": 20786069334, + "congestion_multiplier": 4781948449 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 667496576, + "proving_cost": 54478431628, + "congestion_cost": 208559057669, + "congestion_multiplier": 4781948449 + } + } + }, + { + "l1_block_number": 20973245, + "l1_fees": { + "blob_fee": 333, + "base_fee": 18976916853 + }, + "parent_header": { + "excess_mana": 1337476998, + "mana_used": 94686801, + "proving_cost_per_mana_numerator": 285649568, + "fee_asset_price_numerator": 522653958 + }, + "header": { + "excess_mana": 1332163799, + "mana_used": 98391768, + "proving_cost_per_mana_numerator": 327049540, + "fee_asset_price_numerator": 466383850 + }, + "oracle_input": { + "proving_cost_modifier": 41399972, + "fee_asset_price_modifier": -56270108 + }, + "outputs": { + "fee_asset_price_at_execution": 10052402217, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 62861037, + "proving_cost": 5430849016, + "congestion_cost": 20614124850, + "congestion_multiplier": 4752313946 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 631904427, + "proving_cost": 54593078688, + "congestion_cost": 207221474343, + "congestion_multiplier": 4752313946 + } + } + }, + { + "l1_block_number": 20973248, + "l1_fees": { + "blob_fee": 347, + "base_fee": 18939331593 + }, + "parent_header": { + "excess_mana": 1332163799, + "mana_used": 98391768, + "proving_cost_per_mana_numerator": 327049540, + "fee_asset_price_numerator": 466383850 + }, + "header": { + "excess_mana": 1330555567, + "mana_used": 97285971, + "proving_cost_per_mana_numerator": 349440774, + "fee_asset_price_numerator": 1263490118 + }, + "oracle_input": { + "proving_cost_modifier": 22391234, + "fee_asset_price_modifier": 797106268 + }, + "outputs": { + "fee_asset_price_at_execution": 10046747311, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 62736535, + "proving_cost": 5433097851, + "congestion_cost": 20572997901, + "congestion_multiplier": 4743380250 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 630298114, + "proving_cost": 54584961224, + "congestion_cost": 206691711341, + "congestion_multiplier": 4743380250 + } + } + }, + { + "l1_block_number": 20973251, + "l1_fees": { + "blob_fee": 361, + "base_fee": 18547987166 + }, + "parent_header": { + "excess_mana": 1330555567, + "mana_used": 97285971, + "proving_cost_per_mana_numerator": 349440774, + "fee_asset_price_numerator": 1263490118 + }, + "header": { + "excess_mana": 1327841538, + "mana_used": 94195956, + "proving_cost_per_mana_numerator": 521756115, + "fee_asset_price_numerator": 634906412 + }, + "oracle_input": { + "proving_cost_modifier": 172315341, + "fee_asset_price_modifier": -628583706 + }, + "outputs": { + "fee_asset_price_at_execution": 10127150587, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 61440207, + "proving_cost": 5434314525, + "congestion_cost": 20490052884, + "congestion_multiplier": 4728341944 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 622214228, + "proving_cost": 55034121531, + "congestion_cost": 207505851091, + "congestion_multiplier": 4728341944 + } + } + }, + { + "l1_block_number": 20973254, + "l1_fees": { + "blob_fee": 406, + "base_fee": 19027558519 + }, + "parent_header": { + "excess_mana": 1327841538, + "mana_used": 94195956, + "proving_cost_per_mana_numerator": 521756115, + "fee_asset_price_numerator": 634906412 + }, + "header": { + "excess_mana": 1322037494, + "mana_used": 104831684, + "proving_cost_per_mana_numerator": 328317385, + "fee_asset_price_numerator": 1493437131 + }, + "oracle_input": { + "proving_cost_modifier": -193438730, + "fee_asset_price_modifier": 858530719 + }, + "outputs": { + "fee_asset_price_at_execution": 10063692621, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 63028787, + "proving_cost": 5443686755, + "congestion_cost": 20354702941, + "congestion_multiplier": 4696341818 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 634302338, + "proving_cost": 54783590227, + "congestion_cost": 204843473789, + "congestion_multiplier": 4696341818 + } + } + }, + { + "l1_block_number": 20973257, + "l1_fees": { + "blob_fee": 285, + "base_fee": 19960437790 + }, + "parent_header": { + "excess_mana": 1322037494, + "mana_used": 104831684, + "proving_cost_per_mana_numerator": 328317385, + "fee_asset_price_numerator": 1493437131 + }, + "header": { + "excess_mana": 1326869178, + "mana_used": 95091170, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 683470723 + }, + "oracle_input": { + "proving_cost_modifier": -408184922, + "fee_asset_price_modifier": -809966408 + }, + "outputs": { + "fee_asset_price_at_execution": 10150464462, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 66118950, + "proving_cost": 5433166735, + "congestion_cost": 20473652263, + "congestion_multiplier": 4722965751 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 671138052, + "proving_cost": 55149165859, + "congestion_cost": 207817079702, + "congestion_multiplier": 4722965751 + } + } + }, + { + "l1_block_number": 20973260, + "l1_fees": { + "blob_fee": 320, + "base_fee": 20847107469 + }, + "parent_header": { + "excess_mana": 1326869178, + "mana_used": 95091170, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 683470723 + }, + "header": { + "excess_mana": 1321960348, + "mana_used": 98931930, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 263974984 + }, + "oracle_input": { + "proving_cost_modifier": -89389051, + "fee_asset_price_modifier": -419495739 + }, + "outputs": { + "fee_asset_price_at_execution": 10068581171, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 69056043, + "proving_cost": 5415357955, + "congestion_cost": 20269944100, + "congestion_multiplier": 4695917942 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 695296374, + "proving_cost": 54524971139, + "congestion_cost": 204089577502, + "congestion_multiplier": 4695917942 + } + } + }, + { + "l1_block_number": 20973263, + "l1_fees": { + "blob_fee": 375, + "base_fee": 18902464529 + }, + "parent_header": { + "excess_mana": 1321960348, + "mana_used": 98931930, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 263974984 + }, + "header": { + "excess_mana": 1320892278, + "mana_used": 95278001, + "proving_cost_per_mana_numerator": 100690211, + "fee_asset_price_numerator": 311174512 + }, + "oracle_input": { + "proving_cost_modifier": 100690211, + "fee_asset_price_modifier": 47199528 + }, + "outputs": { + "fee_asset_price_at_execution": 10026432370, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 62614413, + "proving_cost": 5415357955, + "congestion_cost": 20214010516, + "congestion_multiplier": 4690053391 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 627799177, + "proving_cost": 54296720295, + "congestion_cost": 202674409365, + "congestion_multiplier": 4690053391 + } + } + }, + { + "l1_block_number": 20973266, + "l1_fees": { + "blob_fee": 308, + "base_fee": 18299097163 + }, + "parent_header": { + "excess_mana": 1320892278, + "mana_used": 95278001, + "proving_cost_per_mana_numerator": 100690211, + "fee_asset_price_numerator": 311174512 + }, + "header": { + "excess_mana": 1316170279, + "mana_used": 101936608, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 630116718 + }, + "oracle_input": { + "proving_cost_modifier": -154605323, + "fee_asset_price_modifier": 318942206 + }, + "outputs": { + "fee_asset_price_at_execution": 10031165916, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 60615759, + "proving_cost": 5420813436, + "congestion_cost": 20085126946, + "congestion_multiplier": 4664213516 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 608046735, + "proving_cost": 54377078976, + "congestion_cost": 201477240839, + "congestion_multiplier": 4664213516 + } + } + }, + { + "l1_block_number": 20973269, + "l1_fees": { + "blob_fee": 375, + "base_fee": 18189059913 + }, + "parent_header": { + "excess_mana": 1316170279, + "mana_used": 101936608, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 630116718 + }, + "header": { + "excess_mana": 1318106887, + "mana_used": 99042382, + "proving_cost_per_mana_numerator": 3337252, + "fee_asset_price_numerator": 195106265 + }, + "oracle_input": { + "proving_cost_modifier": 3337252, + "fee_asset_price_modifier": -435010453 + }, + "outputs": { + "fee_asset_price_at_execution": 10063210612, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 60251260, + "proving_cost": 5415357955, + "congestion_cost": 20121734902, + "congestion_multiplier": 4674793819 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 606321119, + "proving_cost": 54495887640, + "congestion_cost": 202489256197, + "congestion_multiplier": 4674793819 + } + } + }, + { + "l1_block_number": 20973272, + "l1_fees": { + "blob_fee": 361, + "base_fee": 17956791785 + }, + "parent_header": { + "excess_mana": 1318106887, + "mana_used": 99042382, + "proving_cost_per_mana_numerator": 3337252, + "fee_asset_price_numerator": 195106265 + }, + "header": { + "excess_mana": 1317149269, + "mana_used": 114460674, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -158447076, + "fee_asset_price_modifier": -941718501 + }, + "outputs": { + "fee_asset_price_at_execution": 10019529672, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 59481872, + "proving_cost": 5415538682, + "congestion_cost": 20090911237, + "congestion_multiplier": 4669559052 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 595980381, + "proving_cost": 54261150514, + "congestion_cost": 201301481276, + "congestion_multiplier": 4669559052 + } + } + }, + { + "l1_block_number": 20973275, + "l1_fees": { + "blob_fee": 422, + "base_fee": 18168683930 + }, + "parent_header": { + "excess_mana": 1317149269, + "mana_used": 114460674, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1331609943, + "mana_used": 101559769, + "proving_cost_per_mana_numerator": 21048022, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 21048022, + "fee_asset_price_modifier": -5887937 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 60183765, + "proving_cost": 5415357955, + "congestion_cost": 20529094799, + "congestion_multiplier": 4749235390 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 601837650, + "proving_cost": 54153579550, + "congestion_cost": 205290947990, + "congestion_multiplier": 4749235390 + } + } + }, + { + "l1_block_number": 20973278, + "l1_fees": { + "blob_fee": 422, + "base_fee": 17010109252 + }, + "parent_header": { + "excess_mana": 1331609943, + "mana_used": 101559769, + "proving_cost_per_mana_numerator": 21048022, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1333169712, + "mana_used": 102249578, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 515233807 + }, + "oracle_input": { + "proving_cost_modifier": -92908145, + "fee_asset_price_modifier": 515233807 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 56345986, + "proving_cost": 5416497900, + "congestion_cost": 20566456544, + "congestion_multiplier": 4757910324 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 563459860, + "proving_cost": 54164979000, + "congestion_cost": 205664565440, + "congestion_multiplier": 4757910324 + } + } + }, + { + "l1_block_number": 20973281, + "l1_fees": { + "blob_fee": 361, + "base_fee": 17657903515 + }, + "parent_header": { + "excess_mana": 1333169712, + "mana_used": 102249578, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 515233807 + }, + "header": { + "excess_mana": 1335419290, + "mana_used": 92477431, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -31551963, + "fee_asset_price_modifier": -549794876 + }, + "outputs": { + "fee_asset_price_at_execution": 10051656341, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 58491805, + "proving_cost": 5415357955, + "congestion_cost": 20638875014, + "congestion_multiplier": 4770449668 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 587939522, + "proving_cost": 54433317127, + "congestion_cost": 207454878905, + "congestion_multiplier": 4770449668 + } + } + }, + { + "l1_block_number": 20973284, + "l1_fees": { + "blob_fee": 422, + "base_fee": 18297705033 + }, + "parent_header": { + "excess_mana": 1335419290, + "mana_used": 92477431, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1327896721, + "mana_used": 96681271, + "proving_cost_per_mana_numerator": 79671009, + "fee_asset_price_numerator": 592774955 + }, + "oracle_input": { + "proving_cost_modifier": 79671009, + "fee_asset_price_modifier": 592774955 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 60611147, + "proving_cost": 5415357955, + "congestion_cost": 20417957054, + "congestion_multiplier": 4728647235 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 606111470, + "proving_cost": 54153579550, + "congestion_cost": 204179570540, + "congestion_multiplier": 4728647235 + } + } + }, + { + "l1_block_number": 20973287, + "l1_fees": { + "blob_fee": 361, + "base_fee": 19092004533 + }, + "parent_header": { + "excess_mana": 1327896721, + "mana_used": 96681271, + "proving_cost_per_mana_numerator": 79671009, + "fee_asset_price_numerator": 592774955 + }, + "header": { + "excess_mana": 1324577992, + "mana_used": 89190304, + "proving_cost_per_mana_numerator": 288691509, + "fee_asset_price_numerator": 1507728668 + }, + "oracle_input": { + "proving_cost_modifier": 209020500, + "fee_asset_price_modifier": 914953713 + }, + "outputs": { + "fee_asset_price_at_execution": 10059453534, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 63242265, + "proving_cost": 5419674144, + "congestion_cost": 20343384886, + "congestion_multiplier": 4710321910 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 636182626, + "proving_cost": 54518960220, + "congestion_cost": 204643334984, + "congestion_multiplier": 4710321910 + } + } + }, + { + "l1_block_number": 20973290, + "l1_fees": { + "blob_fee": 390, + "base_fee": 18698500008 + }, + "parent_header": { + "excess_mana": 1324577992, + "mana_used": 89190304, + "proving_cost_per_mana_numerator": 288691509, + "fee_asset_price_numerator": 1507728668 + }, + "header": { + "excess_mana": 1313768296, + "mana_used": 105278121, + "proving_cost_per_mana_numerator": 133541491, + "fee_asset_price_numerator": 1803567814 + }, + "oracle_input": { + "proving_cost_modifier": -155150018, + "fee_asset_price_modifier": 295839146 + }, + "outputs": { + "fee_asset_price_at_execution": 10151915223, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 61938781, + "proving_cost": 5431014221, + "congestion_cost": 20055452452, + "congestion_multiplier": 4651123984 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 628797253, + "proving_cost": 55135195946, + "congestion_cost": 203601253051, + "congestion_multiplier": 4651123984 + } + } + }, + { + "l1_block_number": 20973293, + "l1_fees": { + "blob_fee": 285, + "base_fee": 18642710735 + }, + "parent_header": { + "excess_mana": 1313768296, + "mana_used": 105278121, + "proving_cost_per_mana_numerator": 133541491, + "fee_asset_price_numerator": 1803567814 + }, + "header": { + "excess_mana": 1319046417, + "mana_used": 86926182, + "proving_cost_per_mana_numerator": 75741087, + "fee_asset_price_numerator": 2094753268 + }, + "oracle_input": { + "proving_cost_modifier": -57800404, + "fee_asset_price_modifier": 291185454 + }, + "outputs": { + "fee_asset_price_at_execution": 10181993031, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 61753979, + "proving_cost": 5422594535, + "congestion_cost": 20182048312, + "congestion_multiplier": 4679935412 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 628778583, + "proving_cost": 55212819765, + "congestion_cost": 205493475264, + "congestion_multiplier": 4679935412 + } + } + }, + { + "l1_block_number": 20973296, + "l1_fees": { + "blob_fee": 406, + "base_fee": 17157660059 + }, + "parent_header": { + "excess_mana": 1319046417, + "mana_used": 86926182, + "proving_cost_per_mana_numerator": 75741087, + "fee_asset_price_numerator": 2094753268 + }, + "header": { + "excess_mana": 1305972599, + "mana_used": 121671900, + "proving_cost_per_mana_numerator": 194735085, + "fee_asset_price_numerator": 1536756867 + }, + "oracle_input": { + "proving_cost_modifier": 118993998, + "fee_asset_price_modifier": -557996401 + }, + "outputs": { + "fee_asset_price_at_execution": 10211684722, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 56834748, + "proving_cost": 5419461159, + "congestion_cost": 19763372123, + "congestion_multiplier": 4608894124 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 580378527, + "proving_cost": 55341828718, + "congestion_cost": 201817325163, + "congestion_multiplier": 4608894124 + } + } + }, + { + "l1_block_number": 20973299, + "l1_fees": { + "blob_fee": 578, + "base_fee": 17844563894 + }, + "parent_header": { + "excess_mana": 1305972599, + "mana_used": 121671900, + "proving_cost_per_mana_numerator": 194735085, + "fee_asset_price_numerator": 1536756867 + }, + "header": { + "excess_mana": 1327644499, + "mana_used": 94239640, + "proving_cost_per_mana_numerator": 144284685, + "fee_asset_price_numerator": 1259440678 + }, + "oracle_input": { + "proving_cost_modifier": -50450400, + "fee_asset_price_modifier": -277316189 + }, + "outputs": { + "fee_asset_price_at_execution": 10154862569, + "mana_base_fee_components_in_wei": { + "data_cost": 2, + "gas_cost": 59110117, + "proving_cost": 5425913831, + "congestion_cost": 20444066586, + "congestion_multiplier": 4727252018 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 20, + "gas_cost": 600255114, + "proving_cost": 55099409265, + "congestion_cost": 207606686532, + "congestion_multiplier": 4727252018 + } + } + }, + { + "l1_block_number": 20973302, + "l1_fees": { + "blob_fee": 514, + "base_fee": 18350427669 + }, + "parent_header": { + "excess_mana": 1327644499, + "mana_used": 94239640, + "proving_cost_per_mana_numerator": 144284685, + "fee_asset_price_numerator": 1259440678 + }, + "header": { + "excess_mana": 1321884139, + "mana_used": 104298436, + "proving_cost_per_mana_numerator": 150042426, + "fee_asset_price_numerator": 714535872 + }, + "oracle_input": { + "proving_cost_modifier": 5757741, + "fee_asset_price_modifier": -544904806 + }, + "outputs": { + "fee_asset_price_at_execution": 10126740503, + "mana_base_fee_components_in_wei": { + "data_cost": 2, + "gas_cost": 60785791, + "proving_cost": 5423177126, + "congestion_cost": 20265980859, + "congestion_multiplier": 4695499251 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 20, + "gas_cost": 615561931, + "proving_cost": 54919107456, + "congestion_cost": 205228329197, + "congestion_multiplier": 4695499251 + } + } + }, + { + "l1_block_number": 20973305, + "l1_fees": { + "blob_fee": 556, + "base_fee": 18935369029 + }, + "parent_header": { + "excess_mana": 1321884139, + "mana_used": 104298436, + "proving_cost_per_mana_numerator": 150042426, + "fee_asset_price_numerator": 714535872 + }, + "header": { + "excess_mana": 1326182575, + "mana_used": 95940065, + "proving_cost_per_mana_numerator": 143665287, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -6377139, + "fee_asset_price_modifier": -730072379 + }, + "outputs": { + "fee_asset_price_at_execution": 10071709477, + "mana_base_fee_components_in_wei": { + "data_cost": 2, + "gas_cost": 62723409, + "proving_cost": 5423489388, + "congestion_cost": 20404175589, + "congestion_multiplier": 4719173196 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 20, + "gas_cost": 631731952, + "proving_cost": 54623809467, + "congestion_cost": 205504928650, + "congestion_multiplier": 4719173196 + } + } + }, + { + "l1_block_number": 20973308, + "l1_fees": { + "blob_fee": 494, + "base_fee": 18629157863 + }, + "parent_header": { + "excess_mana": 1326182575, + "mana_used": 95940065, + "proving_cost_per_mana_numerator": 143665287, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1322122640, + "mana_used": 118650737, + "proving_cost_per_mana_numerator": 27347406, + "fee_asset_price_numerator": 126873686 + }, + "oracle_input": { + "proving_cost_modifier": -116317881, + "fee_asset_price_modifier": 126873686 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 61709085, + "proving_cost": 5423143535, + "congestion_cost": 20276456344, + "congestion_multiplier": 4696809695 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 617090850, + "proving_cost": 54231435350, + "congestion_cost": 202764563440, + "congestion_multiplier": 4696809695 + } + } + }, + { + "l1_block_number": 20973311, + "l1_fees": { + "blob_fee": 556, + "base_fee": 17703911185 + }, + "parent_header": { + "excess_mana": 1322122640, + "mana_used": 118650737, + "proving_cost_per_mana_numerator": 27347406, + "fee_asset_price_numerator": 126873686 + }, + "header": { + "excess_mana": 1340773377, + "mana_used": 83539329, + "proving_cost_per_mana_numerator": 33755883, + "fee_asset_price_numerator": 330994440 + }, + "oracle_input": { + "proving_cost_modifier": 6408477, + "fee_asset_price_modifier": 204120754 + }, + "outputs": { + "fee_asset_price_at_execution": 10012695420, + "mana_base_fee_components_in_wei": { + "data_cost": 2, + "gas_cost": 58644205, + "proving_cost": 5416839117, + "congestion_cost": 20809174136, + "congestion_multiplier": 4800426904 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 20, + "gas_cost": 587186562, + "proving_cost": 54237160217, + "congestion_cost": 208355922565, + "congestion_multiplier": 4800426904 + } + } + }, + { + "l1_block_number": 20973314, + "l1_fees": { + "blob_fee": 625, + "base_fee": 19202542875 + }, + "parent_header": { + "excess_mana": 1340773377, + "mana_used": 83539329, + "proving_cost_per_mana_numerator": 33755883, + "fee_asset_price_numerator": 330994440 + }, + "header": { + "excess_mana": 1324312706, + "mana_used": 102397541, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 189252938 + }, + "oracle_input": { + "proving_cost_modifier": -191695900, + "fee_asset_price_modifier": -141741502 + }, + "outputs": { + "fee_asset_price_at_execution": 10033154283, + "mana_base_fee_components_in_wei": { + "data_cost": 2, + "gas_cost": 63608423, + "proving_cost": 5417186265, + "congestion_cost": 20327500884, + "congestion_multiplier": 4708860126 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 20, + "gas_cost": 638193121, + "proving_cost": 54351465576, + "congestion_cost": 203948952556, + "congestion_multiplier": 4708860126 + } + } + }, + { + "l1_block_number": 20973317, + "l1_fees": { + "blob_fee": 556, + "base_fee": 20520058840 + }, + "parent_header": { + "excess_mana": 1324312706, + "mana_used": 102397541, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 189252938 + }, + "header": { + "excess_mana": 1326710247, + "mana_used": 58716486, + "proving_cost_per_mana_numerator": 92573408, + "fee_asset_price_numerator": 635898020 + }, + "oracle_input": { + "proving_cost_modifier": 92573408, + "fee_asset_price_modifier": 446645082 + }, + "outputs": { + "fee_asset_price_at_execution": 10018943213, + "mana_base_fee_components_in_wei": { + "data_cost": 2, + "gas_cost": 67972694, + "proving_cost": 5415357955, + "congestion_cost": 20409437028, + "congestion_multiplier": 4722087601 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 20, + "gas_cost": 681014561, + "proving_cost": 54256163829, + "congestion_cost": 204480990592, + "congestion_multiplier": 4722087601 + } + } + }, + { + "l1_block_number": 20973320, + "l1_fees": { + "blob_fee": 791, + "base_fee": 19995965669 + }, + "parent_header": { + "excess_mana": 1326710247, + "mana_used": 58716486, + "proving_cost_per_mana_numerator": 92573408, + "fee_asset_price_numerator": 635898020 + }, + "header": { + "excess_mana": 1285426733, + "mana_used": 121832935, + "proving_cost_per_mana_numerator": 160371045, + "fee_asset_price_numerator": 448986186 + }, + "oracle_input": { + "proving_cost_modifier": 67797637, + "fee_asset_price_modifier": -186911834 + }, + "outputs": { + "fee_asset_price_at_execution": 10063792414, + "mana_base_fee_components_in_wei": { + "data_cost": 3, + "gas_cost": 66236636, + "proving_cost": 5420373457, + "congestion_cost": 19199972338, + "congestion_multiplier": 4499423506 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 30, + "gas_cost": 666591754, + "proving_cost": 54549513277, + "congestion_cost": 193224535964, + "congestion_multiplier": 4499423506 + } + } + }, + { + "l1_block_number": 20973323, + "l1_fees": { + "blob_fee": 703, + "base_fee": 19348276407 + }, + "parent_header": { + "excess_mana": 1285426733, + "mana_used": 121832935, + "proving_cost_per_mana_numerator": 160371045, + "fee_asset_price_numerator": 448986186 + }, + "header": { + "excess_mana": 1307259668, + "mana_used": 107794157, + "proving_cost_per_mana_numerator": 101292328, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -59078717, + "fee_asset_price_modifier": -711503255 + }, + "outputs": { + "fee_asset_price_at_execution": 10044999563, + "mana_base_fee_components_in_wei": { + "data_cost": 2, + "gas_cost": 64091165, + "proving_cost": 5424049588, + "congestion_cost": 19844237501, + "congestion_multiplier": 4615839751 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 20, + "gas_cost": 643795724, + "proving_cost": 54484575741, + "congestion_cost": 199335357025, + "congestion_multiplier": 4615839751 + } + } + }, + { + "l1_block_number": 20973326, + "l1_fees": { + "blob_fee": 1002, + "base_fee": 19136803008 + }, + "parent_header": { + "excess_mana": 1307259668, + "mana_used": 107794157, + "proving_cost_per_mana_numerator": 101292328, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1315053825, + "mana_used": 104770501, + "proving_cost_per_mana_numerator": 67807403, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -33484925, + "fee_asset_price_modifier": -1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 3, + "gas_cost": 63390659, + "proving_cost": 5420846076, + "congestion_cost": 20062022743, + "congestion_multiplier": 4658124859 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 30, + "gas_cost": 633906590, + "proving_cost": 54208460760, + "congestion_cost": 200620227430, + "congestion_multiplier": 4658124859 + } + } + }, + { + "l1_block_number": 20973329, + "l1_fees": { + "blob_fee": 1127, + "base_fee": 19212580019 + }, + "parent_header": { + "excess_mana": 1315053825, + "mana_used": 104770501, + "proving_cost_per_mana_numerator": 67807403, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1319824326, + "mana_used": 97876951, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -111587454, + "fee_asset_price_modifier": -215251746 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 4, + "gas_cost": 63641671, + "proving_cost": 5419031213, + "congestion_cost": 20199245969, + "congestion_multiplier": 4684196811 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 40, + "gas_cost": 636416710, + "proving_cost": 54190312130, + "congestion_cost": 201992459690, + "congestion_multiplier": 4684196811 + } + } + }, + { + "l1_block_number": 20973332, + "l1_fees": { + "blob_fee": 1172, + "base_fee": 20277424411 + }, + "parent_header": { + "excess_mana": 1319824326, + "mana_used": 97876951, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1317701277, + "mana_used": 46254371, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -99796762, + "fee_asset_price_modifier": -683803507 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 4, + "gas_cost": 67168968, + "proving_cost": 5415357955, + "congestion_cost": 20134996032, + "congestion_multiplier": 4672575858 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 40, + "gas_cost": 671689680, + "proving_cost": 54153579550, + "congestion_cost": 201349960320, + "congestion_multiplier": 4672575858 + } + } + }, + { + "l1_block_number": 20973335, + "l1_fees": { + "blob_fee": 1268, + "base_fee": 19528446485 + }, + "parent_header": { + "excess_mana": 1317701277, + "mana_used": 46254371, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1263955648, + "mana_used": 134292665, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 63367084 + }, + "oracle_input": { + "proving_cost_modifier": -100537926, + "fee_asset_price_modifier": 63367084 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 4, + "gas_cost": 64687978, + "proving_cost": 5415357955, + "congestion_cost": 18565303154, + "congestion_multiplier": 4387800644 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 40, + "gas_cost": 646879780, + "proving_cost": 54153579550, + "congestion_cost": 185653031540, + "congestion_multiplier": 4387800644 + } + } + }, + { + "l1_block_number": 20973338, + "l1_fees": { + "blob_fee": 1372, + "base_fee": 19587243385 + }, + "parent_header": { + "excess_mana": 1263955648, + "mana_used": 134292665, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 63367084 + }, + "header": { + "excess_mana": 1298248313, + "mana_used": 120510766, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -209476542, + "fee_asset_price_modifier": -928399810 + }, + "outputs": { + "fee_asset_price_at_execution": 10006338716, + "mana_base_fee_components_in_wei": { + "data_cost": 5, + "gas_cost": 64882743, + "proving_cost": 5415357955, + "congestion_cost": 19550371183, + "congestion_multiplier": 4567429287 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 50, + "gas_cost": 649238703, + "proving_cost": 54187905966, + "congestion_cost": 195627636080, + "congestion_multiplier": 4567429287 + } + } + }, + { + "l1_block_number": 20973341, + "l1_fees": { + "blob_fee": 1736, + "base_fee": 18965878234 + }, + "parent_header": { + "excess_mana": 1298248313, + "mana_used": 120510766, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1318759079, + "mana_used": 108139250, + "proving_cost_per_mana_numerator": 96857364, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 96857364, + "fee_asset_price_modifier": -933894862 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 6, + "gas_cost": 62824471, + "proving_cost": 5415357955, + "congestion_cost": 20150740009, + "congestion_multiplier": 4678362351 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 60, + "gas_cost": 628244710, + "proving_cost": 54153579550, + "congestion_cost": 201507400090, + "congestion_multiplier": 4678362351 + } + } + }, + { + "l1_block_number": 20973344, + "l1_fees": { + "blob_fee": 1543, + "base_fee": 18373599419 + }, + "parent_header": { + "excess_mana": 1318759079, + "mana_used": 108139250, + "proving_cost_per_mana_numerator": 96857364, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1326898329, + "mana_used": 98216650, + "proving_cost_per_mana_numerator": 222484067, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 125626703, + "fee_asset_price_modifier": -619139751 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 6, + "gas_cost": 60862548, + "proving_cost": 5420605668, + "congestion_cost": 20408201454, + "congestion_multiplier": 4723126839 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 60, + "gas_cost": 608625480, + "proving_cost": 54206056680, + "congestion_cost": 204082014540, + "congestion_multiplier": 4723126839 + } + } + }, + { + "l1_block_number": 20973347, + "l1_fees": { + "blob_fee": 1669, + "base_fee": 18117964296 + }, + "parent_header": { + "excess_mana": 1326898329, + "mana_used": 98216650, + "proving_cost_per_mana_numerator": 222484067, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1325114979, + "mana_used": 99643547, + "proving_cost_per_mana_numerator": 268172405, + "fee_asset_price_numerator": 562767444 + }, + "oracle_input": { + "proving_cost_modifier": 45688338, + "fee_asset_price_modifier": 562767444 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 6, + "gas_cost": 60015756, + "proving_cost": 5427419676, + "congestion_cost": 20376396428, + "congestion_multiplier": 4713282217 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 60, + "gas_cost": 600157560, + "proving_cost": 54274196760, + "congestion_cost": 203763964280, + "congestion_multiplier": 4713282217 + } + } + }, + { + "l1_block_number": 20973350, + "l1_fees": { + "blob_fee": 1484, + "base_fee": 18635391729 + }, + "parent_header": { + "excess_mana": 1325114979, + "mana_used": 99643547, + "proving_cost_per_mana_numerator": 268172405, + "fee_asset_price_numerator": 562767444 + }, + "header": { + "excess_mana": 1324758526, + "mana_used": 94493495, + "proving_cost_per_mana_numerator": 275475534, + "fee_asset_price_numerator": 55546249 + }, + "oracle_input": { + "proving_cost_modifier": 7303129, + "fee_asset_price_modifier": -507221195 + }, + "outputs": { + "fee_asset_price_at_execution": 10056435395, + "mana_base_fee_components_in_wei": { + "data_cost": 5, + "gas_cost": 61729735, + "proving_cost": 5429899940, + "congestion_cost": 20381178325, + "congestion_multiplier": 4711316952 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 50, + "gas_cost": 620781091, + "proving_cost": 54605437947, + "congestion_cost": 204962003099, + "congestion_multiplier": 4711316952 + } + } + }, + { + "l1_block_number": 20973353, + "l1_fees": { + "blob_fee": 1669, + "base_fee": 17699124203 + }, + "parent_header": { + "excess_mana": 1324758526, + "mana_used": 94493495, + "proving_cost_per_mana_numerator": 275475534, + "fee_asset_price_numerator": 55546249 + }, + "header": { + "excess_mana": 1319252021, + "mana_used": 40141150, + "proving_cost_per_mana_numerator": 60908371, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -214567163, + "fee_asset_price_modifier": -205759070 + }, + "outputs": { + "fee_asset_price_at_execution": 10005556167, + "mana_base_fee_components_in_wei": { + "data_cost": 6, + "gas_cost": 58628348, + "proving_cost": 5430296507, + "congestion_cost": 20205069087, + "congestion_multiplier": 4681061337 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 60, + "gas_cost": 586609228, + "proving_cost": 54333136704, + "congestion_cost": 202162953608, + "congestion_multiplier": 4681061337 + } + } + }, + { + "l1_block_number": 20973356, + "l1_fees": { + "blob_fee": 1878, + "base_fee": 19049659164 + }, + "parent_header": { + "excess_mana": 1319252021, + "mana_used": 40141150, + "proving_cost_per_mana_numerator": 60908371, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1259393171, + "mana_used": 139643833, + "proving_cost_per_mana_numerator": 23579480, + "fee_asset_price_numerator": 554264977 + }, + "oracle_input": { + "proving_cost_modifier": -37328891, + "fee_asset_price_modifier": 554264977 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 7, + "gas_cost": 63101995, + "proving_cost": 5418657366, + "congestion_cost": 18443053437, + "congestion_multiplier": 4364440538 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 70, + "gas_cost": 631019950, + "proving_cost": 54186573660, + "congestion_cost": 184430534370, + "congestion_multiplier": 4364440538 + } + } + }, + { + "l1_block_number": 20973359, + "l1_fees": { + "blob_fee": 2113, + "base_fee": 17952935112 + }, + "parent_header": { + "excess_mana": 1259393171, + "mana_used": 139643833, + "proving_cost_per_mana_numerator": 23579480, + "fee_asset_price_numerator": 554264977 + }, + "header": { + "excess_mana": 1299037004, + "mana_used": 107564368, + "proving_cost_per_mana_numerator": 83622719, + "fee_asset_price_numerator": 563075097 + }, + "oracle_input": { + "proving_cost_modifier": 60043239, + "fee_asset_price_modifier": 8810120 + }, + "outputs": { + "fee_asset_price_at_execution": 10055580386, + "mana_base_fee_components_in_wei": { + "data_cost": 8, + "gas_cost": 59469097, + "proving_cost": 5416635018, + "congestion_cost": 19558704904, + "congestion_multiplier": 4571645912 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 80, + "gas_cost": 597996285, + "proving_cost": 54467408845, + "congestion_cost": 196674129408, + "congestion_multiplier": 4571645912 + } + } + }, + { + "l1_block_number": 20973362, + "l1_fees": { + "blob_fee": 2377, + "base_fee": 17889199584 + }, + "parent_header": { + "excess_mana": 1299037004, + "mana_used": 107564368, + "proving_cost_per_mana_numerator": 83622719, + "fee_asset_price_numerator": 563075097 + }, + "header": { + "excess_mana": 1306601372, + "mana_used": 101620485, + "proving_cost_per_mana_numerator": 229458629, + "fee_asset_price_numerator": 494396072 + }, + "oracle_input": { + "proving_cost_modifier": 145835910, + "fee_asset_price_modifier": -68679025 + }, + "outputs": { + "fee_asset_price_at_execution": 10056466334, + "mana_base_fee_components_in_wei": { + "data_cost": 9, + "gas_cost": 59257973, + "proving_cost": 5419888318, + "congestion_cost": 19792243312, + "congestion_multiplier": 4612285971 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 90, + "gas_cost": 595925810, + "proving_cost": 54504924404, + "congestion_cost": 199040028541, + "congestion_multiplier": 4612285971 + } + } + }, + { + "l1_block_number": 20973365, + "l1_fees": { + "blob_fee": 2571, + "base_fee": 19972641950 + }, + "parent_header": { + "excess_mana": 1306601372, + "mana_used": 101620485, + "proving_cost_per_mana_numerator": 229458629, + "fee_asset_price_numerator": 494396072 + }, + "header": { + "excess_mana": 1308221857, + "mana_used": 94418152, + "proving_cost_per_mana_numerator": 141959240, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -87499389, + "fee_asset_price_modifier": -885807858 + }, + "outputs": { + "fee_asset_price_at_execution": 10049562022, + "mana_base_fee_components_in_wei": { + "data_cost": 10, + "gas_cost": 66159376, + "proving_cost": 5427798228, + "congestion_cost": 19893834839, + "congestion_multiplier": 4621039010 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 100, + "gas_cost": 664872752, + "proving_cost": 54546994935, + "congestion_cost": 199924327069, + "congestion_multiplier": 4621039010 + } + } + }, + { + "l1_block_number": 20973368, + "l1_fees": { + "blob_fee": 3661, + "base_fee": 19697758125 + }, + "parent_header": { + "excess_mana": 1308221857, + "mana_used": 94418152, + "proving_cost_per_mana_numerator": 141959240, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1302640009, + "mana_used": 101926798, + "proving_cost_per_mana_numerator": 156388847, + "fee_asset_price_numerator": 697009676 + }, + "oracle_input": { + "proving_cost_modifier": 14429607, + "fee_asset_price_modifier": 697009676 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 14, + "gas_cost": 65248823, + "proving_cost": 5423051015, + "congestion_cost": 19708256647, + "congestion_multiplier": 4590958435 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 140, + "gas_cost": 652488230, + "proving_cost": 54230510150, + "congestion_cost": 197082566470, + "congestion_multiplier": 4590958435 + } + } + }, + { + "l1_block_number": 20973371, + "l1_fees": { + "blob_fee": 4118, + "base_fee": 18752355505 + }, + "parent_header": { + "excess_mana": 1302640009, + "mana_used": 101926798, + "proving_cost_per_mana_numerator": 156388847, + "fee_asset_price_numerator": 697009676 + }, + "header": { + "excess_mana": 1304566807, + "mana_used": 115778581, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1399718159 + }, + "oracle_input": { + "proving_cost_modifier": -161415172, + "fee_asset_price_modifier": 702708483 + }, + "outputs": { + "fee_asset_price_at_execution": 10069944444, + "mana_base_fee_components_in_wei": { + "data_cost": 16, + "gas_cost": 62117177, + "proving_cost": 5423833596, + "congestion_cost": 19756662945, + "congestion_multiplier": 4601319754 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 161, + "gas_cost": 625516521, + "proving_cost": 54617702985, + "congestion_cost": 198948498254, + "congestion_multiplier": 4601319754 + } + } + }, + { + "l1_block_number": 20973374, + "l1_fees": { + "blob_fee": 5864, + "base_fee": 18133633771 + }, + "parent_header": { + "excess_mana": 1304566807, + "mana_used": 115778581, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1399718159 + }, + "header": { + "excess_mana": 1320345388, + "mana_used": 101438272, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 592952138 + }, + "oracle_input": { + "proving_cost_modifier": -154381148, + "fee_asset_price_modifier": -806766021 + }, + "outputs": { + "fee_asset_price_at_execution": 10140956007, + "mana_base_fee_components_in_wei": { + "data_cost": 23, + "gas_cost": 60067661, + "proving_cost": 5415357955, + "congestion_cost": 20188186538, + "congestion_multiplier": 4687053367 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 233, + "gas_cost": 609143507, + "proving_cost": 54916906783, + "congestion_cost": 204727511542, + "congestion_multiplier": 4687053367 + } + } + }, + { + "l1_block_number": 20973377, + "l1_fees": { + "blob_fee": 6099, + "base_fee": 18370080806 + }, + "parent_header": { + "excess_mana": 1320345388, + "mana_used": 101438272, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 592952138 + }, + "header": { + "excess_mana": 1321783660, + "mana_used": 97073818, + "proving_cost_per_mana_numerator": 32850276, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 32850276, + "fee_asset_price_modifier": -629066323 + }, + "outputs": { + "fee_asset_price_at_execution": 10059471357, + "mana_base_fee_components_in_wei": { + "data_cost": 23, + "gas_cost": 60850892, + "proving_cost": 5415357955, + "congestion_cost": 20234303063, + "congestion_multiplier": 4694947279 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 231, + "gas_cost": 612127805, + "proving_cost": 54475638236, + "congestion_cost": 203546392091, + "congestion_multiplier": 4694947279 + } + } + }, + { + "l1_block_number": 20973380, + "l1_fees": { + "blob_fee": 5421, + "base_fee": 18504594480 + }, + "parent_header": { + "excess_mana": 1321783660, + "mana_used": 97073818, + "proving_cost_per_mana_numerator": 32850276, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1318857478, + "mana_used": 100868624, + "proving_cost_per_mana_numerator": 99918728, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 67068452, + "fee_asset_price_modifier": -125217171 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 21, + "gas_cost": 61296469, + "proving_cost": 5417137207, + "congestion_cost": 20154615135, + "congestion_multiplier": 4678900987 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 210, + "gas_cost": 612964690, + "proving_cost": 54171372070, + "congestion_cost": 201546151350, + "congestion_multiplier": 4678900987 + } + } + }, + { + "l1_block_number": 20973383, + "l1_fees": { + "blob_fee": 6343, + "base_fee": 17141190330 + }, + "parent_header": { + "excess_mana": 1318857478, + "mana_used": 100868624, + "proving_cost_per_mana_numerator": 99918728, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1319726102, + "mana_used": 99789829, + "proving_cost_per_mana_numerator": 72115258, + "fee_asset_price_numerator": 318131719 + }, + "oracle_input": { + "proving_cost_modifier": -27803470, + "fee_asset_price_modifier": 318131719 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 24, + "gas_cost": 56780192, + "proving_cost": 5420771615, + "congestion_cost": 20177430492, + "congestion_multiplier": 4683658524 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 240, + "gas_cost": 567801920, + "proving_cost": 54207716150, + "congestion_cost": 201774304920, + "congestion_multiplier": 4683658524 + } + } + }, + { + "l1_block_number": 20973386, + "l1_fees": { + "blob_fee": 7136, + "base_fee": 15977836153 + }, + "parent_header": { + "excess_mana": 1319726102, + "mana_used": 99789829, + "proving_cost_per_mana_numerator": 72115258, + "fee_asset_price_numerator": 318131719 + }, + "header": { + "excess_mana": 1319515931, + "mana_used": 109710155, + "proving_cost_per_mana_numerator": 89852123, + "fee_asset_price_numerator": 331643801 + }, + "oracle_input": { + "proving_cost_modifier": 17736865, + "fee_asset_price_modifier": 13512082 + }, + "outputs": { + "fee_asset_price_at_execution": 10031863829, + "mana_base_fee_components_in_wei": { + "data_cost": 28, + "gas_cost": 52926582, + "proving_cost": 5419264662, + "congestion_cost": 20151382412, + "congestion_multiplier": 4682506954 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 280, + "gas_cost": 530952263, + "proving_cost": 54365325142, + "congestion_cost": 202155924323, + "congestion_multiplier": 4682506954 + } + } + }, + { + "l1_block_number": 20973389, + "l1_fees": { + "blob_fee": 6343, + "base_fee": 18525791343 + }, + "parent_header": { + "excess_mana": 1319515931, + "mana_used": 109710155, + "proving_cost_per_mana_numerator": 89852123, + "fee_asset_price_numerator": 331643801 + }, + "header": { + "excess_mana": 1329226086, + "mana_used": 112920909, + "proving_cost_per_mana_numerator": 220131378, + "fee_asset_price_numerator": 572844933 + }, + "oracle_input": { + "proving_cost_modifier": 130279255, + "fee_asset_price_modifier": 241201132 + }, + "outputs": { + "fee_asset_price_at_execution": 10033219434, + "mana_base_fee_components_in_wei": { + "data_cost": 24, + "gas_cost": 61366683, + "proving_cost": 5420225955, + "congestion_cost": 20479272349, + "congestion_multiplier": 4736007692 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 240, + "gas_cost": 615705396, + "proving_cost": 54382316388, + "congestion_cost": 205473033326, + "congestion_multiplier": 4736007692 + } + } + }, + { + "l1_block_number": 20973392, + "l1_fees": { + "blob_fee": 5638, + "base_fee": 19690491466 + }, + "parent_header": { + "excess_mana": 1329226086, + "mana_used": 112920909, + "proving_cost_per_mana_numerator": 220131378, + "fee_asset_price_numerator": 572844933 + }, + "header": { + "excess_mana": 1342146995, + "mana_used": 97817168, + "proving_cost_per_mana_numerator": 191036242, + "fee_asset_price_numerator": 616910498 + }, + "oracle_input": { + "proving_cost_modifier": -29095136, + "fee_asset_price_modifier": 44065565 + }, + "outputs": { + "fee_asset_price_at_execution": 10057448882, + "mana_base_fee_components_in_wei": { + "data_cost": 22, + "gas_cost": 65224752, + "proving_cost": 5427291987, + "congestion_cost": 20916316888, + "congestion_multiplier": 4808148031 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 221, + "gas_cost": 655994609, + "proving_cost": 54584711726, + "congestion_cost": 210364787900, + "congestion_multiplier": 4808148031 + } + } + }, + { + "l1_block_number": 20973395, + "l1_fees": { + "blob_fee": 6343, + "base_fee": 20475655040 + }, + "parent_header": { + "excess_mana": 1342146995, + "mana_used": 97817168, + "proving_cost_per_mana_numerator": 191036242, + "fee_asset_price_numerator": 616910498 + }, + "header": { + "excess_mana": 1339964163, + "mana_used": 90562122, + "proving_cost_per_mana_numerator": 184355731, + "fee_asset_price_numerator": 493961965 + }, + "oracle_input": { + "proving_cost_modifier": -6680511, + "fee_asset_price_modifier": -122948533 + }, + "outputs": { + "fee_asset_price_at_execution": 10061881730, + "mana_base_fee_components_in_wei": { + "data_cost": 24, + "gas_cost": 67825607, + "proving_cost": 5425713139, + "congestion_cost": 20852836497, + "congestion_multiplier": 4795884105 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 241, + "gas_cost": 682453235, + "proving_cost": 54592883905, + "congestion_cost": 209818774567, + "congestion_multiplier": 4795884105 + } + } + }, + { + "l1_block_number": 20973398, + "l1_fees": { + "blob_fee": 7136, + "base_fee": 18119718386 + }, + "parent_header": { + "excess_mana": 1339964163, + "mana_used": 90562122, + "proving_cost_per_mana_numerator": 184355731, + "fee_asset_price_numerator": 493961965 + }, + "header": { + "excess_mana": 1330526285, + "mana_used": 96393394, + "proving_cost_per_mana_numerator": 47505824, + "fee_asset_price_numerator": 152096606 + }, + "oracle_input": { + "proving_cost_modifier": -136849907, + "fee_asset_price_modifier": -341865359 + }, + "outputs": { + "fee_asset_price_at_execution": 10049518396, + "mana_base_fee_components_in_wei": { + "data_cost": 28, + "gas_cost": 60021567, + "proving_cost": 5425350686, + "congestion_cost": 20532942860, + "congestion_multiplier": 4743217745 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 281, + "gas_cost": 603187841, + "proving_cost": 54522161523, + "congestion_cost": 206346186995, + "congestion_multiplier": 4743217745 + } + } + }, + { + "l1_block_number": 20973401, + "l1_fees": { + "blob_fee": 9393, + "base_fee": 18420060434 + }, + "parent_header": { + "excess_mana": 1330526285, + "mana_used": 96393394, + "proving_cost_per_mana_numerator": 47505824, + "fee_asset_price_numerator": 152096606 + }, + "header": { + "excess_mana": 1326919679, + "mana_used": 80950635, + "proving_cost_per_mana_numerator": 158293696, + "fee_asset_price_numerator": 254761933 + }, + "oracle_input": { + "proving_cost_modifier": 110787872, + "fee_asset_price_modifier": 102665327 + }, + "outputs": { + "fee_asset_price_at_execution": 10015221233, + "mana_base_fee_components_in_wei": { + "data_cost": 36, + "gas_cost": 61016450, + "proving_cost": 5417931176, + "congestion_cost": 20399463512, + "congestion_multiplier": 4723244822 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 360, + "gas_cost": 611093245, + "proving_cost": 54261779352, + "congestion_cost": 204305140107, + "congestion_multiplier": 4723244822 + } + } + }, + { + "l1_block_number": 20973404, + "l1_fees": { + "blob_fee": 9032, + "base_fee": 18056451924 + }, + "parent_header": { + "excess_mana": 1326919679, + "mana_used": 80950635, + "proving_cost_per_mana_numerator": 158293696, + "fee_asset_price_numerator": 254761933 + }, + "header": { + "excess_mana": 1307870314, + "mana_used": 104359267, + "proving_cost_per_mana_numerator": 3583324, + "fee_asset_price_numerator": 32654620 + }, + "oracle_input": { + "proving_cost_modifier": -154710372, + "fee_asset_price_modifier": -222107313 + }, + "outputs": { + "fee_asset_price_at_execution": 10025508672, + "mana_base_fee_components_in_wei": { + "data_cost": 35, + "gas_cost": 59811996, + "proving_cost": 5423936913, + "congestion_cost": 19846448260, + "congestion_multiplier": 4619138743 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 350, + "gas_cost": 599645684, + "proving_cost": 54377726557, + "congestion_cost": 198970739139, + "congestion_multiplier": 4619138743 + } + } + }, + { + "l1_block_number": 20973407, + "l1_fees": { + "blob_fee": 8350, + "base_fee": 18137301254 + }, + "parent_header": { + "excess_mana": 1307870314, + "mana_used": 104359267, + "proving_cost_per_mana_numerator": 3583324, + "fee_asset_price_numerator": 32654620 + }, + "header": { + "excess_mana": 1312229581, + "mana_used": 104159990, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 629122643 + }, + "oracle_input": { + "proving_cost_modifier": -24449045, + "fee_asset_price_modifier": 596468023 + }, + "outputs": { + "fee_asset_price_at_execution": 10003265995, + "mana_base_fee_components_in_wei": { + "data_cost": 32, + "gas_cost": 60079810, + "proving_cost": 5415552008, + "congestion_cost": 19946402356, + "congestion_multiplier": 4642758115 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 320, + "gas_cost": 600994320, + "proving_cost": 54173207245, + "congestion_cost": 199529168410, + "congestion_multiplier": 4642758115 + } + } + }, + { + "l1_block_number": 20973410, + "l1_fees": { + "blob_fee": 7719, + "base_fee": 17694593322 + }, + "parent_header": { + "excess_mana": 1312229581, + "mana_used": 104159990, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 629122643 + }, + "header": { + "excess_mana": 1316389571, + "mana_used": 100721544, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -1988703, + "fee_asset_price_modifier": -660845787 + }, + "outputs": { + "fee_asset_price_at_execution": 10063110577, + "mana_base_fee_components_in_wei": { + "data_cost": 30, + "gas_cost": 58613340, + "proving_cost": 5415357955, + "congestion_cost": 20064351281, + "congestion_multiplier": 4665410374 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 301, + "gas_cost": 589832521, + "proving_cost": 54495345915, + "congestion_cost": 201909785596, + "congestion_multiplier": 4665410374 + } + } + }, + { + "l1_block_number": 20973413, + "l1_fees": { + "blob_fee": 7422, + "base_fee": 17130338099 + }, + "parent_header": { + "excess_mana": 1316389571, + "mana_used": 100721544, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1317111115, + "mana_used": 98622363, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -70656247, + "fee_asset_price_modifier": -322344917 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 29, + "gas_cost": 56744244, + "proving_cost": 5415357955, + "congestion_cost": 20079061631, + "congestion_multiplier": 4669350607 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 290, + "gas_cost": 567442440, + "proving_cost": 54153579550, + "congestion_cost": 200790616310, + "congestion_multiplier": 4669350607 + } + } + }, + { + "l1_block_number": 20973416, + "l1_fees": { + "blob_fee": 7422, + "base_fee": 16184100257 + }, + "parent_header": { + "excess_mana": 1317111115, + "mana_used": 98622363, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1315733478, + "mana_used": 100888431, + "proving_cost_per_mana_numerator": 3503723, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 3503723, + "fee_asset_price_modifier": -870786204 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 29, + "gas_cost": 53609832, + "proving_cost": 5415357955, + "congestion_cost": 20026432851, + "congestion_multiplier": 4661830445 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 290, + "gas_cost": 536098320, + "proving_cost": 54153579550, + "congestion_cost": 200264328510, + "congestion_multiplier": 4661830445 + } + } + }, + { + "l1_block_number": 20973419, + "l1_fees": { + "blob_fee": 5864, + "base_fee": 15185448051 + }, + "parent_header": { + "excess_mana": 1315733478, + "mana_used": 100888431, + "proving_cost_per_mana_numerator": 3503723, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1316621909, + "mana_used": 94491057, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -61497457, + "fee_asset_price_modifier": -550404902 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 23, + "gas_cost": 50301796, + "proving_cost": 5415547697, + "congestion_cost": 20041514385, + "congestion_multiplier": 4666678771 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 230, + "gas_cost": 503017960, + "proving_cost": 54155476970, + "congestion_cost": 200415143850, + "congestion_multiplier": 4666678771 + } + } + }, + { + "l1_block_number": 20973422, + "l1_fees": { + "blob_fee": 7422, + "base_fee": 15575959350 + }, + "parent_header": { + "excess_mana": 1316621909, + "mana_used": 94491057, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1311112966, + "mana_used": 107964581, + "proving_cost_per_mana_numerator": 81072380, + "fee_asset_price_numerator": 56425732 + }, + "oracle_input": { + "proving_cost_modifier": 81072380, + "fee_asset_price_modifier": 56425732 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 29, + "gas_cost": 51595365, + "proving_cost": 5415357955, + "congestion_cost": 19881650612, + "congestion_multiplier": 4636696592 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 290, + "gas_cost": 515953650, + "proving_cost": 54153579550, + "congestion_cost": 198816506120, + "congestion_multiplier": 4636696592 + } + } + }, + { + "l1_block_number": 20973425, + "l1_fees": { + "blob_fee": 7422, + "base_fee": 16430884636 + }, + "parent_header": { + "excess_mana": 1311112966, + "mana_used": 107964581, + "proving_cost_per_mana_numerator": 81072380, + "fee_asset_price_numerator": 56425732 + }, + "header": { + "excess_mana": 1319077547, + "mana_used": 100806765, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -218500226, + "fee_asset_price_modifier": -122148504 + }, + "outputs": { + "fee_asset_price_at_execution": 10005644165, + "mana_base_fee_components_in_wei": { + "data_cost": 29, + "gas_cost": 54427305, + "proving_cost": 5419750094, + "congestion_cost": 20145552480, + "congestion_multiplier": 4680105869 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 290, + "gas_cost": 544580246, + "proving_cost": 54228090903, + "congestion_cost": 201569229622, + "congestion_multiplier": 4680105869 + } + } + }, + { + "l1_block_number": 20973428, + "l1_fees": { + "blob_fee": 8028, + "base_fee": 16321037138 + }, + "parent_header": { + "excess_mana": 1319077547, + "mana_used": 100806765, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1319884312, + "mana_used": 101075675, + "proving_cost_per_mana_numerator": 196535371, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 196535371, + "fee_asset_price_modifier": -861438231 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 31, + "gas_cost": 54063435, + "proving_cost": 5415357955, + "congestion_cost": 20152223111, + "congestion_multiplier": 4684525576 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 310, + "gas_cost": 540634350, + "proving_cost": 54153579550, + "congestion_cost": 201522231110, + "congestion_multiplier": 4684525576 + } + } + }, + { + "l1_block_number": 20973431, + "l1_fees": { + "blob_fee": 9393, + "base_fee": 16122514868 + }, + "parent_header": { + "excess_mana": 1319884312, + "mana_used": 101075675, + "proving_cost_per_mana_numerator": 196535371, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1320959987, + "mana_used": 100604576, + "proving_cost_per_mana_numerator": 210400315, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 13864944, + "fee_asset_price_modifier": -310116113 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 36, + "gas_cost": 53405830, + "proving_cost": 5426011514, + "congestion_cost": 20221378610, + "congestion_multiplier": 4690424950 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 360, + "gas_cost": 534058300, + "proving_cost": 54260115140, + "congestion_cost": 202213786100, + "congestion_multiplier": 4690424950 + } + } + }, + { + "l1_block_number": 20973434, + "l1_fees": { + "blob_fee": 12365, + "base_fee": 16014219091 + }, + "parent_header": { + "excess_mana": 1320959987, + "mana_used": 100604576, + "proving_cost_per_mana_numerator": 210400315, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1321564563, + "mana_used": 103203146, + "proving_cost_per_mana_numerator": 270784851, + "fee_asset_price_numerator": 184588769 + }, + "oracle_input": { + "proving_cost_modifier": 60384536, + "fee_asset_price_modifier": 184588769 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 48, + "gas_cost": 53047100, + "proving_cost": 5426763880, + "congestion_cost": 20241018634, + "congestion_multiplier": 4693743914 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 480, + "gas_cost": 530471000, + "proving_cost": 54267638800, + "congestion_cost": 202410186340, + "congestion_multiplier": 4693743914 + } + } + }, + { + "l1_block_number": 20973437, + "l1_fees": { + "blob_fee": 10568, + "base_fee": 15999039375 + }, + "parent_header": { + "excess_mana": 1321564563, + "mana_used": 103203146, + "proving_cost_per_mana_numerator": 270784851, + "fee_asset_price_numerator": 184588769 + }, + "header": { + "excess_mana": 1324767709, + "mana_used": 103564808, + "proving_cost_per_mana_numerator": 148275372, + "fee_asset_price_numerator": 706703095 + }, + "oracle_input": { + "proving_cost_modifier": -122509479, + "fee_asset_price_modifier": 522114326 + }, + "outputs": { + "fee_asset_price_at_execution": 10018475923, + "mana_base_fee_components_in_wei": { + "data_cost": 41, + "gas_cost": 52996817, + "proving_cost": 5430041795, + "congestion_cost": 20349571847, + "congestion_multiplier": 4711367571 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 410, + "gas_cost": 530947335, + "proving_cost": 54400742984, + "congestion_cost": 203871695592, + "congestion_multiplier": 4711367571 + } + } + }, + { + "l1_block_number": 20973440, + "l1_fees": { + "blob_fee": 12365, + "base_fee": 15287943997 + }, + "parent_header": { + "excess_mana": 1324767709, + "mana_used": 103564808, + "proving_cost_per_mana_numerator": 148275372, + "fee_asset_price_numerator": 706703095 + }, + "header": { + "excess_mana": 1328332517, + "mana_used": 83509824, + "proving_cost_per_mana_numerator": 210001776, + "fee_asset_price_numerator": 1706703095 + }, + "oracle_input": { + "proving_cost_modifier": 61726404, + "fee_asset_price_modifier": 1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10070920613, + "mana_base_fee_components_in_wei": { + "data_cost": 48, + "gas_cost": 50641314, + "proving_cost": 5423393553, + "congestion_cost": 20423946683, + "congestion_multiplier": 4731058899 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 483, + "gas_cost": 510004653, + "proving_cost": 54618565925, + "congestion_cost": 205687945648, + "congestion_multiplier": 4731058899 + } + } + }, + { + "l1_block_number": 20973443, + "l1_fees": { + "blob_fee": 11889, + "base_fee": 16054573592 + }, + "parent_header": { + "excess_mana": 1328332517, + "mana_used": 83509824, + "proving_cost_per_mana_numerator": 210001776, + "fee_asset_price_numerator": 1706703095 + }, + "header": { + "excess_mana": 1311842341, + "mana_used": 102290817, + "proving_cost_per_mana_numerator": 251023939, + "fee_asset_price_numerator": 931130184 + }, + "oracle_input": { + "proving_cost_modifier": 41022163, + "fee_asset_price_modifier": -775572911 + }, + "outputs": { + "fee_asset_price_at_execution": 10172135048, + "mana_base_fee_components_in_wei": { + "data_cost": 46, + "gas_cost": 53180775, + "proving_cost": 5426742252, + "congestion_cost": 19950509844, + "congestion_multiplier": 4640655093 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 467, + "gas_cost": 540962025, + "proving_cost": 55201555058, + "congestion_cost": 202939280409, + "congestion_multiplier": 4640655093 + } + } + }, + { + "l1_block_number": 20973446, + "l1_fees": { + "blob_fee": 13910, + "base_fee": 15218141837 + }, + "parent_header": { + "excess_mana": 1311842341, + "mana_used": 102290817, + "proving_cost_per_mana_numerator": 251023939, + "fee_asset_price_numerator": 931130184 + }, + "header": { + "excess_mana": 1314133158, + "mana_used": 65360376, + "proving_cost_per_mana_numerator": 398208983, + "fee_asset_price_numerator": 981642141 + }, + "oracle_input": { + "proving_cost_modifier": 147185044, + "fee_asset_price_modifier": 50511957 + }, + "outputs": { + "fee_asset_price_at_execution": 10093547868, + "mana_base_fee_components_in_wei": { + "data_cost": 54, + "gas_cost": 50410094, + "proving_cost": 5428968876, + "congestion_cost": 20016773868, + "congestion_multiplier": 4653109920 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 545, + "gas_cost": 508816696, + "proving_cost": 54797557223, + "congestion_cost": 202040265199, + "congestion_multiplier": 4653109920 + } + } + }, + { + "l1_block_number": 20973449, + "l1_fees": { + "blob_fee": 16276, + "base_fee": 13615000865 + }, + "parent_header": { + "excess_mana": 1314133158, + "mana_used": 65360376, + "proving_cost_per_mana_numerator": 398208983, + "fee_asset_price_numerator": 981642141 + }, + "header": { + "excess_mana": 1279493534, + "mana_used": 139029355, + "proving_cost_per_mana_numerator": 374671734, + "fee_asset_price_numerator": 931807111 + }, + "oracle_input": { + "proving_cost_modifier": -23537249, + "fee_asset_price_modifier": -49835030 + }, + "outputs": { + "fee_asset_price_at_execution": 10098647605, + "mana_base_fee_components_in_wei": { + "data_cost": 63, + "gas_cost": 45099690, + "proving_cost": 5436965389, + "congestion_cost": 19013432147, + "congestion_multiplier": 4468297376 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 636, + "gas_cost": 455445876, + "proving_cost": 54905997504, + "congestion_cost": 192009951014, + "congestion_multiplier": 4468297376 + } + } + }, + { + "l1_block_number": 20973452, + "l1_fees": { + "blob_fee": 12365, + "base_fee": 15419645270 + }, + "parent_header": { + "excess_mana": 1279493534, + "mana_used": 139029355, + "proving_cost_per_mana_numerator": 374671734, + "fee_asset_price_numerator": 931807111 + }, + "header": { + "excess_mana": 1318522889, + "mana_used": 111326678, + "proving_cost_per_mana_numerator": 418751286, + "fee_asset_price_numerator": 1920185324 + }, + "oracle_input": { + "proving_cost_modifier": 44079552, + "fee_asset_price_modifier": 988378213 + }, + "outputs": { + "fee_asset_price_at_execution": 10093616194, + "mana_base_fee_components_in_wei": { + "data_cost": 48, + "gas_cost": 51077574, + "proving_cost": 5435685828, + "congestion_cost": 20175211633, + "congestion_multiplier": 4677069700 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 484, + "gas_cost": 515557428, + "proving_cost": 54865726498, + "congestion_cost": 203640842856, + "congestion_multiplier": 4677069700 + } + } + }, + { + "l1_block_number": 20973455, + "l1_fees": { + "blob_fee": 11889, + "base_fee": 14609143504 + }, + "parent_header": { + "excess_mana": 1318522889, + "mana_used": 111326678, + "proving_cost_per_mana_numerator": 418751286, + "fee_asset_price_numerator": 1920185324 + }, + "header": { + "excess_mana": 1329849567, + "mana_used": 88606966, + "proving_cost_per_mana_numerator": 415078001, + "fee_asset_price_numerator": 1682521585 + }, + "oracle_input": { + "proving_cost_modifier": -3673285, + "fee_asset_price_modifier": -237663739 + }, + "outputs": { + "fee_asset_price_at_execution": 10193873944, + "mana_base_fee_components_in_wei": { + "data_cost": 46, + "gas_cost": 48392787, + "proving_cost": 5438082382, + "congestion_cost": 20516475132, + "congestion_multiplier": 4739463741 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 468, + "gas_cost": 493309970, + "proving_cost": 55435126299, + "congestion_cost": 209142361270, + "congestion_multiplier": 4739463741 + } + } + }, + { + "l1_block_number": 20973458, + "l1_fees": { + "blob_fee": 9770, + "base_fee": 15085608411 + }, + "parent_header": { + "excess_mana": 1329849567, + "mana_used": 88606966, + "proving_cost_per_mana_numerator": 415078001, + "fee_asset_price_numerator": 1682521585 + }, + "header": { + "excess_mana": 1318456533, + "mana_used": 102801105, + "proving_cost_per_mana_numerator": 429004476, + "fee_asset_price_numerator": 2444732238 + }, + "oracle_input": { + "proving_cost_modifier": 13926475, + "fee_asset_price_modifier": 762210653 + }, + "outputs": { + "fee_asset_price_at_execution": 10169675569, + "mana_base_fee_components_in_wei": { + "data_cost": 38, + "gas_cost": 49971077, + "proving_cost": 5437882629, + "congestion_cost": 20177228091, + "congestion_multiplier": 4676706602 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 386, + "gas_cost": 508189640, + "proving_cost": 55301502119, + "congestion_cost": 205195863567, + "congestion_multiplier": 4676706602 + } + } + }, + { + "l1_block_number": 20973461, + "l1_fees": { + "blob_fee": 11431, + "base_fee": 14312834898 + }, + "parent_header": { + "excess_mana": 1318456533, + "mana_used": 102801105, + "proving_cost_per_mana_numerator": 429004476, + "fee_asset_price_numerator": 2444732238 + }, + "header": { + "excess_mana": 1321257638, + "mana_used": 98200479, + "proving_cost_per_mana_numerator": 378149572, + "fee_asset_price_numerator": 2307269582 + }, + "oracle_input": { + "proving_cost_modifier": -50854904, + "fee_asset_price_modifier": -137462656 + }, + "outputs": { + "fee_asset_price_at_execution": 10247486083, + "mana_base_fee_components_in_wei": { + "data_cost": 44, + "gas_cost": 47411265, + "proving_cost": 5438639987, + "congestion_cost": 20254823317, + "congestion_multiplier": 4692058682 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 450, + "gas_cost": 485846278, + "proving_cost": 55732387577, + "congestion_cost": 207561020054, + "congestion_multiplier": 4692058682 + } + } + }, + { + "l1_block_number": 20973464, + "l1_fees": { + "blob_fee": 13375, + "base_fee": 14648933305 + }, + "parent_header": { + "excess_mana": 1321257638, + "mana_used": 98200479, + "proving_cost_per_mana_numerator": 378149572, + "fee_asset_price_numerator": 2307269582 + }, + "header": { + "excess_mana": 1319458117, + "mana_used": 111026869, + "proving_cost_per_mana_numerator": 466968694, + "fee_asset_price_numerator": 3297800050 + }, + "oracle_input": { + "proving_cost_modifier": 88819122, + "fee_asset_price_modifier": 990530468 + }, + "outputs": { + "fee_asset_price_at_execution": 10233409294, + "mana_base_fee_components_in_wei": { + "data_cost": 52, + "gas_cost": 48524591, + "proving_cost": 5435874875, + "congestion_cost": 20194602317, + "congestion_multiplier": 4682190229 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 532, + "gas_cost": 496572000, + "proving_cost": 55627532466, + "congestion_cost": 206659631039, + "congestion_multiplier": 4682190229 + } + } + }, + { + "l1_block_number": 20973467, + "l1_fees": { + "blob_fee": 12365, + "base_fee": 14460098285 + }, + "parent_header": { + "excess_mana": 1319458117, + "mana_used": 111026869, + "proving_cost_per_mana_numerator": 466968694, + "fee_asset_price_numerator": 3297800050 + }, + "header": { + "excess_mana": 1330484986, + "mana_used": 89014895, + "proving_cost_per_mana_numerator": 569856216, + "fee_asset_price_numerator": 3100410811 + }, + "oracle_input": { + "proving_cost_modifier": 102887522, + "fee_asset_price_modifier": -197389239 + }, + "outputs": { + "fee_asset_price_at_execution": 10335278018, + "mana_base_fee_components_in_wei": { + "data_cost": 48, + "gas_cost": 47899075, + "proving_cost": 5440705116, + "congestion_cost": 20543782871, + "congestion_multiplier": 4742988559 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 496, + "gas_cost": 495050256, + "proving_cost": 56231199987, + "congestion_cost": 212325707513, + "congestion_multiplier": 4742988559 + } + } + }, + { + "l1_block_number": 20973470, + "l1_fees": { + "blob_fee": 9393, + "base_fee": 13977736089 + }, + "parent_header": { + "excess_mana": 1330484986, + "mana_used": 89014895, + "proving_cost_per_mana_numerator": 569856216, + "fee_asset_price_numerator": 3100410811 + }, + "header": { + "excess_mana": 1319499881, + "mana_used": 86837462, + "proving_cost_per_mana_numerator": 400019914, + "fee_asset_price_numerator": 2376944353 + }, + "oracle_input": { + "proving_cost_modifier": -169836302, + "fee_asset_price_modifier": -723466458 + }, + "outputs": { + "fee_asset_price_at_execution": 10314897413, + "mana_base_fee_components_in_wei": { + "data_cost": 36, + "gas_cost": 46301250, + "proving_cost": 5446305804, + "congestion_cost": 20226080839, + "congestion_multiplier": 4682419024 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 371, + "gas_cost": 477592643, + "proving_cost": 56178085648, + "congestion_cost": 208629948921, + "congestion_multiplier": 4682419024 + } + } + }, + { + "l1_block_number": 20973473, + "l1_fees": { + "blob_fee": 10161, + "base_fee": 13453174678 + }, + "parent_header": { + "excess_mana": 1319499881, + "mana_used": 86837462, + "proving_cost_per_mana_numerator": 400019914, + "fee_asset_price_numerator": 2376944353 + }, + "header": { + "excess_mana": 1306337343, + "mana_used": 110299037, + "proving_cost_per_mana_numerator": 433582759, + "fee_asset_price_numerator": 2738803177 + }, + "oracle_input": { + "proving_cost_modifier": 33562845, + "fee_asset_price_modifier": 361858824 + }, + "outputs": { + "fee_asset_price_at_execution": 10240541883, + "mana_base_fee_components_in_wei": { + "data_cost": 39, + "gas_cost": 44563641, + "proving_cost": 5437063850, + "congestion_cost": 19793397213, + "congestion_multiplier": 4610861392 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 399, + "gas_cost": 456355832, + "proving_cost": 55678480076, + "congestion_cost": 202695113166, + "congestion_multiplier": 4610861392 + } + } + }, + { + "l1_block_number": 20973476, + "l1_fees": { + "blob_fee": 9032, + "base_fee": 13408774809 + }, + "parent_header": { + "excess_mana": 1306337343, + "mana_used": 110299037, + "proving_cost_per_mana_numerator": 433582759, + "fee_asset_price_numerator": 2738803177 + }, + "header": { + "excess_mana": 1316636380, + "mana_used": 103749155, + "proving_cost_per_mana_numerator": 508162696, + "fee_asset_price_numerator": 1738803177 + }, + "oracle_input": { + "proving_cost_modifier": 74579937, + "fee_asset_price_modifier": -1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10277665314, + "mana_base_fee_components_in_wei": { + "data_cost": 35, + "gas_cost": 44416566, + "proving_cost": 5438888989, + "congestion_cost": 20105953448, + "congestion_multiplier": 4666757783 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 359, + "gas_cost": 456498599, + "proving_cost": 55899080708, + "congestion_cost": 206642260357, + "congestion_multiplier": 4666757783 + } + } + }, + { + "l1_block_number": 20973479, + "l1_fees": { + "blob_fee": 9032, + "base_fee": 12441369415 + }, + "parent_header": { + "excess_mana": 1316636380, + "mana_used": 103749155, + "proving_cost_per_mana_numerator": 508162696, + "fee_asset_price_numerator": 1738803177 + }, + "header": { + "excess_mana": 1320385535, + "mana_used": 95638144, + "proving_cost_per_mana_numerator": 427579520, + "fee_asset_price_numerator": 1939889114 + }, + "oracle_input": { + "proving_cost_modifier": -80583176, + "fee_asset_price_modifier": 201085937 + }, + "outputs": { + "fee_asset_price_at_execution": 10175400836, + "mana_base_fee_components_in_wei": { + "data_cost": 35, + "gas_cost": 41212036, + "proving_cost": 5442946822, + "congestion_cost": 20221593936, + "congestion_multiplier": 4687273533 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 356, + "gas_cost": 419348985, + "proving_cost": 55384165642, + "congestion_cost": 205762823841, + "congestion_multiplier": 4687273533 + } + } + }, + { + "l1_block_number": 20973482, + "l1_fees": { + "blob_fee": 8350, + "base_fee": 13666269945 + }, + "parent_header": { + "excess_mana": 1320385535, + "mana_used": 95638144, + "proving_cost_per_mana_numerator": 427579520, + "fee_asset_price_numerator": 1939889114 + }, + "header": { + "excess_mana": 1316023679, + "mana_used": 90637725, + "proving_cost_per_mana_numerator": 357292279, + "fee_asset_price_numerator": 1840626366 + }, + "oracle_input": { + "proving_cost_modifier": -70287241, + "fee_asset_price_modifier": -99262748 + }, + "outputs": { + "fee_asset_price_at_execution": 10195882722, + "mana_base_fee_components_in_wei": { + "data_cost": 32, + "gas_cost": 45269519, + "proving_cost": 5438562490, + "congestion_cost": 20089544709, + "congestion_multiplier": 4663413569 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 326, + "gas_cost": 461562706, + "proving_cost": 55450945324, + "congestion_cost": 204830641791, + "congestion_multiplier": 4663413569 + } + } + }, + { + "l1_block_number": 20973485, + "l1_fees": { + "blob_fee": 10991, + "base_fee": 14378775361 + }, + "parent_header": { + "excess_mana": 1316023679, + "mana_used": 90637725, + "proving_cost_per_mana_numerator": 357292279, + "fee_asset_price_numerator": 1840626366 + }, + "header": { + "excess_mana": 1306661404, + "mana_used": 122727699, + "proving_cost_per_mana_numerator": 551873296, + "fee_asset_price_numerator": 2609752577 + }, + "oracle_input": { + "proving_cost_modifier": 194581017, + "fee_asset_price_modifier": 769126211 + }, + "outputs": { + "fee_asset_price_at_execution": 10185767030, + "mana_base_fee_components_in_wei": { + "data_cost": 43, + "gas_cost": 47629693, + "proving_cost": 5434741217, + "congestion_cost": 19805667788, + "congestion_multiplier": 4612609938 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 437, + "gas_cost": 485144956, + "proving_cost": 55357007904, + "congestion_cost": 201735917962, + "congestion_multiplier": 4612609938 + } + } + }, + { + "l1_block_number": 20973488, + "l1_fees": { + "blob_fee": 9770, + "base_fee": 14272987887 + }, + "parent_header": { + "excess_mana": 1306661404, + "mana_used": 122727699, + "proving_cost_per_mana_numerator": 551873296, + "fee_asset_price_numerator": 2609752577 + }, + "header": { + "excess_mana": 1329389103, + "mana_used": 99727233, + "proving_cost_per_mana_numerator": 285835544, + "fee_asset_price_numerator": 3084375033 + }, + "oracle_input": { + "proving_cost_modifier": -266037752, + "fee_asset_price_modifier": 474622456 + }, + "outputs": { + "fee_asset_price_at_execution": 10264410480, + "mana_base_fee_components_in_wei": { + "data_cost": 38, + "gas_cost": 47279272, + "proving_cost": 5445326487, + "congestion_cost": 20525379444, + "congestion_multiplier": 4736911077 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 390, + "gas_cost": 485293855, + "proving_cost": 55893066260, + "congestion_cost": 210680919870, + "congestion_multiplier": 4736911077 + } + } + }, + { + "l1_block_number": 20973491, + "l1_fees": { + "blob_fee": 9393, + "base_fee": 14695176958 + }, + "parent_header": { + "excess_mana": 1329389103, + "mana_used": 99727233, + "proving_cost_per_mana_numerator": 285835544, + "fee_asset_price_numerator": 3084375033 + }, + "header": { + "excess_mana": 1329116336, + "mana_used": 82105056, + "proving_cost_per_mana_numerator": 412888248, + "fee_asset_price_numerator": 3116627095 + }, + "oracle_input": { + "proving_cost_modifier": 127052704, + "fee_asset_price_modifier": 32252062 + }, + "outputs": { + "fee_asset_price_at_execution": 10313243472, + "mana_base_fee_components_in_wei": { + "data_cost": 36, + "gas_cost": 48677773, + "proving_cost": 5430859116, + "congestion_cost": 20468259993, + "congestion_multiplier": 4735399592 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 371, + "gas_cost": 502025724, + "proving_cost": 56009772325, + "congestion_cost": 211094148756, + "congestion_multiplier": 4735399592 + } + } + }, + { + "l1_block_number": 20973494, + "l1_fees": { + "blob_fee": 12860, + "base_fee": 14320169685 + }, + "parent_header": { + "excess_mana": 1329116336, + "mana_used": 82105056, + "proving_cost_per_mana_numerator": 412888248, + "fee_asset_price_numerator": 3116627095 + }, + "header": { + "excess_mana": 1311221392, + "mana_used": 93681672, + "proving_cost_per_mana_numerator": 304560378, + "fee_asset_price_numerator": 3756345736 + }, + "oracle_input": { + "proving_cost_modifier": -108327870, + "fee_asset_price_modifier": 639718641 + }, + "outputs": { + "fee_asset_price_at_execution": 10316570242, + "mana_base_fee_components_in_wei": { + "data_cost": 50, + "gas_cost": 47435562, + "proving_cost": 5437763554, + "congestion_cost": 19951231737, + "congestion_multiplier": 4637284834 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 515, + "gas_cost": 489372307, + "proving_cost": 56099069664, + "congestion_cost": 205828283629, + "congestion_multiplier": 4637284834 + } + } + }, + { + "l1_block_number": 20973497, + "l1_fees": { + "blob_fee": 14467, + "base_fee": 14624476597 + }, + "parent_header": { + "excess_mana": 1311221392, + "mana_used": 93681672, + "proving_cost_per_mana_numerator": 304560378, + "fee_asset_price_numerator": 3756345736 + }, + "header": { + "excess_mana": 1304903064, + "mana_used": 109568285, + "proving_cost_per_mana_numerator": 292493513, + "fee_asset_price_numerator": 4217767568 + }, + "oracle_input": { + "proving_cost_modifier": -12066865, + "fee_asset_price_modifier": 461421832 + }, + "outputs": { + "fee_asset_price_at_execution": 10382778813, + "mana_base_fee_components_in_wei": { + "data_cost": 56, + "gas_cost": 48443578, + "proving_cost": 5431876130, + "congestion_cost": 19746306546, + "congestion_multiplier": 4603130364 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 581, + "gas_cost": 502978955, + "proving_cost": 56397968397, + "congestion_cost": 205021533240, + "congestion_multiplier": 4603130364 + } + } + }, + { + "l1_block_number": 20973500, + "l1_fees": { + "blob_fee": 16276, + "base_fee": 15231641377 + }, + "parent_header": { + "excess_mana": 1304903064, + "mana_used": 109568285, + "proving_cost_per_mana_numerator": 292493513, + "fee_asset_price_numerator": 4217767568 + }, + "header": { + "excess_mana": 1314471349, + "mana_used": 102110913, + "proving_cost_per_mana_numerator": 267362944, + "fee_asset_price_numerator": 4455082919 + }, + "oracle_input": { + "proving_cost_modifier": -25130569, + "fee_asset_price_modifier": 237315351 + }, + "outputs": { + "fee_asset_price_at_execution": 10430797921, + "mana_base_fee_components_in_wei": { + "data_cost": 63, + "gas_cost": 50454812, + "proving_cost": 5431220713, + "congestion_cost": 20035258100, + "congestion_multiplier": 4654951443 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 657, + "gas_cost": 526283948, + "proving_cost": 56651965721, + "congestion_cost": 208983728536, + "congestion_multiplier": 4654951443 + } + } + }, + { + "l1_block_number": 20973503, + "l1_fees": { + "blob_fee": 16276, + "base_fee": 13996481627 + }, + "parent_header": { + "excess_mana": 1314471349, + "mana_used": 102110913, + "proving_cost_per_mana_numerator": 267362944, + "fee_asset_price_numerator": 4455082919 + }, + "header": { + "excess_mana": 1316582262, + "mana_used": 110421352, + "proving_cost_per_mana_numerator": 453360181, + "fee_asset_price_numerator": 4592575600 + }, + "oracle_input": { + "proving_cost_modifier": 185997237, + "fee_asset_price_modifier": 137492681 + }, + "outputs": { + "fee_asset_price_at_execution": 10455581202, + "mana_base_fee_components_in_wei": { + "data_cost": 63, + "gas_cost": 46363345, + "proving_cost": 5429855988, + "congestion_cost": 20078351978, + "congestion_multiplier": 4666462303 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 658, + "gas_cost": 484755718, + "proving_cost": 56772300197, + "congestion_cost": 209930839508, + "congestion_multiplier": 4666462303 + } + } + }, + { + "l1_block_number": 20973506, + "l1_fees": { + "blob_fee": 13375, + "base_fee": 13706103465 + }, + "parent_header": { + "excess_mana": 1316582262, + "mana_used": 110421352, + "proving_cost_per_mana_numerator": 453360181, + "fee_asset_price_numerator": 4592575600 + }, + "header": { + "excess_mana": 1327003614, + "mana_used": 108194469, + "proving_cost_per_mana_numerator": 374375618, + "fee_asset_price_numerator": 5151371732 + }, + "oracle_input": { + "proving_cost_modifier": -78984563, + "fee_asset_price_modifier": 558796132 + }, + "outputs": { + "fee_asset_price_at_execution": 10469966748, + "mana_base_fee_components_in_wei": { + "data_cost": 52, + "gas_cost": 45401467, + "proving_cost": 5439964768, + "congestion_cost": 20425906088, + "congestion_multiplier": 4723708686 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 544, + "gas_cost": 475351849, + "proving_cost": 56956250231, + "congestion_cost": 213858557539, + "congestion_multiplier": 4723708686 + } + } + }, + { + "l1_block_number": 20973509, + "l1_fees": { + "blob_fee": 16928, + "base_fee": 15294708227 + }, + "parent_header": { + "excess_mana": 1327003614, + "mana_used": 108194469, + "proving_cost_per_mana_numerator": 374375618, + "fee_asset_price_numerator": 5151371732 + }, + "header": { + "excess_mana": 1335198083, + "mana_used": 92861766, + "proving_cost_per_mana_numerator": 195541519, + "fee_asset_price_numerator": 5340082778 + }, + "oracle_input": { + "proving_cost_modifier": -178834099, + "fee_asset_price_modifier": 188711046 + }, + "outputs": { + "fee_asset_price_at_execution": 10528636286, + "mana_base_fee_components_in_wei": { + "data_cost": 66, + "gas_cost": 50663721, + "proving_cost": 5435669732, + "congestion_cost": 20679171565, + "congestion_multiplier": 4769215177 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 694, + "gas_cost": 533419891, + "proving_cost": 57230189579, + "congestion_cost": 217723476103, + "congestion_multiplier": 4769215177 + } + } + }, + { + "l1_block_number": 20973512, + "l1_fees": { + "blob_fee": 11889, + "base_fee": 16431846806 + }, + "parent_header": { + "excess_mana": 1335198083, + "mana_used": 92861766, + "proving_cost_per_mana_numerator": 195541519, + "fee_asset_price_numerator": 5340082778 + }, + "header": { + "excess_mana": 1328059849, + "mana_used": 88389595, + "proving_cost_per_mana_numerator": 283776529, + "fee_asset_price_numerator": 6340082778 + }, + "oracle_input": { + "proving_cost_modifier": 88235010, + "fee_asset_price_modifier": 1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10548523745, + "mana_base_fee_components_in_wei": { + "data_cost": 46, + "gas_cost": 54430492, + "proving_cost": 5425957588, + "congestion_cost": 20439380598, + "congestion_multiplier": 4729549829 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 485, + "gas_cost": 574161337, + "proving_cost": 57235842456, + "congestion_cost": 215605291571, + "congestion_multiplier": 4729549829 + } + } + }, + { + "l1_block_number": 20973515, + "l1_fees": { + "blob_fee": 12365, + "base_fee": 17477541478 + }, + "parent_header": { + "excess_mana": 1328059849, + "mana_used": 88389595, + "proving_cost_per_mana_numerator": 283776529, + "fee_asset_price_numerator": 6340082778 + }, + "header": { + "excess_mana": 1316449444, + "mana_used": 97332202, + "proving_cost_per_mana_numerator": 259044148, + "fee_asset_price_numerator": 7340082778 + }, + "oracle_input": { + "proving_cost_modifier": -24732381, + "fee_asset_price_modifier": 1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10654538171, + "mana_base_fee_components_in_wei": { + "data_cost": 48, + "gas_cost": 57894356, + "proving_cost": 5430747295, + "congestion_cost": 20119918075, + "congestion_multiplier": 4665737204 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 511, + "gas_cost": 616837625, + "proving_cost": 57862104351, + "congestion_cost": 214368435127, + "congestion_multiplier": 4665737204 + } + } + }, + { + "l1_block_number": 20973518, + "l1_fees": { + "blob_fee": 13375, + "base_fee": 15978208780 + }, + "parent_header": { + "excess_mana": 1316449444, + "mana_used": 97332202, + "proving_cost_per_mana_numerator": 259044148, + "fee_asset_price_numerator": 7340082778 + }, + "header": { + "excess_mana": 1313781646, + "mana_used": 107383104, + "proving_cost_per_mana_numerator": 285050814, + "fee_asset_price_numerator": 6978325524 + }, + "oracle_input": { + "proving_cost_modifier": 26006666, + "fee_asset_price_modifier": -361757254 + }, + "outputs": { + "fee_asset_price_at_execution": 10761618060, + "mana_base_fee_components_in_wei": { + "data_cost": 52, + "gas_cost": 52927816, + "proving_cost": 5429404308, + "congestion_cost": 20017072781, + "congestion_multiplier": 4651196633 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 559, + "gas_cost": 569588940, + "proving_cost": 58429175456, + "congestion_cost": 215416091948, + "congestion_multiplier": 4651196633 + } + } + }, + { + "l1_block_number": 20973521, + "l1_fees": { + "blob_fee": 9393, + "base_fee": 15694997319 + }, + "parent_header": { + "excess_mana": 1313781646, + "mana_used": 107383104, + "proving_cost_per_mana_numerator": 285050814, + "fee_asset_price_numerator": 6978325524 + }, + "header": { + "excess_mana": 1321164750, + "mana_used": 99195845, + "proving_cost_per_mana_numerator": 356671899, + "fee_asset_price_numerator": 6942005273 + }, + "oracle_input": { + "proving_cost_modifier": 71621085, + "fee_asset_price_modifier": -36320251 + }, + "outputs": { + "fee_asset_price_at_execution": 10722757459, + "mana_base_fee_components_in_wei": { + "data_cost": 36, + "gas_cost": 51989678, + "proving_cost": 5430816498, + "congestion_cost": 20240046593, + "congestion_multiplier": 4691548782 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 386, + "gas_cost": 557472707, + "proving_cost": 58233328112, + "congestion_cost": 217029110575, + "congestion_multiplier": 4691548782 + } + } + }, + { + "l1_block_number": 20973524, + "l1_fees": { + "blob_fee": 9770, + "base_fee": 16114710895 + }, + "parent_header": { + "excess_mana": 1321164750, + "mana_used": 99195845, + "proving_cost_per_mana_numerator": 356671899, + "fee_asset_price_numerator": 6942005273 + }, + "header": { + "excess_mana": 1320360595, + "mana_used": 75773539, + "proving_cost_per_mana_numerator": 236578589, + "fee_asset_price_numerator": 7295623463 + }, + "oracle_input": { + "proving_cost_modifier": -120093310, + "fee_asset_price_modifier": 353618190 + }, + "outputs": { + "fee_asset_price_at_execution": 10718863633, + "mana_base_fee_components_in_wei": { + "data_cost": 38, + "gas_cost": 53379979, + "proving_cost": 5434707501, + "congestion_cost": 20235329235, + "congestion_multiplier": 4687136761 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 407, + "gas_cost": 572172715, + "proving_cost": 58253888588, + "congestion_cost": 216899734638, + "congestion_multiplier": 4687136761 + } + } + }, + { + "l1_block_number": 20973527, + "l1_fees": { + "blob_fee": 9032, + "base_fee": 15193310536 + }, + "parent_header": { + "excess_mana": 1320360595, + "mana_used": 75773539, + "proving_cost_per_mana_numerator": 236578589, + "fee_asset_price_numerator": 7295623463 + }, + "header": { + "excess_mana": 1296134134, + "mana_used": 118152636, + "proving_cost_per_mana_numerator": 155286419, + "fee_asset_price_numerator": 7974068845 + }, + "oracle_input": { + "proving_cost_modifier": -81292170, + "fee_asset_price_modifier": 678445382 + }, + "outputs": { + "fee_asset_price_at_execution": 10756834581, + "mana_base_fee_components_in_wei": { + "data_cost": 35, + "gas_cost": 50327841, + "proving_cost": 5428184699, + "congestion_cost": 19482386766, + "congestion_multiplier": 4556145304 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 376, + "gas_cost": 541368260, + "proving_cost": 58390084882, + "congestion_cost": 209568811684, + "congestion_multiplier": 4556145304 + } + } + }, + { + "l1_block_number": 20973530, + "l1_fees": { + "blob_fee": 8028, + "base_fee": 15696924869 + }, + "parent_header": { + "excess_mana": 1296134134, + "mana_used": 118152636, + "proving_cost_per_mana_numerator": 155286419, + "fee_asset_price_numerator": 7974068845 + }, + "header": { + "excess_mana": 1314286770, + "mana_used": 112950187, + "proving_cost_per_mana_numerator": 121267759, + "fee_asset_price_numerator": 8775829688 + }, + "oracle_input": { + "proving_cost_modifier": -34018660, + "fee_asset_price_modifier": 801760843 + }, + "outputs": { + "fee_asset_price_at_execution": 10830061952, + "mana_base_fee_components_in_wei": { + "data_cost": 31, + "gas_cost": 51996063, + "proving_cost": 5423773803, + "congestion_cost": 20008169045, + "congestion_multiplier": 4653946280 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 335, + "gas_cost": 563120583, + "proving_cost": 58739806300, + "congestion_cost": 216689710303, + "congestion_multiplier": 4653946280 + } + } + }, + { + "l1_block_number": 20973533, + "l1_fees": { + "blob_fee": 6861, + "base_fee": 17589348647 + }, + "parent_header": { + "excess_mana": 1314286770, + "mana_used": 112950187, + "proving_cost_per_mana_numerator": 121267759, + "fee_asset_price_numerator": 8775829688 + }, + "header": { + "excess_mana": 1327236957, + "mana_used": 86247445, + "proving_cost_per_mana_numerator": 156972445, + "fee_asset_price_numerator": 9300867729 + }, + "oracle_input": { + "proving_cost_modifier": 35704686, + "fee_asset_price_modifier": 525038041 + }, + "outputs": { + "fee_asset_price_at_execution": 10917242169, + "mana_base_fee_components_in_wei": { + "data_cost": 26, + "gas_cost": 58264717, + "proving_cost": 5421929021, + "congestion_cost": 20413713484, + "congestion_multiplier": 4724998488 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 283, + "gas_cost": 636090025, + "proving_cost": 59192512145, + "congestion_cost": 222861453673, + "congestion_multiplier": 4724998488 + } + } + }, + { + "l1_block_number": 20973536, + "l1_fees": { + "blob_fee": 7422, + "base_fee": 21124868019 + }, + "parent_header": { + "excess_mana": 1327236957, + "mana_used": 86247445, + "proving_cost_per_mana_numerator": 156972445, + "fee_asset_price_numerator": 9300867729 + }, + "header": { + "excess_mana": 1313484402, + "mana_used": 93046450, + "proving_cost_per_mana_numerator": 67913921, + "fee_asset_price_numerator": 9836646214 + }, + "oracle_input": { + "proving_cost_modifier": -89058524, + "fee_asset_price_modifier": 535778485 + }, + "outputs": { + "fee_asset_price_at_execution": 10974712583, + "mana_base_fee_components_in_wei": { + "data_cost": 29, + "gas_cost": 69976125, + "proving_cost": 5423865250, + "congestion_cost": 20050210096, + "congestion_multiplier": 4649579342 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 318, + "gas_cost": 767967859, + "proving_cost": 59525362207, + "congestion_cost": 220045293032, + "congestion_multiplier": 4649579342 + } + } + }, + { + "l1_block_number": 20973539, + "l1_fees": { + "blob_fee": 6597, + "base_fee": 20799423931 + }, + "parent_header": { + "excess_mana": 1313484402, + "mana_used": 93046450, + "proving_cost_per_mana_numerator": 67913921, + "fee_asset_price_numerator": 9836646214 + }, + "header": { + "excess_mana": 1306530852, + "mana_used": 111312010, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 10091294188 + }, + "oracle_input": { + "proving_cost_modifier": -226866819, + "fee_asset_price_modifier": 254647974 + }, + "outputs": { + "fee_asset_price_at_execution": 11033670532, + "mana_base_fee_components_in_wei": { + "data_cost": 25, + "gas_cost": 68898091, + "proving_cost": 5419036986, + "congestion_cost": 19821902621, + "congestion_multiplier": 4611905435 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 275, + "gas_cost": 760198836, + "proving_cost": 59791868704, + "congestion_cost": 218708342837, + "congestion_multiplier": 4611905435 + } + } + }, + { + "l1_block_number": 20973542, + "l1_fees": { + "blob_fee": 5864, + "base_fee": 19793695587 + }, + "parent_header": { + "excess_mana": 1306530852, + "mana_used": 111312010, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 10091294188 + }, + "header": { + "excess_mana": 1317842862, + "mana_used": 104587798, + "proving_cost_per_mana_numerator": 19892327, + "fee_asset_price_numerator": 10346274506 + }, + "oracle_input": { + "proving_cost_modifier": 19892327, + "fee_asset_price_modifier": 254980318 + }, + "outputs": { + "fee_asset_price_at_execution": 11061803355, + "mana_base_fee_components_in_wei": { + "data_cost": 23, + "gas_cost": 65566616, + "proving_cost": 5415357955, + "congestion_cost": 20133354110, + "congestion_multiplier": 4673349955 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 254, + "gas_cost": 725285012, + "proving_cost": 59903624795, + "congestion_cost": 222711204041, + "congestion_multiplier": 4673349955 + } + } + }, + { + "l1_block_number": 20973545, + "l1_fees": { + "blob_fee": 6597, + "base_fee": 20094986128 + }, + "parent_header": { + "excess_mana": 1317842862, + "mana_used": 104587798, + "proving_cost_per_mana_numerator": 19892327, + "fee_asset_price_numerator": 10346274506 + }, + "header": { + "excess_mana": 1322430660, + "mana_used": 104970014, + "proving_cost_per_mana_numerator": 32749244, + "fee_asset_price_numerator": 9864976938 + }, + "oracle_input": { + "proving_cost_modifier": 12856917, + "fee_asset_price_modifier": -481297568 + }, + "outputs": { + "fee_asset_price_at_execution": 11090044767, + "mana_base_fee_components_in_wei": { + "data_cost": 25, + "gas_cost": 66564641, + "proving_cost": 5416435302, + "congestion_cost": 20278889922, + "congestion_multiplier": 4698502652 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 277, + "gas_cost": 738204848, + "proving_cost": 60068509976, + "congestion_cost": 224893797060, + "congestion_multiplier": 4698502652 + } + } + }, + { + "l1_block_number": 20973548, + "l1_fees": { + "blob_fee": 9393, + "base_fee": 18609737244 + }, + "parent_header": { + "excess_mana": 1322430660, + "mana_used": 104970014, + "proving_cost_per_mana_numerator": 32749244, + "fee_asset_price_numerator": 9864976938 + }, + "header": { + "excess_mana": 1327400674, + "mana_used": 52607414, + "proving_cost_per_mana_numerator": 81068013, + "fee_asset_price_numerator": 9361738499 + }, + "oracle_input": { + "proving_cost_modifier": 48318769, + "fee_asset_price_modifier": -503238439 + }, + "outputs": { + "fee_asset_price_at_execution": 11036796894, + "mana_base_fee_components_in_wei": { + "data_cost": 36, + "gas_cost": 61644754, + "proving_cost": 5417131734, + "congestion_cost": 20413393404, + "congestion_multiplier": 4725903642 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 397, + "gas_cost": 680360629, + "proving_cost": 59787782696, + "congestion_cost": 225298476917, + "congestion_multiplier": 4725903642 + } + } + }, + { + "l1_block_number": 20973551, + "l1_fees": { + "blob_fee": 11889, + "base_fee": 18614276755 + }, + "parent_header": { + "excess_mana": 1327400674, + "mana_used": 52607414, + "proving_cost_per_mana_numerator": 81068013, + "fee_asset_price_numerator": 9361738499 + }, + "header": { + "excess_mana": 1280008088, + "mana_used": 127805778, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 8901487473 + }, + "oracle_input": { + "proving_cost_modifier": -141528716, + "fee_asset_price_modifier": -460251026 + }, + "outputs": { + "fee_asset_price_at_execution": 10981395008, + "mana_base_fee_components_in_wei": { + "data_cost": 46, + "gas_cost": 61659791, + "proving_cost": 5419749858, + "congestion_cost": 19025908518, + "congestion_multiplier": 4470988227 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 505, + "gas_cost": 677110521, + "proving_cost": 59516414035, + "congestion_cost": 208931016822, + "congestion_multiplier": 4470988227 + } + } + }, + { + "l1_block_number": 20973554, + "l1_fees": { + "blob_fee": 10991, + "base_fee": 18020600851 + }, + "parent_header": { + "excess_mana": 1280008088, + "mana_used": 127805778, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 8901487473 + }, + "header": { + "excess_mana": 1307813866, + "mana_used": 94149668, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 8724451260 + }, + "oracle_input": { + "proving_cost_modifier": -63645948, + "fee_asset_price_modifier": -177036213 + }, + "outputs": { + "fee_asset_price_at_execution": 10930969157, + "mana_base_fee_components_in_wei": { + "data_cost": 43, + "gas_cost": 59693240, + "proving_cost": 5415357955, + "congestion_cost": 19813299852, + "congestion_multiplier": 4618833686 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 470, + "gas_cost": 652504965, + "proving_cost": 59195110780, + "congestion_cost": 216578569580, + "congestion_multiplier": 4618833686 + } + } + }, + { + "l1_block_number": 20973557, + "l1_fees": { + "blob_fee": 12365, + "base_fee": 18277826651 + }, + "parent_header": { + "excess_mana": 1307813866, + "mana_used": 94149668, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 8724451260 + }, + "header": { + "excess_mana": 1301963534, + "mana_used": 99444246, + "proving_cost_per_mana_numerator": 60729549, + "fee_asset_price_numerator": 8166861291 + }, + "oracle_input": { + "proving_cost_modifier": 60729549, + "fee_asset_price_modifier": -557589969 + }, + "outputs": { + "fee_asset_price_at_execution": 10911634503, + "mana_base_fee_components_in_wei": { + "data_cost": 48, + "gas_cost": 60545300, + "proving_cost": 5415357955, + "congestion_cost": 19643851606, + "congestion_multiplier": 4587326240 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 523, + "gas_cost": 660648184, + "proving_cost": 59090406707, + "congestion_cost": 214346528955, + "congestion_multiplier": 4587326240 + } + } + }, + { + "l1_block_number": 20973560, + "l1_fees": { + "blob_fee": 17605, + "base_fee": 17939510902 + }, + "parent_header": { + "excess_mana": 1301963534, + "mana_used": 99444246, + "proving_cost_per_mana_numerator": 60729549, + "fee_asset_price_numerator": 8166861291 + }, + "header": { + "excess_mana": 1301407780, + "mana_used": 116843419, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 8056731716 + }, + "oracle_input": { + "proving_cost_modifier": -133462995, + "fee_asset_price_modifier": -110129575 + }, + "outputs": { + "fee_asset_price_at_execution": 10850961633, + "mana_base_fee_components_in_wei": { + "data_cost": 69, + "gas_cost": 59424629, + "proving_cost": 5418647676, + "congestion_cost": 19635297943, + "congestion_multiplier": 4584344383 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 748, + "gas_cost": 644814369, + "proving_cost": 58797538035, + "congestion_cost": 213061864632, + "congestion_multiplier": 4584344383 + } + } + }, + { + "l1_block_number": 20973563, + "l1_fees": { + "blob_fee": 19806, + "base_fee": 17915455837 + }, + "parent_header": { + "excess_mana": 1301407780, + "mana_used": 116843419, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 8056731716 + }, + "header": { + "excess_mana": 1318251199, + "mana_used": 106156025, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 7883590148 + }, + "oracle_input": { + "proving_cost_modifier": -98037428, + "fee_asset_price_modifier": -173141568 + }, + "outputs": { + "fee_asset_price_at_execution": 10839018093, + "mana_base_fee_components_in_wei": { + "data_cost": 77, + "gas_cost": 59344947, + "proving_cost": 5415357955, + "congestion_cost": 20122726305, + "congestion_multiplier": 4675583202 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 834, + "gas_cost": 643240954, + "proving_cost": 58697162854, + "congestion_cost": 218110594500, + "congestion_multiplier": 4675583202 + } + } + }, + { + "l1_block_number": 20973566, + "l1_fees": { + "blob_fee": 16276, + "base_fee": 17059822050 + }, + "parent_header": { + "excess_mana": 1318251199, + "mana_used": 106156025, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 7883590148 + }, + "header": { + "excess_mana": 1324407224, + "mana_used": 91163155, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 7801958587 + }, + "oracle_input": { + "proving_cost_modifier": -13958851, + "fee_asset_price_modifier": -81631561 + }, + "outputs": { + "fee_asset_price_at_execution": 10820267485, + "mana_base_fee_components_in_wei": { + "data_cost": 63, + "gas_cost": 56510660, + "proving_cost": 5415357955, + "congestion_cost": 20297245101, + "congestion_multiplier": 4709380889 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 681, + "gas_cost": 611460456, + "proving_cost": 58595621600, + "congestion_cost": 219621621201, + "congestion_multiplier": 4709380889 + } + } + }, + { + "l1_block_number": 20973569, + "l1_fees": { + "blob_fee": 19806, + "base_fee": 16555278446 + }, + "parent_header": { + "excess_mana": 1324407224, + "mana_used": 91163155, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 7801958587 + }, + "header": { + "excess_mana": 1315570379, + "mana_used": 110308203, + "proving_cost_per_mana_numerator": 77408002, + "fee_asset_price_numerator": 7466434184 + }, + "oracle_input": { + "proving_cost_modifier": 77408002, + "fee_asset_price_modifier": -335524403 + }, + "outputs": { + "fee_asset_price_at_execution": 10811438336, + "mana_base_fee_components_in_wei": { + "data_cost": 77, + "gas_cost": 54839359, + "proving_cost": 5415357955, + "congestion_cost": 20026069534, + "congestion_multiplier": 4660940932 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 832, + "gas_cost": 592892348, + "proving_cost": 58547808597, + "congestion_cost": 216510615879, + "congestion_multiplier": 4660940932 + } + } + }, + { + "l1_block_number": 20973572, + "l1_fees": { + "blob_fee": 20599, + "base_fee": 16295282001 + }, + "parent_header": { + "excess_mana": 1315570379, + "mana_used": 110308203, + "proving_cost_per_mana_numerator": 77408002, + "fee_asset_price_numerator": 7466434184 + }, + "header": { + "excess_mana": 1325878582, + "mana_used": 110082615, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 7232729626 + }, + "oracle_input": { + "proving_cost_modifier": -205859688, + "fee_asset_price_modifier": -233704558 + }, + "outputs": { + "fee_asset_price_at_execution": 10775224109, + "mana_base_fee_components_in_wei": { + "data_cost": 80, + "gas_cost": 53978121, + "proving_cost": 5419551498, + "congestion_cost": 20347819386, + "congestion_multiplier": 4717495018 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 862, + "gas_cost": 581626350, + "proving_cost": 58396881961, + "congestion_cost": 219252314013, + "congestion_multiplier": 4717495018 + } + } + }, + { + "l1_block_number": 20973575, + "l1_fees": { + "blob_fee": 23174, + "base_fee": 15308679642 + }, + "parent_header": { + "excess_mana": 1325878582, + "mana_used": 110082615, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 7232729626 + }, + "header": { + "excess_mana": 1335961197, + "mana_used": 105815738, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 6254996440 + }, + "oracle_input": { + "proving_cost_modifier": -84442481, + "fee_asset_price_modifier": -977733186 + }, + "outputs": { + "fee_asset_price_at_execution": 10750071323, + "mana_base_fee_components_in_wei": { + "data_cost": 91, + "gas_cost": 50710001, + "proving_cost": 5415357955, + "congestion_cost": 20626072440, + "congestion_multiplier": 4773475241 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 978, + "gas_cost": 545136127, + "proving_cost": 58215484255, + "congestion_cost": 221731749843, + "congestion_multiplier": 4773475241 + } + } + }, + { + "l1_block_number": 20973578, + "l1_fees": { + "blob_fee": 23174, + "base_fee": 15069272311 + }, + "parent_header": { + "excess_mana": 1335961197, + "mana_used": 105815738, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 6254996440 + }, + "header": { + "excess_mana": 1341776935, + "mana_used": 95248719, + "proving_cost_per_mana_numerator": 40498148, + "fee_asset_price_numerator": 6365721613 + }, + "oracle_input": { + "proving_cost_modifier": 40498148, + "fee_asset_price_modifier": 110725173 + }, + "outputs": { + "fee_asset_price_at_execution": 10645476470, + "mana_base_fee_components_in_wei": { + "data_cost": 91, + "gas_cost": 49916964, + "proving_cost": 5415357955, + "congestion_cost": 20801201205, + "congestion_multiplier": 4806066697 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 968, + "gas_cost": 531389865, + "proving_cost": 57649065686, + "congestion_cost": 221438697975, + "congestion_multiplier": 4806066697 + } + } + }, + { + "l1_block_number": 20973581, + "l1_fees": { + "blob_fee": 23174, + "base_fee": 15303102977 + }, + "parent_header": { + "excess_mana": 1341776935, + "mana_used": 95248719, + "proving_cost_per_mana_numerator": 40498148, + "fee_asset_price_numerator": 6365721613 + }, + "header": { + "excess_mana": 1337025654, + "mana_used": 90408891, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 6906882271 + }, + "oracle_input": { + "proving_cost_modifier": -69662332, + "fee_asset_price_modifier": 541160658 + }, + "outputs": { + "fee_asset_price_at_execution": 10657270221, + "mana_base_fee_components_in_wei": { + "data_cost": 91, + "gas_cost": 50691528, + "proving_cost": 5417551518, + "congestion_cost": 20666808808, + "congestion_multiplier": 4779423901 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 969, + "gas_cost": 540233311, + "proving_cost": 57736310463, + "congestion_cost": 220251766072, + "congestion_multiplier": 4779423901 + } + } + }, + { + "l1_block_number": 20973584, + "l1_fees": { + "blob_fee": 20599, + "base_fee": 15137821864 + }, + "parent_header": { + "excess_mana": 1337025654, + "mana_used": 90408891, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 6906882271 + }, + "header": { + "excess_mana": 1327434545, + "mana_used": 95066489, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 6335884269 + }, + "oracle_input": { + "proving_cost_modifier": -141635049, + "fee_asset_price_modifier": -570998002 + }, + "outputs": { + "fee_asset_price_at_execution": 10715099508, + "mana_base_fee_components_in_wei": { + "data_cost": 80, + "gas_cost": 50144034, + "proving_cost": 5415357955, + "congestion_cost": 20364957681, + "congestion_multiplier": 4726090929 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 857, + "gas_cost": 537298314, + "proving_cost": 58026099359, + "congestion_cost": 218212548028, + "congestion_multiplier": 4726090929 + } + } + }, + { + "l1_block_number": 20973587, + "l1_fees": { + "blob_fee": 23174, + "base_fee": 15472115815 + }, + "parent_header": { + "excess_mana": 1327434545, + "mana_used": 95066489, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 6335884269 + }, + "header": { + "excess_mana": 1322501034, + "mana_used": 106900881, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 5626654198 + }, + "oracle_input": { + "proving_cost_modifier": -38760060, + "fee_asset_price_modifier": -709230071 + }, + "outputs": { + "fee_asset_price_at_execution": 10654090849, + "mana_base_fee_components_in_wei": { + "data_cost": 91, + "gas_cost": 51251383, + "proving_cost": 5415357955, + "congestion_cost": 20220384392, + "congestion_multiplier": 4698889532 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 969, + "gas_cost": 546036890, + "proving_cost": 57695715632, + "congestion_cost": 215429812314, + "congestion_multiplier": 4698889532 + } + } + }, + { + "l1_block_number": 20973590, + "l1_fees": { + "blob_fee": 19806, + "base_fee": 16177942905 + }, + "parent_header": { + "excess_mana": 1322501034, + "mana_used": 106900881, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 5626654198 + }, + "header": { + "excess_mana": 1329401915, + "mana_used": 100313077, + "proving_cost_per_mana_numerator": 57773876, + "fee_asset_price_numerator": 5720592720 + }, + "oracle_input": { + "proving_cost_modifier": 57773876, + "fee_asset_price_modifier": 93938522 + }, + "outputs": { + "fee_asset_price_at_execution": 10578796154, + "mana_base_fee_components_in_wei": { + "data_cost": 77, + "gas_cost": 53589435, + "proving_cost": 5415357955, + "congestion_cost": 20437358702, + "congestion_multiplier": 4736982084 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 814, + "gas_cost": 566911708, + "proving_cost": 57287967906, + "congestion_cost": 216202651634, + "congestion_multiplier": 4736982084 + } + } + }, + { + "l1_block_number": 20973593, + "l1_fees": { + "blob_fee": 17605, + "base_fee": 15631978451 + }, + "parent_header": { + "excess_mana": 1329401915, + "mana_used": 100313077, + "proving_cost_per_mana_numerator": 57773876, + "fee_asset_price_numerator": 5720592720 + }, + "header": { + "excess_mana": 1329714992, + "mana_used": 84502427, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 5666336427 + }, + "oracle_input": { + "proving_cost_modifier": -101826303, + "fee_asset_price_modifier": -54256293 + }, + "outputs": { + "fee_asset_price_at_execution": 10588738388, + "mana_base_fee_components_in_wei": { + "data_cost": 69, + "gas_cost": 51780928, + "proving_cost": 5418487521, + "congestion_cost": 20451788955, + "congestion_multiplier": 4738717558 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 730, + "gas_cost": 548294700, + "proving_cost": 57374946818, + "congestion_cost": 216558642811, + "congestion_multiplier": 4738717558 + } + } + }, + { + "l1_block_number": 20973596, + "l1_fees": { + "blob_fee": 14467, + "base_fee": 14200105654 + }, + "parent_header": { + "excess_mana": 1329714992, + "mana_used": 84502427, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 5666336427 + }, + "header": { + "excess_mana": 1314217419, + "mana_used": 111946924, + "proving_cost_per_mana_numerator": 92058319, + "fee_asset_price_numerator": 5034697877 + }, + "oracle_input": { + "proving_cost_modifier": 92058319, + "fee_asset_price_modifier": -631638550 + }, + "outputs": { + "fee_asset_price_at_execution": 10582994890, + "mana_base_fee_components_in_wei": { + "data_cost": 56, + "gas_cost": 47037849, + "proving_cost": 5415357955, + "congestion_cost": 19957238382, + "congestion_multiplier": 4653568671 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 592, + "gas_cost": 497801315, + "proving_cost": 57310705565, + "congestion_cost": 211207351815, + "congestion_multiplier": 4653568671 + } + } + }, + { + "l1_block_number": 20973599, + "l1_fees": { + "blob_fee": 19806, + "base_fee": 13624273988 + }, + "parent_header": { + "excess_mana": 1314217419, + "mana_used": 111946924, + "proving_cost_per_mana_numerator": 92058319, + "fee_asset_price_numerator": 5034697877 + }, + "header": { + "excess_mana": 1326164343, + "mana_used": 90155196, + "proving_cost_per_mana_numerator": 95464087, + "fee_asset_price_numerator": 5794889457 + }, + "oracle_input": { + "proving_cost_modifier": 3405768, + "fee_asset_price_modifier": 760191580 + }, + "outputs": { + "fee_asset_price_at_execution": 10516359284, + "mana_base_fee_components_in_wei": { + "data_cost": 77, + "gas_cost": 45130407, + "proving_cost": 5420345537, + "congestion_cost": 20326501733, + "congestion_multiplier": 4719072530 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 809, + "gas_cost": 474607574, + "proving_cost": 57002301110, + "congestion_cost": 213760795211, + "congestion_multiplier": 4719072530 + } + } + }, + { + "l1_block_number": 20973602, + "l1_fees": { + "blob_fee": 21424, + "base_fee": 14061825642 + }, + "parent_header": { + "excess_mana": 1326164343, + "mana_used": 90155196, + "proving_cost_per_mana_numerator": 95464087, + "fee_asset_price_numerator": 5794889457 + }, + "header": { + "excess_mana": 1316319539, + "mana_used": 101203237, + "proving_cost_per_mana_numerator": 65367598, + "fee_asset_price_numerator": 6106040447 + }, + "oracle_input": { + "proving_cost_modifier": -30096489, + "fee_asset_price_modifier": 311150990 + }, + "outputs": { + "fee_asset_price_at_execution": 10596608399, + "mana_base_fee_components_in_wei": { + "data_cost": 84, + "gas_cost": 46579797, + "proving_cost": 5420530145, + "congestion_cost": 20037111969, + "congestion_multiplier": 4665028118 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 890, + "gas_cost": 493587868, + "proving_cost": 57439235261, + "congestion_cost": 212325428982, + "congestion_multiplier": 4665028118 + } + } + }, + { + "l1_block_number": 20973605, + "l1_fees": { + "blob_fee": 16928, + "base_fee": 14532060269 + }, + "parent_header": { + "excess_mana": 1316319539, + "mana_used": 101203237, + "proving_cost_per_mana_numerator": 65367598, + "fee_asset_price_numerator": 6106040447 + }, + "header": { + "excess_mana": 1317522776, + "mana_used": 91749672, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 6443912293 + }, + "oracle_input": { + "proving_cost_modifier": -82937069, + "fee_asset_price_modifier": 337871846 + }, + "outputs": { + "fee_asset_price_at_execution": 10629631199, + "mana_base_fee_components_in_wei": { + "data_cost": 66, + "gas_cost": 48137449, + "proving_cost": 5418899001, + "congestion_cost": 20072771878, + "congestion_multiplier": 4671600111 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 701, + "gas_cost": 511683329, + "proving_cost": 57600897885, + "congestion_cost": 213366162204, + "congestion_multiplier": 4671600111 + } + } + }, + { + "l1_block_number": 20973608, + "l1_fees": { + "blob_fee": 17605, + "base_fee": 14271585742 + }, + "parent_header": { + "excess_mana": 1317522776, + "mana_used": 91749672, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 6443912293 + }, + "header": { + "excess_mana": 1309272448, + "mana_used": 112543125, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 6440084946 + }, + "oracle_input": { + "proving_cost_modifier": -150216996, + "fee_asset_price_modifier": -3827347 + }, + "outputs": { + "fee_asset_price_at_execution": 10665606471, + "mana_base_fee_components_in_wei": { + "data_cost": 69, + "gas_cost": 47274627, + "proving_cost": 5415357955, + "congestion_cost": 19811453536, + "congestion_multiplier": 4626722645 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 735, + "gas_cost": 504212567, + "proving_cost": 57758076847, + "congestion_cost": 211301167033, + "congestion_multiplier": 4626722645 + } + } + }, + { + "l1_block_number": 20973611, + "l1_fees": { + "blob_fee": 20599, + "base_fee": 14166674563 + }, + "parent_header": { + "excess_mana": 1309272448, + "mana_used": 112543125, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 6440084946 + }, + "header": { + "excess_mana": 1321815573, + "mana_used": 99544210, + "proving_cost_per_mana_numerator": 34927497, + "fee_asset_price_numerator": 5702092437 + }, + "oracle_input": { + "proving_cost_modifier": 34927497, + "fee_asset_price_modifier": -737992509 + }, + "outputs": { + "fee_asset_price_at_execution": 10665198269, + "mana_base_fee_components_in_wei": { + "data_cost": 80, + "gas_cost": 46927109, + "proving_cost": 5415357955, + "congestion_cost": 20183813190, + "congestion_multiplier": 4695122583 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 853, + "gas_cost": 500486921, + "proving_cost": 57755866287, + "congestion_cost": 215264369495, + "congestion_multiplier": 4695122583 + } + } + }, + { + "l1_block_number": 20973614, + "l1_fees": { + "blob_fee": 23174, + "base_fee": 13909087252 + }, + "parent_header": { + "excess_mana": 1321815573, + "mana_used": 99544210, + "proving_cost_per_mana_numerator": 34927497, + "fee_asset_price_numerator": 5702092437 + }, + "header": { + "excess_mana": 1321359783, + "mana_used": 83475620, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 4840039687 + }, + "oracle_input": { + "proving_cost_modifier": -179338485, + "fee_asset_price_modifier": -862052750 + }, + "outputs": { + "fee_asset_price_at_execution": 10586779623, + "mana_base_fee_components_in_wei": { + "data_cost": 91, + "gas_cost": 46073851, + "proving_cost": 5417249734, + "congestion_cost": 20173975333, + "congestion_multiplier": 4692619462 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 963, + "gas_cost": 487773706, + "proving_cost": 57351229096, + "congestion_cost": 213577430970, + "congestion_multiplier": 4692619462 + } + } + }, + { + "l1_block_number": 20973617, + "l1_fees": { + "blob_fee": 29330, + "base_fee": 12839237179 + }, + "parent_header": { + "excess_mana": 1321359783, + "mana_used": 83475620, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 4840039687 + }, + "header": { + "excess_mana": 1304835403, + "mana_used": 117833942, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 4567935259 + }, + "oracle_input": { + "proving_cost_modifier": -93855121, + "fee_asset_price_modifier": -272104428 + }, + "outputs": { + "fee_asset_price_at_execution": 10495908240, + "mana_base_fee_components_in_wei": { + "data_cost": 115, + "gas_cost": 42529973, + "proving_cost": 5415357955, + "congestion_cost": 19663493358, + "congestion_multiplier": 4602765979 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1207, + "gas_cost": 446390694, + "proving_cost": 56839100182, + "congestion_cost": 206386221963, + "congestion_multiplier": 4602765979 + } + } + }, + { + "l1_block_number": 20973620, + "l1_fees": { + "blob_fee": 35692, + "base_fee": 11710398600 + }, + "parent_header": { + "excess_mana": 1304835403, + "mana_used": 117833942, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 4567935259 + }, + "header": { + "excess_mana": 1322669345, + "mana_used": 107648739, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 4485569068 + }, + "oracle_input": { + "proving_cost_modifier": -57253967, + "fee_asset_price_modifier": -82366191 + }, + "outputs": { + "fee_asset_price_at_execution": 10467387230, + "mana_base_fee_components_in_wei": { + "data_cost": 140, + "gas_cost": 38790695, + "proving_cost": 5415357955, + "congestion_cost": 20179341210, + "congestion_multiplier": 4699814946 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1465, + "gas_cost": 406037225, + "proving_cost": 56684648704, + "congestion_cost": 211224978491, + "congestion_multiplier": 4699814946 + } + } + }, + { + "l1_block_number": 20973623, + "l1_fees": { + "blob_fee": 34318, + "base_fee": 11226899085 + }, + "parent_header": { + "excess_mana": 1322669345, + "mana_used": 107648739, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 4485569068 + }, + "header": { + "excess_mana": 1330318084, + "mana_used": 107126075, + "proving_cost_per_mana_numerator": 73369673, + "fee_asset_price_numerator": 3485569068 + }, + "oracle_input": { + "proving_cost_modifier": 73369673, + "fee_asset_price_modifier": -1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10458769192, + "mana_base_fee_components_in_wei": { + "data_cost": 134, + "gas_cost": 37189103, + "proving_cost": 5415357955, + "congestion_cost": 20403772164, + "congestion_multiplier": 4742062461 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1401, + "gas_cost": 388952244, + "proving_cost": 56637978943, + "congestion_cost": 213398343709, + "congestion_multiplier": 4742062461 + } + } + }, + { + "l1_block_number": 20973626, + "l1_fees": { + "blob_fee": 30505, + "base_fee": 11990879691 + }, + "parent_header": { + "excess_mana": 1330318084, + "mana_used": 107126075, + "proving_cost_per_mana_numerator": 73369673, + "fee_asset_price_numerator": 3485569068 + }, + "header": { + "excess_mana": 1337444159, + "mana_used": 103590464, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 2648632075 + }, + "oracle_input": { + "proving_cost_modifier": -178086909, + "fee_asset_price_modifier": -836936993 + }, + "outputs": { + "fee_asset_price_at_execution": 10354702700, + "mana_base_fee_components_in_wei": { + "data_cost": 119, + "gas_cost": 39719788, + "proving_cost": 5419332643, + "congestion_cost": 20644852354, + "congestion_multiplier": 4781764723 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1232, + "gas_cost": 411286596, + "proving_cost": 56115578350, + "congestion_cost": 213771308411, + "congestion_multiplier": 4781764723 + } + } + }, + { + "l1_block_number": 20973629, + "l1_fees": { + "blob_fee": 30505, + "base_fee": 12389925316 + }, + "parent_header": { + "excess_mana": 1337444159, + "mana_used": 103590464, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 2648632075 + }, + "header": { + "excess_mana": 1341034623, + "mana_used": 75455999, + "proving_cost_per_mana_numerator": 154461127, + "fee_asset_price_numerator": 2282803058 + }, + "oracle_input": { + "proving_cost_modifier": 154461127, + "fee_asset_price_modifier": -365829017 + }, + "outputs": { + "fee_asset_price_at_execution": 10268402007, + "mana_base_fee_components_in_wei": { + "data_cost": 119, + "gas_cost": 41041627, + "proving_cost": 5415357955, + "congestion_cost": 20744655554, + "congestion_multiplier": 4801894416 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1221, + "gas_cost": 421431925, + "proving_cost": 55607072493, + "congestion_cost": 213014462725, + "congestion_multiplier": 4801894416 + } + } + }, + { + "l1_block_number": 20973632, + "l1_fees": { + "blob_fee": 35692, + "base_fee": 13053650178 + }, + "parent_header": { + "excess_mana": 1341034623, + "mana_used": 75455999, + "proving_cost_per_mana_numerator": 154461127, + "fee_asset_price_numerator": 2282803058 + }, + "header": { + "excess_mana": 1316490622, + "mana_used": 37243071, + "proving_cost_per_mana_numerator": 237298150, + "fee_asset_price_numerator": 2606097745 + }, + "oracle_input": { + "proving_cost_modifier": 82837023, + "fee_asset_price_modifier": 323294687 + }, + "outputs": { + "fee_asset_price_at_execution": 10230905841, + "mana_base_fee_components_in_wei": { + "data_cost": 140, + "gas_cost": 43240216, + "proving_cost": 5423729041, + "congestion_cost": 20041702048, + "congestion_multiplier": 4665961997 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1432, + "gas_cost": 442386578, + "proving_cost": 55489661125, + "congestion_cost": 205044766546, + "congestion_multiplier": 4665961997 + } + } + }, + { + "l1_block_number": 20973635, + "l1_fees": { + "blob_fee": 37121, + "base_fee": 12793394041 + }, + "parent_header": { + "excess_mana": 1316490622, + "mana_used": 37243071, + "proving_cost_per_mana_numerator": 237298150, + "fee_asset_price_numerator": 2606097745 + }, + "header": { + "excess_mana": 1253733693, + "mana_used": 148558024, + "proving_cost_per_mana_numerator": 262704790, + "fee_asset_price_numerator": 2753929735 + }, + "oracle_input": { + "proving_cost_modifier": 25406640, + "fee_asset_price_modifier": 147831990 + }, + "outputs": { + "fee_asset_price_at_execution": 10264035340, + "mana_base_fee_components_in_wei": { + "data_cost": 145, + "gas_cost": 42378117, + "proving_cost": 5428223758, + "congestion_cost": 18247939638, + "congestion_multiplier": 4335636475 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1488, + "gas_cost": 434970490, + "proving_cost": 55715480485, + "congestion_cost": 187297497326, + "congestion_multiplier": 4335636475 + } + } + }, + { + "l1_block_number": 20973638, + "l1_fees": { + "blob_fee": 40153, + "base_fee": 12536317780 + }, + "parent_header": { + "excess_mana": 1253733693, + "mana_used": 148558024, + "proving_cost_per_mana_numerator": 262704790, + "fee_asset_price_numerator": 2753929735 + }, + "header": { + "excess_mana": 1302291717, + "mana_used": 113034877, + "proving_cost_per_mana_numerator": 189011056, + "fee_asset_price_numerator": 3394892634 + }, + "oracle_input": { + "proving_cost_modifier": -73693734, + "fee_asset_price_modifier": 640962899 + }, + "outputs": { + "fee_asset_price_at_execution": 10279220089, + "mana_base_fee_components_in_wei": { + "data_cost": 157, + "gas_cost": 41526552, + "proving_cost": 5429603062, + "congestion_cost": 19636366169, + "congestion_multiplier": 4589087993 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1613, + "gas_cost": 426860567, + "proving_cost": 55812084870, + "congestion_cost": 201846529599, + "congestion_multiplier": 4589087993 + } + } + }, + { + "l1_block_number": 20973641, + "l1_fees": { + "blob_fee": 35692, + "base_fee": 13073165878 + }, + "parent_header": { + "excess_mana": 1302291717, + "mana_used": 113034877, + "proving_cost_per_mana_numerator": 189011056, + "fee_asset_price_numerator": 3394892634 + }, + "header": { + "excess_mana": 1315326594, + "mana_used": 103158900, + "proving_cost_per_mana_numerator": 234196404, + "fee_asset_price_numerator": 4210671750 + }, + "oracle_input": { + "proving_cost_modifier": 45185348, + "fee_asset_price_modifier": 815779116 + }, + "outputs": { + "fee_asset_price_at_execution": 10345317680, + "mana_base_fee_components_in_wei": { + "data_cost": 140, + "gas_cost": 43304861, + "proving_cost": 5425603259, + "congestion_cost": 20014080594, + "congestion_multiplier": 4659611689 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1448, + "gas_cost": 448002544, + "proving_cost": 56129589319, + "congestion_cost": 207052021818, + "congestion_multiplier": 4659611689 + } + } + }, + { + "l1_block_number": 20973644, + "l1_fees": { + "blob_fee": 31726, + "base_fee": 13867324942 + }, + "parent_header": { + "excess_mana": 1315326594, + "mana_used": 103158900, + "proving_cost_per_mana_numerator": 234196404, + "fee_asset_price_numerator": 4210671750 + }, + "header": { + "excess_mana": 1318485494, + "mana_used": 104972183, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3935539809 + }, + "oracle_input": { + "proving_cost_modifier": -353785666, + "fee_asset_price_modifier": -275131941 + }, + "outputs": { + "fee_asset_price_at_execution": 10430057797, + "mana_base_fee_components_in_wei": { + "data_cost": 124, + "gas_cost": 45935513, + "proving_cost": 5428055391, + "congestion_cost": 20127126415, + "congestion_multiplier": 4676865072 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1293, + "gas_cost": 479110055, + "proving_cost": 56614931453, + "congestion_cost": 209927091795, + "congestion_multiplier": 4676865072 + } + } + }, + { + "l1_block_number": 20973647, + "l1_fees": { + "blob_fee": 22282, + "base_fee": 13249689068 + }, + "parent_header": { + "excess_mana": 1318485494, + "mana_used": 104972183, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3935539809 + }, + "header": { + "excess_mana": 1323457677, + "mana_used": 96706411, + "proving_cost_per_mana_numerator": 36679632, + "fee_asset_price_numerator": 3198003093 + }, + "oracle_input": { + "proving_cost_modifier": 36679632, + "fee_asset_price_modifier": -737536716 + }, + "outputs": { + "fee_asset_price_at_execution": 10401400817, + "mana_base_fee_components_in_wei": { + "data_cost": 87, + "gas_cost": 43889595, + "proving_cost": 5415357955, + "congestion_cost": 20221882032, + "congestion_multiplier": 4704151813 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 904, + "gas_cost": 456513269, + "proving_cost": 56327308657, + "congestion_cost": 210335900288, + "congestion_multiplier": 4704151813 + } + } + }, + { + "l1_block_number": 20973650, + "l1_fees": { + "blob_fee": 25067, + "base_fee": 12734890786 + }, + "parent_header": { + "excess_mana": 1323457677, + "mana_used": 96706411, + "proving_cost_per_mana_numerator": 36679632, + "fee_asset_price_numerator": 3198003093 + }, + "header": { + "excess_mana": 1320164088, + "mana_used": 95903793, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3461054523 + }, + "oracle_input": { + "proving_cost_modifier": -88632265, + "fee_asset_price_modifier": 263051430 + }, + "outputs": { + "fee_asset_price_at_execution": 10324968870, + "mana_base_fee_components_in_wei": { + "data_cost": 98, + "gas_cost": 42184325, + "proving_cost": 5417344652, + "congestion_cost": 20124147647, + "congestion_multiplier": 4686059250 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1011, + "gas_cost": 435551842, + "proving_cost": 55933914889, + "congestion_cost": 207781197990, + "congestion_multiplier": 4686059250 + } + } + }, + { + "l1_block_number": 20973653, + "l1_fees": { + "blob_fee": 22282, + "base_fee": 13407760302 + }, + "parent_header": { + "excess_mana": 1320164088, + "mana_used": 95903793, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3461054523 + }, + "header": { + "excess_mana": 1316067881, + "mana_used": 81430584, + "proving_cost_per_mana_numerator": 58298087, + "fee_asset_price_numerator": 3252958372 + }, + "oracle_input": { + "proving_cost_modifier": 58298087, + "fee_asset_price_modifier": -208096151 + }, + "outputs": { + "fee_asset_price_at_execution": 10352164602, + "mana_base_fee_components_in_wei": { + "data_cost": 87, + "gas_cost": 44413206, + "proving_cost": 5415357955, + "congestion_cost": 20002716866, + "congestion_multiplier": 4663654750 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 900, + "gas_cost": 459772819, + "proving_cost": 56060676928, + "congestion_cost": 207071417484, + "congestion_multiplier": 4663654750 + } + } + }, + { + "l1_block_number": 20973656, + "l1_fees": { + "blob_fee": 25067, + "base_fee": 13114282564 + }, + "parent_header": { + "excess_mana": 1316067881, + "mana_used": 81430584, + "proving_cost_per_mana_numerator": 58298087, + "fee_asset_price_numerator": 3252958372 + }, + "header": { + "excess_mana": 1297498465, + "mana_used": 116095544, + "proving_cost_per_mana_numerator": 177160749, + "fee_asset_price_numerator": 2252958372 + }, + "oracle_input": { + "proving_cost_modifier": 118862662, + "fee_asset_price_modifier": -1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10330644545, + "mana_base_fee_components_in_wei": { + "data_cost": 98, + "gas_cost": 43441060, + "proving_cost": 5418515925, + "congestion_cost": 19463268612, + "congestion_multiplier": 4563423937 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1012, + "gas_cost": 448774149, + "proving_cost": 55976761982, + "congestion_cost": 201068109714, + "congestion_multiplier": 4563423937 + } + } + }, + { + "l1_block_number": 20973659, + "l1_fees": { + "blob_fee": 35692, + "base_fee": 12944326949 + }, + "parent_header": { + "excess_mana": 1297498465, + "mana_used": 116095544, + "proving_cost_per_mana_numerator": 177160749, + "fee_asset_price_numerator": 2252958372 + }, + "header": { + "excess_mana": 1313594009, + "mana_used": 109242161, + "proving_cost_per_mana_numerator": 28596982, + "fee_asset_price_numerator": 1397045405 + }, + "oracle_input": { + "proving_cost_modifier": -148563767, + "fee_asset_price_modifier": -855912967 + }, + "outputs": { + "fee_asset_price_at_execution": 10227852915, + "mana_base_fee_components_in_wei": { + "data_cost": 140, + "gas_cost": 42878083, + "proving_cost": 5424960347, + "congestion_cost": 19958571173, + "congestion_multiplier": 4650175644 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1431, + "gas_cost": 438550726, + "proving_cost": 55485696498, + "congestion_cost": 204133330351, + "congestion_multiplier": 4650175644 + } + } + }, + { + "l1_block_number": 20973662, + "l1_fees": { + "blob_fee": 40153, + "base_fee": 13369037262 + }, + "parent_header": { + "excess_mana": 1313594009, + "mana_used": 109242161, + "proving_cost_per_mana_numerator": 28596982, + "fee_asset_price_numerator": 1397045405 + }, + "header": { + "excess_mana": 1322836170, + "mana_used": 108183872, + "proving_cost_per_mana_numerator": 304511687, + "fee_asset_price_numerator": 1620690980 + }, + "oracle_input": { + "proving_cost_modifier": 275914705, + "fee_asset_price_modifier": 223645575 + }, + "outputs": { + "fee_asset_price_at_execution": 10140684968, + "mana_base_fee_components_in_wei": { + "data_cost": 157, + "gas_cost": 44284935, + "proving_cost": 5416906805, + "congestion_cost": 20210409632, + "congestion_multiplier": 4700732370 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1592, + "gas_cost": 449079574, + "proving_cost": 54931145410, + "congestion_cost": 204947397152, + "congestion_multiplier": 4700732370 + } + } + }, + { + "l1_block_number": 20973665, + "l1_fees": { + "blob_fee": 52854, + "base_fee": 13746614736 + }, + "parent_header": { + "excess_mana": 1322836170, + "mana_used": 108183872, + "proving_cost_per_mana_numerator": 304511687, + "fee_asset_price_numerator": 1620690980 + }, + "header": { + "excess_mana": 1331020042, + "mana_used": 100370566, + "proving_cost_per_mana_numerator": 216866276, + "fee_asset_price_numerator": 1091240296 + }, + "oracle_input": { + "proving_cost_modifier": -87645411, + "fee_asset_price_modifier": -529450684 + }, + "outputs": { + "fee_asset_price_at_execution": 10163389541, + "mana_base_fee_components_in_wei": { + "data_cost": 207, + "gas_cost": 45535661, + "proving_cost": 5431873485, + "congestion_cost": 20518149071, + "congestion_multiplier": 4745958673 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 2103, + "gas_cost": 462796660, + "proving_cost": 55206246165, + "congestion_cost": 208533941668, + "congestion_multiplier": 4745958673 + } + } + }, + { + "l1_block_number": 20973668, + "l1_fees": { + "blob_fee": 43433, + "base_fee": 12637057600 + }, + "parent_header": { + "excess_mana": 1331020042, + "mana_used": 100370566, + "proving_cost_per_mana_numerator": 216866276, + "fee_asset_price_numerator": 1091240296 + }, + "header": { + "excess_mana": 1331390608, + "mana_used": 89670939, + "proving_cost_per_mana_numerator": 192384436, + "fee_asset_price_numerator": 91240296 + }, + "oracle_input": { + "proving_cost_modifier": -24481840, + "fee_asset_price_modifier": -1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10109721603, + "mana_base_fee_components_in_wei": { + "data_cost": 170, + "gas_cost": 41860253, + "proving_cost": 5427114783, + "congestion_cost": 20497810885, + "congestion_multiplier": 4748016788 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1718, + "gas_cost": 423195504, + "proving_cost": 54866619563, + "congestion_cost": 207227161518, + "congestion_multiplier": 4748016788 + } + } + }, + { + "l1_block_number": 20973671, + "l1_fees": { + "blob_fee": 37121, + "base_fee": 14261690469 + }, + "parent_header": { + "excess_mana": 1331390608, + "mana_used": 89670939, + "proving_cost_per_mana_numerator": 192384436, + "fee_asset_price_numerator": 91240296 + }, + "header": { + "excess_mana": 1321061547, + "mana_used": 91748908, + "proving_cost_per_mana_numerator": 252885275, + "fee_asset_price_numerator": 125382631 + }, + "oracle_input": { + "proving_cost_modifier": 60500839, + "fee_asset_price_modifier": 34142335 + }, + "outputs": { + "fee_asset_price_at_execution": 10009128193, + "mana_base_fee_components_in_wei": { + "data_cost": 145, + "gas_cost": 47241849, + "proving_cost": 5425786288, + "congestion_cost": 20200850642, + "congestion_multiplier": 4690982323 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1451, + "gas_cost": 472849722, + "proving_cost": 54307390504, + "congestion_cost": 202192903683, + "congestion_multiplier": 4690982323 + } + } + }, + { + "l1_block_number": 20973674, + "l1_fees": { + "blob_fee": 40153, + "base_fee": 14838773563 + }, + "parent_header": { + "excess_mana": 1321061547, + "mana_used": 91748908, + "proving_cost_per_mana_numerator": 252885275, + "fee_asset_price_numerator": 125382631 + }, + "header": { + "excess_mana": 1312810455, + "mana_used": 108557927, + "proving_cost_per_mana_numerator": 223094872, + "fee_asset_price_numerator": 512679736 + }, + "oracle_input": { + "proving_cost_modifier": -29790403, + "fee_asset_price_modifier": 387297105 + }, + "outputs": { + "fee_asset_price_at_execution": 10012546126, + "mana_base_fee_components_in_wei": { + "data_cost": 157, + "gas_cost": 49153437, + "proving_cost": 5429069928, + "congestion_cost": 19973134627, + "congestion_multiplier": 4645914510 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1571, + "gas_cost": 492151055, + "proving_cost": 54358813075, + "congestion_cost": 199981931733, + "congestion_multiplier": 4645914510 + } + } + }, + { + "l1_block_number": 20973677, + "l1_fees": { + "blob_fee": 37121, + "base_fee": 14896911474 + }, + "parent_header": { + "excess_mana": 1312810455, + "mana_used": 108557927, + "proving_cost_per_mana_numerator": 223094872, + "fee_asset_price_numerator": 512679736 + }, + "header": { + "excess_mana": 1321368382, + "mana_used": 110851131, + "proving_cost_per_mana_numerator": 85700300, + "fee_asset_price_numerator": 443662552 + }, + "oracle_input": { + "proving_cost_modifier": -137394572, + "fee_asset_price_modifier": -69017184 + }, + "outputs": { + "fee_asset_price_at_execution": 10051399618, + "mana_base_fee_components_in_wei": { + "data_cost": 145, + "gas_cost": 49346019, + "proving_cost": 5427452827, + "congestion_cost": 20223993114, + "congestion_multiplier": 4692666674 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1457, + "gas_cost": 495996556, + "proving_cost": 54553497272, + "congestion_cost": 203279436660, + "congestion_multiplier": 4692666674 + } + } + }, + { + "l1_block_number": 20973680, + "l1_fees": { + "blob_fee": 27115, + "base_fee": 17507207114 + }, + "parent_header": { + "excess_mana": 1321368382, + "mana_used": 110851131, + "proving_cost_per_mana_numerator": 85700300, + "fee_asset_price_numerator": 443662552 + }, + "header": { + "excess_mana": 1332219513, + "mana_used": 100945171, + "proving_cost_per_mana_numerator": 158359051, + "fee_asset_price_numerator": 1140511040 + }, + "oracle_input": { + "proving_cost_modifier": 72658751, + "fee_asset_price_modifier": 696848488 + }, + "outputs": { + "fee_asset_price_at_execution": 10044464819, + "mana_base_fee_components_in_wei": { + "data_cost": 106, + "gas_cost": 57992623, + "proving_cost": 5420000922, + "congestion_cost": 20556849011, + "congestion_multiplier": 4752623738 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1064, + "gas_cost": 582504861, + "proving_cost": 54441008579, + "congestion_cost": 206482546680, + "congestion_multiplier": 4752623738 + } + } + }, + { + "l1_block_number": 20973683, + "l1_fees": { + "blob_fee": 27115, + "base_fee": 17359812143 + }, + "parent_header": { + "excess_mana": 1332219513, + "mana_used": 100945171, + "proving_cost_per_mana_numerator": 158359051, + "fee_asset_price_numerator": 1140511040 + }, + "header": { + "excess_mana": 1333164684, + "mana_used": 95398013, + "proving_cost_per_mana_numerator": 233651354, + "fee_asset_price_numerator": 1146490236 + }, + "oracle_input": { + "proving_cost_modifier": 75292303, + "fee_asset_price_modifier": 5979196 + }, + "outputs": { + "fee_asset_price_at_execution": 10114703966, + "mana_base_fee_components_in_wei": { + "data_cost": 106, + "gas_cost": 57504377, + "proving_cost": 5423940458, + "congestion_cost": 20598625108, + "congestion_multiplier": 4757882334 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1072, + "gas_cost": 581639750, + "proving_cost": 54861552061, + "congestion_cost": 208348995074, + "congestion_multiplier": 4757882334 + } + } + }, + { + "l1_block_number": 20973686, + "l1_fees": { + "blob_fee": 29330, + "base_fee": 16774258941 + }, + "parent_header": { + "excess_mana": 1333164684, + "mana_used": 95398013, + "proving_cost_per_mana_numerator": 233651354, + "fee_asset_price_numerator": 1146490236 + }, + "header": { + "excess_mana": 1328562697, + "mana_used": 104797878, + "proving_cost_per_mana_numerator": 350116580, + "fee_asset_price_numerator": 1091371198 + }, + "oracle_input": { + "proving_cost_modifier": 116465226, + "fee_asset_price_modifier": -55119038 + }, + "outputs": { + "fee_asset_price_at_execution": 10115308762, + "mana_base_fee_components_in_wei": { + "data_cost": 115, + "gas_cost": 55564732, + "proving_cost": 5428025805, + "congestion_cost": 20466587412, + "congestion_multiplier": 4732333194 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1163, + "gas_cost": 562054420, + "proving_cost": 54906156985, + "congestion_cost": 207025850976, + "congestion_multiplier": 4732333194 + } + } + }, + { + "l1_block_number": 20973689, + "l1_fees": { + "blob_fee": 40153, + "base_fee": 16436884687 + }, + "parent_header": { + "excess_mana": 1328562697, + "mana_used": 104797878, + "proving_cost_per_mana_numerator": 350116580, + "fee_asset_price_numerator": 1091371198 + }, + "header": { + "excess_mana": 1333360575, + "mana_used": 94135126, + "proving_cost_per_mana_numerator": 487258535, + "fee_asset_price_numerator": 1295374975 + }, + "oracle_input": { + "proving_cost_modifier": 137141955, + "fee_asset_price_modifier": 204003777 + }, + "outputs": { + "fee_asset_price_at_execution": 10109734837, + "mana_base_fee_components_in_wei": { + "data_cost": 157, + "gas_cost": 54447180, + "proving_cost": 5434351251, + "congestion_cost": 20632245310, + "congestion_multiplier": 4758972930 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1587, + "gas_cost": 550446552, + "proving_cost": 54939850158, + "congestion_cost": 208586529176, + "congestion_multiplier": 4758972930 + } + } + }, + { + "l1_block_number": 20973692, + "l1_fees": { + "blob_fee": 50819, + "base_fee": 15897028148 + }, + "parent_header": { + "excess_mana": 1333360575, + "mana_used": 94135126, + "proving_cost_per_mana_numerator": 487258535, + "fee_asset_price_numerator": 1295374975 + }, + "header": { + "excess_mana": 1327495701, + "mana_used": 88175023, + "proving_cost_per_mana_numerator": 692563901, + "fee_asset_price_numerator": 614727199 + }, + "oracle_input": { + "proving_cost_modifier": 205305366, + "fee_asset_price_modifier": -680647776 + }, + "outputs": { + "fee_asset_price_at_execution": 10130380130, + "mana_base_fee_components_in_wei": { + "data_cost": 199, + "gas_cost": 52658905, + "proving_cost": 5441809139, + "congestion_cost": 20474746377, + "congestion_multiplier": 4726429105 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 2015, + "gas_cost": 533454724, + "proving_cost": 55127595172, + "congestion_cost": 207416963864, + "congestion_multiplier": 4726429105 + } + } + }, + { + "l1_block_number": 20973695, + "l1_fees": { + "blob_fee": 41761, + "base_fee": 14721886802 + }, + "parent_header": { + "excess_mana": 1327495701, + "mana_used": 88175023, + "proving_cost_per_mana_numerator": 692563901, + "fee_asset_price_numerator": 614727199 + }, + "header": { + "excess_mana": 1315670724, + "mana_used": 95588997, + "proving_cost_per_mana_numerator": 693229477, + "fee_asset_price_numerator": 1107651260 + }, + "oracle_input": { + "proving_cost_modifier": 665576, + "fee_asset_price_modifier": 492924061 + }, + "outputs": { + "fee_asset_price_at_execution": 10061662052, + "mana_base_fee_components_in_wei": { + "data_cost": 164, + "gas_cost": 48766250, + "proving_cost": 5452992942, + "congestion_cost": 20144626829, + "congestion_multiplier": 4661488176 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1650, + "gas_cost": 490669527, + "proving_cost": 54866172154, + "congestion_cost": 202688427317, + "congestion_multiplier": 4661488176 + } + } + }, + { + "l1_block_number": 20973698, + "l1_fees": { + "blob_fee": 32996, + "base_fee": 13847852742 + }, + "parent_header": { + "excess_mana": 1315670724, + "mana_used": 95588997, + "proving_cost_per_mana_numerator": 693229477, + "fee_asset_price_numerator": 1107651260 + }, + "header": { + "excess_mana": 1311259721, + "mana_used": 98042679, + "proving_cost_per_mana_numerator": 627079751, + "fee_asset_price_numerator": 1021247990 + }, + "oracle_input": { + "proving_cost_modifier": -66149726, + "fee_asset_price_modifier": -86403270 + }, + "outputs": { + "fee_asset_price_at_execution": 10111380842, + "mana_base_fee_components_in_wei": { + "data_cost": 129, + "gas_cost": 45871012, + "proving_cost": 5453029235, + "congestion_cost": 20002210509, + "congestion_multiplier": 4637492797 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1304, + "gas_cost": 463819271, + "proving_cost": 55137655337, + "congestion_cost": 202249968138, + "congestion_multiplier": 4637492797 + } + } + }, + { + "l1_block_number": 20973701, + "l1_fees": { + "blob_fee": 37121, + "base_fee": 12795525944 + }, + "parent_header": { + "excess_mana": 1311259721, + "mana_used": 98042679, + "proving_cost_per_mana_numerator": 627079751, + "fee_asset_price_numerator": 1021247990 + }, + "header": { + "excess_mana": 1309302400, + "mana_used": 116369229, + "proving_cost_per_mana_numerator": 355053462, + "fee_asset_price_numerator": 400314957 + }, + "oracle_input": { + "proving_cost_modifier": -272026289, + "fee_asset_price_modifier": -620933033 + }, + "outputs": { + "fee_asset_price_at_execution": 10102648052, + "mana_base_fee_components_in_wei": { + "data_cost": 145, + "gas_cost": 42385179, + "proving_cost": 5449423264, + "congestion_cost": 19918157015, + "congestion_multiplier": 4626884786 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1464, + "gas_cost": 428202546, + "proving_cost": 55053605322, + "congestion_cost": 201226130167, + "congestion_multiplier": 4626884786 + } + } + }, + { + "l1_block_number": 20973704, + "l1_fees": { + "blob_fee": 32996, + "base_fee": 12974547741 + }, + "parent_header": { + "excess_mana": 1309302400, + "mana_used": 116369229, + "proving_cost_per_mana_numerator": 355053462, + "fee_asset_price_numerator": 400314957 + }, + "header": { + "excess_mana": 1325671629, + "mana_used": 96645177, + "proving_cost_per_mana_numerator": 400248833, + "fee_asset_price_numerator": 497696853 + }, + "oracle_input": { + "proving_cost_modifier": 45195371, + "fee_asset_price_modifier": 97381896 + }, + "outputs": { + "fee_asset_price_at_execution": 10040111728, + "mana_base_fee_components_in_wei": { + "data_cost": 129, + "gas_cost": 42978189, + "proving_cost": 5434619545, + "congestion_cost": 20356686621, + "congestion_multiplier": 4716352885 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1295, + "gas_cost": 431505819, + "proving_cost": 54564187430, + "congestion_cost": 204383408086, + "congestion_multiplier": 4716352885 + } + } + }, + { + "l1_block_number": 20973707, + "l1_fees": { + "blob_fee": 31726, + "base_fee": 12024548672 + }, + "parent_header": { + "excess_mana": 1325671629, + "mana_used": 96645177, + "proving_cost_per_mana_numerator": 400248833, + "fee_asset_price_numerator": 497696853 + }, + "header": { + "excess_mana": 1322316806, + "mana_used": 117502004, + "proving_cost_per_mana_numerator": 365016066, + "fee_asset_price_numerator": 360522242 + }, + "oracle_input": { + "proving_cost_modifier": -35232767, + "fee_asset_price_modifier": -137174611 + }, + "outputs": { + "fee_asset_price_at_execution": 10049893742, + "mana_base_fee_components_in_wei": { + "data_cost": 124, + "gas_cost": 39831317, + "proving_cost": 5437076296, + "congestion_cost": 20252930111, + "congestion_multiplier": 4697876810 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1246, + "gas_cost": 400300503, + "proving_cost": 54642039041, + "congestion_cost": 203539795579, + "congestion_multiplier": 4697876810 + } + } + }, + { + "l1_block_number": 20973710, + "l1_fees": { + "blob_fee": 28201, + "base_fee": 12463433465 + }, + "parent_header": { + "excess_mana": 1322316806, + "mana_used": 117502004, + "proving_cost_per_mana_numerator": 365016066, + "fee_asset_price_numerator": 360522242 + }, + "header": { + "excess_mana": 1339818810, + "mana_used": 80370368, + "proving_cost_per_mana_numerator": 207515968, + "fee_asset_price_numerator": 587790795 + }, + "oracle_input": { + "proving_cost_modifier": -157500098, + "fee_asset_price_modifier": 227268553 + }, + "outputs": { + "fee_asset_price_at_execution": 10036117290, + "mana_base_fee_components_in_wei": { + "data_cost": 110, + "gas_cost": 41285123, + "proving_cost": 5435161001, + "congestion_cost": 20783488988, + "congestion_multiplier": 4795068572 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1103, + "gas_cost": 414342336, + "proving_cost": 54547913296, + "congestion_cost": 208585533178, + "congestion_multiplier": 4795068572 + } + } + }, + { + "l1_block_number": 20973713, + "l1_fees": { + "blob_fee": 25067, + "base_fee": 11667927282 + }, + "parent_header": { + "excess_mana": 1339818810, + "mana_used": 80370368, + "proving_cost_per_mana_numerator": 207515968, + "fee_asset_price_numerator": 587790795 + }, + "header": { + "excess_mana": 1320189178, + "mana_used": 122543064, + "proving_cost_per_mana_numerator": 255539944, + "fee_asset_price_numerator": 888025172 + }, + "oracle_input": { + "proving_cost_modifier": 48023976, + "fee_asset_price_modifier": 300234377 + }, + "outputs": { + "fee_asset_price_at_execution": 10058952167, + "mana_base_fee_components_in_wei": { + "data_cost": 98, + "gas_cost": 38650009, + "proving_cost": 5426607355, + "congestion_cost": 20146014638, + "congestion_multiplier": 4686196813 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 985, + "gas_cost": 388778591, + "proving_cost": 54585983813, + "congestion_cost": 202647797599, + "congestion_multiplier": 4686196813 + } + } + }, + { + "l1_block_number": 20973716, + "l1_fees": { + "blob_fee": 17605, + "base_fee": 12588865223 + }, + "parent_header": { + "excess_mana": 1320189178, + "mana_used": 122543064, + "proving_cost_per_mana_numerator": 255539944, + "fee_asset_price_numerator": 888025172 + }, + "header": { + "excess_mana": 1342732242, + "mana_used": 100615032, + "proving_cost_per_mana_numerator": 286957295, + "fee_asset_price_numerator": 981528734 + }, + "oracle_input": { + "proving_cost_modifier": 31417351, + "fee_asset_price_modifier": 93503562 + }, + "outputs": { + "fee_asset_price_at_execution": 10089197981, + "mana_base_fee_components_in_wei": { + "data_cost": 69, + "gas_cost": 41700616, + "proving_cost": 5429214054, + "congestion_cost": 20852071397, + "congestion_multiplier": 4811441485 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 696, + "gas_cost": 420725770, + "proving_cost": 54776415472, + "congestion_cost": 210380676638, + "congestion_multiplier": 4811441485 + } + } + }, + { + "l1_block_number": 20973719, + "l1_fees": { + "blob_fee": 19806, + "base_fee": 12041731239 + }, + "parent_header": { + "excess_mana": 1342732242, + "mana_used": 100615032, + "proving_cost_per_mana_numerator": 286957295, + "fee_asset_price_numerator": 981528734 + }, + "header": { + "excess_mana": 1343347274, + "mana_used": 77006488, + "proving_cost_per_mana_numerator": 143731815, + "fee_asset_price_numerator": 1796621780 + }, + "oracle_input": { + "proving_cost_modifier": -143225480, + "fee_asset_price_modifier": 815093046 + }, + "outputs": { + "fee_asset_price_at_execution": 10098636152, + "mana_base_fee_components_in_wei": { + "data_cost": 77, + "gas_cost": 39888234, + "proving_cost": 5430920037, + "congestion_cost": 20870614033, + "congestion_multiplier": 4814904984 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 777, + "gas_cost": 402816761, + "proving_cost": 54844885424, + "congestion_cost": 210764737388, + "congestion_multiplier": 4814904984 + } + } + }, + { + "l1_block_number": 20973722, + "l1_fees": { + "blob_fee": 22282, + "base_fee": 11999031875 + }, + "parent_header": { + "excess_mana": 1343347274, + "mana_used": 77006488, + "proving_cost_per_mana_numerator": 143731815, + "fee_asset_price_numerator": 1796621780 + }, + "header": { + "excess_mana": 1320353762, + "mana_used": 106572663, + "proving_cost_per_mana_numerator": 204284475, + "fee_asset_price_numerator": 1339655635 + }, + "oracle_input": { + "proving_cost_modifier": 60552660, + "fee_asset_price_modifier": -456966145 + }, + "outputs": { + "fee_asset_price_at_execution": 10181285811, + "mana_base_fee_components_in_wei": { + "data_cost": 87, + "gas_cost": 39746793, + "proving_cost": 5423147143, + "congestion_cost": 20142232668, + "congestion_multiplier": 4687099289 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 885, + "gas_cost": 404673459, + "proving_cost": 55214611057, + "congestion_cost": 205073827664, + "congestion_multiplier": 4687099289 + } + } + }, + { + "l1_block_number": 20973725, + "l1_fees": { + "blob_fee": 25067, + "base_fee": 11451155317 + }, + "parent_header": { + "excess_mana": 1320353762, + "mana_used": 106572663, + "proving_cost_per_mana_numerator": 204284475, + "fee_asset_price_numerator": 1339655635 + }, + "header": { + "excess_mana": 1326926425, + "mana_used": 107682586, + "proving_cost_per_mana_numerator": 22685411, + "fee_asset_price_numerator": 1288771117 + }, + "oracle_input": { + "proving_cost_modifier": -181599064, + "fee_asset_price_modifier": -50884518 + }, + "outputs": { + "fee_asset_price_at_execution": 10134866922, + "mana_base_fee_components_in_wei": { + "data_cost": 98, + "gas_cost": 37931951, + "proving_cost": 5426431997, + "congestion_cost": 20345368845, + "congestion_multiplier": 4723282101 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 993, + "gas_cost": 384435275, + "proving_cost": 54996166150, + "congestion_cost": 206197605723, + "congestion_multiplier": 4723282101 + } + } + }, + { + "l1_block_number": 20973728, + "l1_fees": { + "blob_fee": 30505, + "base_fee": 11303347796 + }, + "parent_header": { + "excess_mana": 1326926425, + "mana_used": 107682586, + "proving_cost_per_mana_numerator": 22685411, + "fee_asset_price_numerator": 1288771117 + }, + "header": { + "excess_mana": 1334609011, + "mana_used": 99341302, + "proving_cost_per_mana_numerator": 39587039, + "fee_asset_price_numerator": 2288771117 + }, + "oracle_input": { + "proving_cost_modifier": 16901628, + "fee_asset_price_modifier": 1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10129711156, + "mana_base_fee_components_in_wei": { + "data_cost": 119, + "gas_cost": 37442339, + "proving_cost": 5416586590, + "congestion_cost": 20539487789, + "congestion_multiplier": 4765929299 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1205, + "gas_cost": 379280079, + "proving_cost": 54868457608, + "congestion_cost": 208059078594, + "congestion_multiplier": 4765929299 + } + } + }, + { + "l1_block_number": 20973731, + "l1_fees": { + "blob_fee": 27115, + "base_fee": 11131576212 + }, + "parent_header": { + "excess_mana": 1334609011, + "mana_used": 99341302, + "proving_cost_per_mana_numerator": 39587039, + "fee_asset_price_numerator": 2288771117 + }, + "header": { + "excess_mana": 1333950313, + "mana_used": 98924508, + "proving_cost_per_mana_numerator": 102816084, + "fee_asset_price_numerator": 2351903422 + }, + "oracle_input": { + "proving_cost_modifier": 63229045, + "fee_asset_price_modifier": 63132305 + }, + "outputs": { + "fee_asset_price_at_execution": 10231516445, + "mana_base_fee_components_in_wei": { + "data_cost": 106, + "gas_cost": 36873346, + "proving_cost": 5417502159, + "congestion_cost": 20520766766, + "congestion_multiplier": 4762257723 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1084, + "gas_cost": 377270245, + "proving_cost": 55429262430, + "congestion_cost": 209958562630, + "congestion_multiplier": 4762257723 + } + } + }, + { + "l1_block_number": 20973734, + "l1_fees": { + "blob_fee": 27115, + "base_fee": 11324057276 + }, + "parent_header": { + "excess_mana": 1333950313, + "mana_used": 98924508, + "proving_cost_per_mana_numerator": 102816084, + "fee_asset_price_numerator": 2351903422 + }, + "header": { + "excess_mana": 1332874821, + "mana_used": 92189342, + "proving_cost_per_mana_numerator": 236788546, + "fee_asset_price_numerator": 1804191747 + }, + "oracle_input": { + "proving_cost_modifier": 133972462, + "fee_asset_price_modifier": -547711675 + }, + "outputs": { + "fee_asset_price_at_execution": 10237977877, + "mana_base_fee_components_in_wei": { + "data_cost": 106, + "gas_cost": 37510939, + "proving_cost": 5420928677, + "congestion_cost": 20503368030, + "congestion_multiplier": 4756269021 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1085, + "gas_cost": 384036163, + "proving_cost": 55499347867, + "congestion_cost": 209913028295, + "congestion_multiplier": 4756269021 + } + } + }, + { + "l1_block_number": 20973737, + "l1_fees": { + "blob_fee": 23174, + "base_fee": 12400836887 + }, + "parent_header": { + "excess_mana": 1332874821, + "mana_used": 92189342, + "proving_cost_per_mana_numerator": 236788546, + "fee_asset_price_numerator": 1804191747 + }, + "header": { + "excess_mana": 1325064163, + "mana_used": 95916080, + "proving_cost_per_mana_numerator": 141587906, + "fee_asset_price_numerator": 2358872831 + }, + "oracle_input": { + "proving_cost_modifier": -95200640, + "fee_asset_price_modifier": 554681084 + }, + "outputs": { + "fee_asset_price_at_execution": 10182056561, + "mana_base_fee_components_in_wei": { + "data_cost": 91, + "gas_cost": 41077772, + "proving_cost": 5428196095, + "congestion_cost": 20307425133, + "congestion_multiplier": 4713001998 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 926, + "gas_cost": 418256197, + "proving_cost": 55270199663, + "congestion_cost": 206771351312, + "congestion_multiplier": 4713001998 + } + } + }, + { + "l1_block_number": 20973740, + "l1_fees": { + "blob_fee": 28201, + "base_fee": 12009113331 + }, + "parent_header": { + "excess_mana": 1325064163, + "mana_used": 95916080, + "proving_cost_per_mana_numerator": 141587906, + "fee_asset_price_numerator": 2358872831 + }, + "header": { + "excess_mana": 1320980243, + "mana_used": 82886232, + "proving_cost_per_mana_numerator": 228305694, + "fee_asset_price_numerator": 2538942324 + }, + "oracle_input": { + "proving_cost_modifier": 86717788, + "fee_asset_price_modifier": 180069493 + }, + "outputs": { + "fee_asset_price_at_execution": 10238691428, + "mana_base_fee_components_in_wei": { + "data_cost": 110, + "gas_cost": 39780187, + "proving_cost": 5423030877, + "congestion_cost": 20160701910, + "congestion_multiplier": 4690536112 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1126, + "gas_cost": 407297059, + "proving_cost": 55524739754, + "congestion_cost": 206419205828, + "congestion_multiplier": 4690536112 + } + } + }, + { + "l1_block_number": 20973743, + "l1_fees": { + "blob_fee": 29330, + "base_fee": 11347704848 + }, + "parent_header": { + "excess_mana": 1320980243, + "mana_used": 82886232, + "proving_cost_per_mana_numerator": 228305694, + "fee_asset_price_numerator": 2538942324 + }, + "header": { + "excess_mana": 1303866475, + "mana_used": 99575548, + "proving_cost_per_mana_numerator": 191313213, + "fee_asset_price_numerator": 2276176576 + }, + "oracle_input": { + "proving_cost_modifier": -36992481, + "fee_asset_price_modifier": -262765748 + }, + "outputs": { + "fee_asset_price_at_execution": 10257144798, + "mana_base_fee_components_in_wei": { + "data_cost": 115, + "gas_cost": 37589272, + "proving_cost": 5427735649, + "congestion_cost": 19661785712, + "congestion_multiplier": 4597551030 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1179, + "gas_cost": 385558605, + "proving_cost": 55673070477, + "congestion_cost": 201673783035, + "congestion_multiplier": 4597551030 + } + } + }, + { + "l1_block_number": 20973746, + "l1_fees": { + "blob_fee": 32996, + "base_fee": 11581848907 + }, + "parent_header": { + "excess_mana": 1303866475, + "mana_used": 99575548, + "proving_cost_per_mana_numerator": 191313213, + "fee_asset_price_numerator": 2276176576 + }, + "header": { + "excess_mana": 1303442023, + "mana_used": 112024559, + "proving_cost_per_mana_numerator": 80126553, + "fee_asset_price_numerator": 2827578672 + }, + "oracle_input": { + "proving_cost_modifier": -111186660, + "fee_asset_price_modifier": 551402096 + }, + "outputs": { + "fee_asset_price_at_execution": 10230227914, + "mana_base_fee_components_in_wei": { + "data_cost": 129, + "gas_cost": 38364874, + "proving_cost": 5425728166, + "congestion_cost": 19644881570, + "congestion_multiplier": 4595268412 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1319, + "gas_cost": 392481404, + "proving_cost": 55506435737, + "congestion_cost": 200971615804, + "congestion_multiplier": 4595268412 + } + } + }, + { + "l1_block_number": 20973749, + "l1_fees": { + "blob_fee": 29330, + "base_fee": 11435533437 + }, + "parent_header": { + "excess_mana": 1303442023, + "mana_used": 112024559, + "proving_cost_per_mana_numerator": 80126553, + "fee_asset_price_numerator": 2827578672 + }, + "header": { + "excess_mana": 1315466582, + "mana_used": 120164071, + "proving_cost_per_mana_numerator": 56045946, + "fee_asset_price_numerator": 3348463536 + }, + "oracle_input": { + "proving_cost_modifier": -24080607, + "fee_asset_price_modifier": 520884864 + }, + "outputs": { + "fee_asset_price_at_execution": 10286793414, + "mana_base_fee_components_in_wei": { + "data_cost": 115, + "gas_cost": 37880204, + "proving_cost": 5419698833, + "congestion_cost": 19976785911, + "congestion_multiplier": 4660374931 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1182, + "gas_cost": 389665833, + "proving_cost": 55751322261, + "congestion_cost": 205497069742, + "congestion_multiplier": 4660374931 + } + } + }, + { + "l1_block_number": 20973752, + "l1_fees": { + "blob_fee": 41761, + "base_fee": 11193020248 + }, + "parent_header": { + "excess_mana": 1315466582, + "mana_used": 120164071, + "proving_cost_per_mana_numerator": 56045946, + "fee_asset_price_numerator": 3348463536 + }, + "header": { + "excess_mana": 1335630653, + "mana_used": 94218981, + "proving_cost_per_mana_numerator": 26648853, + "fee_asset_price_numerator": 3252411517 + }, + "oracle_input": { + "proving_cost_modifier": -29397093, + "fee_asset_price_modifier": -96052019 + }, + "outputs": { + "fee_asset_price_at_execution": 10340515557, + "mana_base_fee_components_in_wei": { + "data_cost": 164, + "gas_cost": 37076879, + "proving_cost": 5418393894, + "congestion_cost": 20576015236, + "congestion_multiplier": 4771629521 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1695, + "gas_cost": 383394044, + "proving_cost": 56028986354, + "congestion_cost": 212766605648, + "congestion_multiplier": 4771629521 + } + } + }, + { + "l1_block_number": 20973755, + "l1_fees": { + "blob_fee": 30505, + "base_fee": 10757053816 + }, + "parent_header": { + "excess_mana": 1335630653, + "mana_used": 94218981, + "proving_cost_per_mana_numerator": 26648853, + "fee_asset_price_numerator": 3252411517 + }, + "header": { + "excess_mana": 1329849634, + "mana_used": 105066595, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3510685066 + }, + "oracle_input": { + "proving_cost_modifier": -199703229, + "fee_asset_price_modifier": 258273549 + }, + "outputs": { + "fee_asset_price_at_execution": 10330588052, + "mana_base_fee_components_in_wei": { + "data_cost": 119, + "gas_cost": 35632740, + "proving_cost": 5416801278, + "congestion_cost": 20389181783, + "congestion_multiplier": 4739464113 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1229, + "gas_cost": 368107158, + "proving_cost": 55958742562, + "congestion_cost": 210632237717, + "congestion_multiplier": 4739464113 + } + } + }, + { + "l1_block_number": 20973758, + "l1_fees": { + "blob_fee": 25067, + "base_fee": 10381187963 + }, + "parent_header": { + "excess_mana": 1329849634, + "mana_used": 105066595, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3510685066 + }, + "header": { + "excess_mana": 1334916229, + "mana_used": 89931642, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3335505808 + }, + "oracle_input": { + "proving_cost_modifier": -49792707, + "fee_asset_price_modifier": -175179258 + }, + "outputs": { + "fee_asset_price_at_execution": 10357303713, + "mana_base_fee_components_in_wei": { + "data_cost": 98, + "gas_cost": 34387685, + "proving_cost": 5415357955, + "congestion_cost": 20532694724, + "congestion_multiplier": 4767642696 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1015, + "gas_cost": 356163697, + "proving_cost": 56088507054, + "congestion_cost": 212663355302, + "congestion_multiplier": 4767642696 + } + } + }, + { + "l1_block_number": 20973761, + "l1_fees": { + "blob_fee": 25067, + "base_fee": 12244616598 + }, + "parent_header": { + "excess_mana": 1334916229, + "mana_used": 89931642, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3335505808 + }, + "header": { + "excess_mana": 1324847871, + "mana_used": 101874759, + "proving_cost_per_mana_numerator": 90251834, + "fee_asset_price_numerator": 3015527291 + }, + "oracle_input": { + "proving_cost_modifier": 90251834, + "fee_asset_price_modifier": -319978517 + }, + "outputs": { + "fee_asset_price_at_execution": 10339175748, + "mana_base_fee_components_in_wei": { + "data_cost": 98, + "gas_cost": 40560292, + "proving_cost": 5415357955, + "congestion_cost": 20251329375, + "congestion_multiplier": 4711809469 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1013, + "gas_cost": 419359987, + "proving_cost": 55990337635, + "congestion_cost": 209382053538, + "congestion_multiplier": 4711809469 + } + } + }, + { + "l1_block_number": 20973764, + "l1_fees": { + "blob_fee": 20599, + "base_fee": 11587680957 + }, + "parent_header": { + "excess_mana": 1324847871, + "mana_used": 101874759, + "proving_cost_per_mana_numerator": 90251834, + "fee_asset_price_numerator": 3015527291 + }, + "header": { + "excess_mana": 1326722630, + "mana_used": 94633541, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 2948017643 + }, + "oracle_input": { + "proving_cost_modifier": -202786759, + "fee_asset_price_modifier": -67509648 + }, + "outputs": { + "fee_asset_price_at_execution": 10306145480, + "mana_base_fee_components_in_wei": { + "data_cost": 80, + "gas_cost": 38384193, + "proving_cost": 5420247621, + "congestion_cost": 20317879543, + "congestion_multiplier": 4722156016 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 824, + "gas_cost": 395593077, + "proving_cost": 55861860519, + "congestion_cost": 209399022415, + "congestion_multiplier": 4722156016 + } + } + }, + { + "l1_block_number": 20973767, + "l1_fees": { + "blob_fee": 23174, + "base_fee": 11392419394 + }, + "parent_header": { + "excess_mana": 1326722630, + "mana_used": 94633541, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 2948017643 + }, + "header": { + "excess_mana": 1321356171, + "mana_used": 107027137, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 2964670861 + }, + "oracle_input": { + "proving_cost_modifier": -569992, + "fee_asset_price_modifier": 16653218 + }, + "outputs": { + "fee_asset_price_at_execution": 10299190185, + "mana_base_fee_components_in_wei": { + "data_cost": 91, + "gas_cost": 37737389, + "proving_cost": 5415357955, + "congestion_cost": 20136098191, + "congestion_multiplier": 4692599631 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 937, + "gas_cost": 388664546, + "proving_cost": 55773801498, + "congestion_cost": 207385504852, + "congestion_multiplier": 4692599631 + } + } + }, + { + "l1_block_number": 20973770, + "l1_fees": { + "blob_fee": 26071, + "base_fee": 11075431045 + }, + "parent_header": { + "excess_mana": 1321356171, + "mana_used": 107027137, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 2964670861 + }, + "header": { + "excess_mana": 1328383308, + "mana_used": 98027217, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 2914036442 + }, + "oracle_input": { + "proving_cost_modifier": -8209932, + "fee_asset_price_modifier": -50634419 + }, + "outputs": { + "fee_asset_price_at_execution": 10300905475, + "mana_base_fee_components_in_wei": { + "data_cost": 102, + "gas_cost": 36687365, + "proving_cost": 5415357955, + "congestion_cost": 20343435448, + "congestion_multiplier": 4731340052 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1050, + "gas_cost": 377913078, + "proving_cost": 55783090407, + "congestion_cost": 209555805586, + "congestion_multiplier": 4731340052 + } + } + }, + { + "l1_block_number": 20973773, + "l1_fees": { + "blob_fee": 20599, + "base_fee": 11109198013 + }, + "parent_header": { + "excess_mana": 1328383308, + "mana_used": 98027217, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 2914036442 + }, + "header": { + "excess_mana": 1326410525, + "mana_used": 95385211, + "proving_cost_per_mana_numerator": 85267716, + "fee_asset_price_numerator": 3385377647 + }, + "oracle_input": { + "proving_cost_modifier": 85267716, + "fee_asset_price_modifier": 471341205 + }, + "outputs": { + "fee_asset_price_at_execution": 10295690992, + "mana_base_fee_components_in_wei": { + "data_cost": 80, + "gas_cost": 36799218, + "proving_cost": 5415357955, + "congestion_cost": 20284380171, + "congestion_multiplier": 4720431974 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 823, + "gas_cost": 378873377, + "proving_cost": 55754852115, + "congestion_cost": 208841710204, + "congestion_multiplier": 4720431974 + } + } + }, + { + "l1_block_number": 20973776, + "l1_fees": { + "blob_fee": 19044, + "base_fee": 10883747585 + }, + "parent_header": { + "excess_mana": 1326410525, + "mana_used": 95385211, + "proving_cost_per_mana_numerator": 85267716, + "fee_asset_price_numerator": 3385377647 + }, + "header": { + "excess_mana": 1321795736, + "mana_used": 108511444, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3548299411 + }, + "oracle_input": { + "proving_cost_modifier": -113972577, + "fee_asset_price_modifier": 162921764 + }, + "outputs": { + "fee_asset_price_at_execution": 10344333371, + "mana_base_fee_components_in_wei": { + "data_cost": 74, + "gas_cost": 36052413, + "proving_cost": 5419977476, + "congestion_cost": 20160104991, + "congestion_multiplier": 4695013614 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 765, + "gas_cost": 372938178, + "proving_cost": 56066053875, + "congestion_cost": 208542846821, + "congestion_multiplier": 4695013614 + } + } + }, + { + "l1_block_number": 20973779, + "l1_fees": { + "blob_fee": 15649, + "base_fee": 10780629747 + }, + "parent_header": { + "excess_mana": 1321795736, + "mana_used": 108511444, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3548299411 + }, + "header": { + "excess_mana": 1330307180, + "mana_used": 93449181, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3189620902 + }, + "oracle_input": { + "proving_cost_modifier": -93357778, + "fee_asset_price_modifier": -358678509 + }, + "outputs": { + "fee_asset_price_at_execution": 10361200278, + "mana_base_fee_components_in_wei": { + "data_cost": 61, + "gas_cost": 35710836, + "proving_cost": 5415357955, + "congestion_cost": 20397910350, + "congestion_multiplier": 4742001964 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 632, + "gas_cost": 370007123, + "proving_cost": 56109608348, + "congestion_cost": 211346834389, + "congestion_multiplier": 4742001964 + } + } + }, + { + "l1_block_number": 20973782, + "l1_fees": { + "blob_fee": 13910, + "base_fee": 11769070727 + }, + "parent_header": { + "excess_mana": 1330307180, + "mana_used": 93449181, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3189620902 + }, + "header": { + "excess_mana": 1323756361, + "mana_used": 102696150, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3501596935 + }, + "oracle_input": { + "proving_cost_modifier": -140392501, + "fee_asset_price_modifier": 311976033 + }, + "outputs": { + "fee_asset_price_at_execution": 10324103448, + "mana_base_fee_components_in_wei": { + "data_cost": 54, + "gas_cost": 38985046, + "proving_cost": 5415357955, + "congestion_cost": 20212682757, + "congestion_multiplier": 4705796015 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 557, + "gas_cost": 402485647, + "proving_cost": 55908715735, + "congestion_cost": 208677827744, + "congestion_multiplier": 4705796015 + } + } + }, + { + "l1_block_number": 20973785, + "l1_fees": { + "blob_fee": 14467, + "base_fee": 11246048481 + }, + "parent_header": { + "excess_mana": 1323756361, + "mana_used": 102696150, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3501596935 + }, + "header": { + "excess_mana": 1326452511, + "mana_used": 114672112, + "proving_cost_per_mana_numerator": 169825398, + "fee_asset_price_numerator": 2803029127 + }, + "oracle_input": { + "proving_cost_modifier": 169825398, + "fee_asset_price_modifier": -698567808 + }, + "outputs": { + "fee_asset_price_at_execution": 10356362471, + "mana_base_fee_components_in_wei": { + "data_cost": 56, + "gas_cost": 37252535, + "proving_cost": 5415357955, + "congestion_cost": 20287331028, + "congestion_multiplier": 4720663865 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 579, + "gas_cost": 385800755, + "proving_cost": 56083409892, + "congestion_cost": 210102953695, + "congestion_multiplier": 4720663865 + } + } + }, + { + "l1_block_number": 20973788, + "l1_fees": { + "blob_fee": 11431, + "base_fee": 11164890840 + }, + "parent_header": { + "excess_mana": 1326452511, + "mana_used": 114672112, + "proving_cost_per_mana_numerator": 169825398, + "fee_asset_price_numerator": 2803029127 + }, + "header": { + "excess_mana": 1341124623, + "mana_used": 91197669, + "proving_cost_per_mana_numerator": 185721686, + "fee_asset_price_numerator": 3523632779 + }, + "oracle_input": { + "proving_cost_modifier": 15896288, + "fee_asset_price_modifier": 720603652 + }, + "outputs": { + "fee_asset_price_at_execution": 10284268363, + "mana_base_fee_components_in_wei": { + "data_cost": 44, + "gas_cost": 36983700, + "proving_cost": 5424562421, + "congestion_cost": 20766983585, + "congestion_multiplier": 4802400082 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 452, + "gas_cost": 380350295, + "proving_cost": 55787655689, + "congestion_cost": 213573232278, + "congestion_multiplier": 4802400082 + } + } + }, + { + "l1_block_number": 20973791, + "l1_fees": { + "blob_fee": 10991, + "base_fee": 10813707297 + }, + "parent_header": { + "excess_mana": 1341124623, + "mana_used": 91197669, + "proving_cost_per_mana_numerator": 185721686, + "fee_asset_price_numerator": 3523632779 + }, + "header": { + "excess_mana": 1332322292, + "mana_used": 106948598, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3627293630 + }, + "oracle_input": { + "proving_cost_modifier": -193404025, + "fee_asset_price_modifier": 103660851 + }, + "outputs": { + "fee_asset_price_at_execution": 10358644834, + "mana_base_fee_components_in_wei": { + "data_cost": 43, + "gas_cost": 35820405, + "proving_cost": 5425424794, + "congestion_cost": 20497119876, + "congestion_multiplier": 4753195282 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 445, + "gas_cost": 371050853, + "proving_cost": 56200048514, + "congestion_cost": 212322384915, + "congestion_multiplier": 4753195282 + } + } + }, + { + "l1_block_number": 20973794, + "l1_fees": { + "blob_fee": 11431, + "base_fee": 11438721490 + }, + "parent_header": { + "excess_mana": 1332322292, + "mana_used": 106948598, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3627293630 + }, + "header": { + "excess_mana": 1339270890, + "mana_used": 98247953, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3405798460 + }, + "oracle_input": { + "proving_cost_modifier": -104227219, + "fee_asset_price_modifier": -221495170 + }, + "outputs": { + "fee_asset_price_at_execution": 10369388261, + "mana_base_fee_components_in_wei": { + "data_cost": 44, + "gas_cost": 37890764, + "proving_cost": 5415357955, + "congestion_cost": 20678695309, + "congestion_multiplier": 4791995599 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 456, + "gas_cost": 392904043, + "proving_cost": 56153949207, + "congestion_cost": 214425420389, + "congestion_multiplier": 4791995599 + } + } + }, + { + "l1_block_number": 20973797, + "l1_fees": { + "blob_fee": 13910, + "base_fee": 10815929413 + }, + "parent_header": { + "excess_mana": 1339270890, + "mana_used": 98247953, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3405798460 + }, + "header": { + "excess_mana": 1337518843, + "mana_used": 93403246, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 4405798460 + }, + "oracle_input": { + "proving_cost_modifier": -24507243, + "fee_asset_price_modifier": 1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10346445984, + "mana_base_fee_components_in_wei": { + "data_cost": 54, + "gas_cost": 35827766, + "proving_cost": 5415357955, + "congestion_cost": 20617379840, + "congestion_multiplier": 4782182573 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 558, + "gas_cost": 370690045, + "proving_cost": 56029708565, + "congestion_cost": 213316606846, + "congestion_multiplier": 4782182573 + } + } + }, + { + "l1_block_number": 20973800, + "l1_fees": { + "blob_fee": 10991, + "base_fee": 10583530192 + }, + "parent_header": { + "excess_mana": 1337518843, + "mana_used": 93403246, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 4405798460 + }, + "header": { + "excess_mana": 1330922089, + "mana_used": 89690723, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 4114053528 + }, + "oracle_input": { + "proving_cost_modifier": -22027852, + "fee_asset_price_modifier": -291744932 + }, + "outputs": { + "fee_asset_price_at_execution": 10450429495, + "mana_base_fee_components_in_wei": { + "data_cost": 43, + "gas_cost": 35057943, + "proving_cost": 5415357955, + "congestion_cost": 20414068498, + "congestion_multiplier": 4745414794 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 449, + "gas_cost": 366370561, + "proving_cost": 56592816498, + "congestion_cost": 213335783544, + "congestion_multiplier": 4745414794 + } + } + }, + { + "l1_block_number": 20973803, + "l1_fees": { + "blob_fee": 9032, + "base_fee": 11186336309 + }, + "parent_header": { + "excess_mana": 1330922089, + "mana_used": 89690723, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 4114053528 + }, + "header": { + "excess_mana": 1320612812, + "mana_used": 87770657, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 4743652738 + }, + "oracle_input": { + "proving_cost_modifier": -11552448, + "fee_asset_price_modifier": 629599210 + }, + "outputs": { + "fee_asset_price_at_execution": 10419985328, + "mana_base_fee_components_in_wei": { + "data_cost": 35, + "gas_cost": 37054739, + "proving_cost": 5415357955, + "congestion_cost": 20111334004, + "congestion_multiplier": 4688520111 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 364, + "gas_cost": 386109836, + "proving_cost": 56427950436, + "congestion_cost": 209559805248, + "congestion_multiplier": 4688520111 + } + } + }, + { + "l1_block_number": 20973806, + "l1_fees": { + "blob_fee": 8684, + "base_fee": 11129408959 + }, + "parent_header": { + "excess_mana": 1320612812, + "mana_used": 87770657, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 4743652738 + }, + "header": { + "excess_mana": 1308383469, + "mana_used": 102859592, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 5197759505 + }, + "oracle_input": { + "proving_cost_modifier": -4484625, + "fee_asset_price_modifier": 454106767 + }, + "outputs": { + "fee_asset_price_at_execution": 10485796429, + "mana_base_fee_components_in_wei": { + "data_cost": 34, + "gas_cost": 36866167, + "proving_cost": 5415357955, + "congestion_cost": 19747480824, + "congestion_multiplier": 4621912867 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 356, + "gas_cost": 386571122, + "proving_cost": 56784341106, + "congestion_cost": 207068063906, + "congestion_multiplier": 4621912867 + } + } + }, + { + "l1_block_number": 20973809, + "l1_fees": { + "blob_fee": 8684, + "base_fee": 11133709414 + }, + "parent_header": { + "excess_mana": 1308383469, + "mana_used": 102859592, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 5197759505 + }, + "header": { + "excess_mana": 1311243061, + "mana_used": 114671108, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 6197759505 + }, + "oracle_input": { + "proving_cost_modifier": -117737933, + "fee_asset_price_modifier": 1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10533521419, + "mana_base_fee_components_in_wei": { + "data_cost": 34, + "gas_cost": 36880412, + "proving_cost": 5415357955, + "congestion_cost": 19831985061, + "congestion_multiplier": 4637402403 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 358, + "gas_cost": 388480609, + "proving_cost": 57042789010, + "congestion_cost": 208900639421, + "congestion_multiplier": 4637402403 + } + } + }, + { + "l1_block_number": 20973812, + "l1_fees": { + "blob_fee": 9770, + "base_fee": 10564687507 + }, + "parent_header": { + "excess_mana": 1311243061, + "mana_used": 114671108, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 6197759505 + }, + "header": { + "excess_mana": 1325914169, + "mana_used": 96314421, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 7197759505 + }, + "oracle_input": { + "proving_cost_modifier": -61178209, + "fee_asset_price_modifier": 1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10639385069, + "mana_base_fee_components_in_wei": { + "data_cost": 38, + "gas_cost": 34995527, + "proving_cost": 5415357955, + "congestion_cost": 20262732642, + "congestion_multiplier": 4717691443 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 404, + "gas_cost": 372330887, + "proving_cost": 57616078569, + "congestion_cost": 215583015128, + "congestion_multiplier": 4717691443 + } + } + }, + { + "l1_block_number": 20973815, + "l1_fees": { + "blob_fee": 10991, + "base_fee": 9916160334 + }, + "parent_header": { + "excess_mana": 1325914169, + "mana_used": 96314421, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 7197759505 + }, + "header": { + "excess_mana": 1322228590, + "mana_used": 105614317, + "proving_cost_per_mana_numerator": 87880734, + "fee_asset_price_numerator": 7535535998 + }, + "oracle_input": { + "proving_cost_modifier": 87880734, + "fee_asset_price_modifier": 337776493 + }, + "outputs": { + "fee_asset_price_at_execution": 10746312667, + "mana_base_fee_components_in_wei": { + "data_cost": 43, + "gas_cost": 32847281, + "proving_cost": 5415357955, + "congestion_cost": 20144150367, + "congestion_multiplier": 4697391955 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 462, + "gas_cost": 352987151, + "proving_cost": 58195129788, + "congestion_cost": 216475338254, + "congestion_multiplier": 4697391955 + } + } + }, + { + "l1_block_number": 20973818, + "l1_fees": { + "blob_fee": 9770, + "base_fee": 11009914791 + }, + "parent_header": { + "excess_mana": 1322228590, + "mana_used": 105614317, + "proving_cost_per_mana_numerator": 87880734, + "fee_asset_price_numerator": 7535535998 + }, + "header": { + "excess_mana": 1327842907, + "mana_used": 104200639, + "proving_cost_per_mana_numerator": 136531463, + "fee_asset_price_numerator": 6535535998 + }, + "oracle_input": { + "proving_cost_modifier": 48650729, + "fee_asset_price_modifier": -1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10782672558, + "mana_base_fee_components_in_wei": { + "data_cost": 38, + "gas_cost": 36470342, + "proving_cost": 5420119103, + "congestion_cost": 20344072763, + "congestion_multiplier": 4728349517 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 409, + "gas_cost": 393247755, + "proving_cost": 58443369513, + "congestion_cost": 219363475099, + "congestion_multiplier": 4728349517 + } + } + }, + { + "l1_block_number": 20973821, + "l1_fees": { + "blob_fee": 10568, + "base_fee": 11544661257 + }, + "parent_header": { + "excess_mana": 1327842907, + "mana_used": 104200639, + "proving_cost_per_mana_numerator": 136531463, + "fee_asset_price_numerator": 6535535998 + }, + "header": { + "excess_mana": 1332043546, + "mana_used": 95146481, + "proving_cost_per_mana_numerator": 93236650, + "fee_asset_price_numerator": 6189753188 + }, + "oracle_input": { + "proving_cost_modifier": -43294813, + "fee_asset_price_modifier": -345782810 + }, + "outputs": { + "fee_asset_price_at_execution": 10675383173, + "mana_base_fee_components_in_wei": { + "data_cost": 41, + "gas_cost": 38241690, + "proving_cost": 5422756672, + "congestion_cost": 20487729330, + "congestion_multiplier": 4751645362 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 437, + "gas_cost": 408244693, + "proving_cost": 57890005327, + "congestion_cost": 218714360942, + "congestion_multiplier": 4751645362 + } + } + }, + { + "l1_block_number": 20973824, + "l1_fees": { + "blob_fee": 9032, + "base_fee": 11598807653 + }, + "parent_header": { + "excess_mana": 1332043546, + "mana_used": 95146481, + "proving_cost_per_mana_numerator": 93236650, + "fee_asset_price_numerator": 6189753188 + }, + "header": { + "excess_mana": 1327190027, + "mana_used": 85556181, + "proving_cost_per_mana_numerator": 194872565, + "fee_asset_price_numerator": 6205591853 + }, + "oracle_input": { + "proving_cost_modifier": 101635915, + "fee_asset_price_modifier": 15838665 + }, + "outputs": { + "fee_asset_price_at_execution": 10638533280, + "mana_base_fee_components_in_wei": { + "data_cost": 35, + "gas_cost": 38421050, + "proving_cost": 5420409407, + "congestion_cost": 20332719122, + "congestion_multiplier": 4724739054 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 372, + "gas_cost": 408743619, + "proving_cost": 57665205867, + "congestion_cost": 216310309052, + "congestion_multiplier": 4724739054 + } + } + }, + { + "l1_block_number": 20973827, + "l1_fees": { + "blob_fee": 9032, + "base_fee": 11635181863 + }, + "parent_header": { + "excess_mana": 1327190027, + "mana_used": 85556181, + "proving_cost_per_mana_numerator": 194872565, + "fee_asset_price_numerator": 6205591853 + }, + "header": { + "excess_mana": 1312746208, + "mana_used": 100135907, + "proving_cost_per_mana_numerator": 240667911, + "fee_asset_price_numerator": 6278612236 + }, + "oracle_input": { + "proving_cost_modifier": 45795346, + "fee_asset_price_modifier": 73020383 + }, + "outputs": { + "fee_asset_price_at_execution": 10640218416, + "mana_base_fee_components_in_wei": { + "data_cost": 35, + "gas_cost": 38541539, + "proving_cost": 5425921291, + "congestion_cost": 19921056176, + "congestion_multiplier": 4645565295 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 372, + "gas_cost": 410090393, + "proving_cost": 57732987644, + "congestion_cost": 211964388790, + "congestion_multiplier": 4645565295 + } + } + }, + { + "l1_block_number": 20973830, + "l1_fees": { + "blob_fee": 9770, + "base_fee": 10954393731 + }, + "parent_header": { + "excess_mana": 1312746208, + "mana_used": 100135907, + "proving_cost_per_mana_numerator": 240667911, + "fee_asset_price_numerator": 6278612236 + }, + "header": { + "excess_mana": 1312882115, + "mana_used": 102142387, + "proving_cost_per_mana_numerator": 301905516, + "fee_asset_price_numerator": 6462410828 + }, + "oracle_input": { + "proving_cost_modifier": 61237605, + "fee_asset_price_modifier": 183798592 + }, + "outputs": { + "fee_asset_price_at_execution": 10647990781, + "mana_base_fee_components_in_wei": { + "data_cost": 38, + "gas_cost": 36286429, + "proving_cost": 5428406679, + "congestion_cost": 19925932750, + "congestion_multiplier": 4646304050 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 404, + "gas_cost": 386377561, + "proving_cost": 57801624273, + "congestion_cost": 212171148224, + "congestion_multiplier": 4646304050 + } + } + }, + { + "l1_block_number": 20973833, + "l1_fees": { + "blob_fee": 9032, + "base_fee": 12832884693 + }, + "parent_header": { + "excess_mana": 1312882115, + "mana_used": 102142387, + "proving_cost_per_mana_numerator": 301905516, + "fee_asset_price_numerator": 6462410828 + }, + "header": { + "excess_mana": 1315024502, + "mana_used": 108099379, + "proving_cost_per_mana_numerator": 186947548, + "fee_asset_price_numerator": 6196588479 + }, + "oracle_input": { + "proving_cost_modifier": -114957968, + "fee_asset_price_modifier": -265822349 + }, + "outputs": { + "fee_asset_price_at_execution": 10667579635, + "mana_base_fee_components_in_wei": { + "data_cost": 35, + "gas_cost": 42508930, + "proving_cost": 5431731923, + "congestion_cost": 20024581849, + "congestion_multiplier": 4657965051 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 373, + "gas_cost": 453467395, + "proving_cost": 57943432844, + "congestion_cost": 213613821531, + "congestion_multiplier": 4657965051 + } + } + }, + { + "l1_block_number": 20973836, + "l1_fees": { + "blob_fee": 7422, + "base_fee": 11598902204 + }, + "parent_header": { + "excess_mana": 1315024502, + "mana_used": 108099379, + "proving_cost_per_mana_numerator": 186947548, + "fee_asset_price_numerator": 6196588479 + }, + "header": { + "excess_mana": 1323123881, + "mana_used": 112983367, + "proving_cost_per_mana_numerator": 317869118, + "fee_asset_price_numerator": 5612257785 + }, + "oracle_input": { + "proving_cost_modifier": 130921570, + "fee_asset_price_modifier": -584330694 + }, + "outputs": { + "fee_asset_price_at_execution": 10639260480, + "mana_base_fee_components_in_wei": { + "data_cost": 29, + "gas_cost": 38421363, + "proving_cost": 5425491302, + "congestion_cost": 20229125958, + "congestion_multiplier": 4702315006 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 308, + "gas_cost": 408774888, + "proving_cost": 57723215193, + "congestion_cost": 215222940349, + "congestion_multiplier": 4702315006 + } + } + }, + { + "l1_block_number": 20973839, + "l1_fees": { + "blob_fee": 8684, + "base_fee": 11475907941 + }, + "parent_header": { + "excess_mana": 1323123881, + "mana_used": 112983367, + "proving_cost_per_mana_numerator": 317869118, + "fee_asset_price_numerator": 5612257785 + }, + "header": { + "excess_mana": 1336107248, + "mana_used": 78716153, + "proving_cost_per_mana_numerator": 324730950, + "fee_asset_price_numerator": 5123208967 + }, + "oracle_input": { + "proving_cost_modifier": 6861832, + "fee_asset_price_modifier": -489048818 + }, + "outputs": { + "fee_asset_price_at_execution": 10577273297, + "mana_base_fee_components_in_wei": { + "data_cost": 34, + "gas_cost": 38013945, + "proving_cost": 5432599093, + "congestion_cost": 20647685682, + "congestion_multiplier": 4774291000 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 359, + "gas_cost": 402083885, + "proving_cost": 57462085319, + "congestion_cost": 218396214409, + "congestion_multiplier": 4774291000 + } + } + }, + { + "l1_block_number": 20973842, + "l1_fees": { + "blob_fee": 9032, + "base_fee": 11221372712 + }, + "parent_header": { + "excess_mana": 1336107248, + "mana_used": 78716153, + "proving_cost_per_mana_numerator": 324730950, + "fee_asset_price_numerator": 5123208967 + }, + "header": { + "excess_mana": 1314823401, + "mana_used": 100573975, + "proving_cost_per_mana_numerator": 462472768, + "fee_asset_price_numerator": 5461974111 + }, + "oracle_input": { + "proving_cost_modifier": 137741818, + "fee_asset_price_modifier": 338765144 + }, + "outputs": { + "fee_asset_price_at_execution": 10525671549, + "mana_base_fee_components_in_wei": { + "data_cost": 35, + "gas_cost": 37170797, + "proving_cost": 5432971881, + "congestion_cost": 20003596494, + "congestion_multiplier": 4656869216 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 368, + "gas_cost": 391247600, + "proving_cost": 57185677554, + "congestion_cost": 210551286494, + "congestion_multiplier": 4656869216 + } + } + }, + { + "l1_block_number": 20973845, + "l1_fees": { + "blob_fee": 7136, + "base_fee": 11631406437 + }, + "parent_header": { + "excess_mana": 1314823401, + "mana_used": 100573975, + "proving_cost_per_mana_numerator": 462472768, + "fee_asset_price_numerator": 5461974111 + }, + "header": { + "excess_mana": 1315397376, + "mana_used": 109913708, + "proving_cost_per_mana_numerator": 413470065, + "fee_asset_price_numerator": 5513990530 + }, + "oracle_input": { + "proving_cost_modifier": -49002703, + "fee_asset_price_modifier": 52016419 + }, + "outputs": { + "fee_asset_price_at_execution": 10561389320, + "mana_base_fee_components_in_wei": { + "data_cost": 28, + "gas_cost": 38529033, + "proving_cost": 5440460512, + "congestion_cost": 20053088632, + "congestion_multiplier": 4659997590 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 295, + "gas_cost": 406920117, + "proving_cost": 57458821547, + "congestion_cost": 211788476111, + "congestion_multiplier": 4659997590 + } + } + }, + { + "l1_block_number": 20973848, + "l1_fees": { + "blob_fee": 9032, + "base_fee": 11248483537 + }, + "parent_header": { + "excess_mana": 1315397376, + "mana_used": 109913708, + "proving_cost_per_mana_numerator": 413470065, + "fee_asset_price_numerator": 5513990530 + }, + "header": { + "excess_mana": 1325311084, + "mana_used": 96372911, + "proving_cost_per_mana_numerator": 224365590, + "fee_asset_price_numerator": 6431399838 + }, + "oracle_input": { + "proving_cost_modifier": -189104475, + "fee_asset_price_modifier": 917409308 + }, + "outputs": { + "fee_asset_price_at_execution": 10566884406, + "mana_base_fee_components_in_wei": { + "data_cost": 35, + "gas_cost": 37260601, + "proving_cost": 5437795192, + "congestion_cost": 20336349006, + "congestion_multiplier": 4714363770 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 369, + "gas_cost": 393728463, + "proving_cost": 57460553217, + "congestion_cost": 214891849186, + "congestion_multiplier": 4714363770 + } + } + }, + { + "l1_block_number": 20973851, + "l1_fees": { + "blob_fee": 9393, + "base_fee": 10907228421 + }, + "parent_header": { + "excess_mana": 1325311084, + "mana_used": 96372911, + "proving_cost_per_mana_numerator": 224365590, + "fee_asset_price_numerator": 6431399838 + }, + "header": { + "excess_mana": 1321683995, + "mana_used": 108674213, + "proving_cost_per_mana_numerator": 293389751, + "fee_asset_price_numerator": 5928393552 + }, + "oracle_input": { + "proving_cost_modifier": 69024161, + "fee_asset_price_modifier": -503006286 + }, + "outputs": { + "fee_asset_price_at_execution": 10664272026, + "mana_base_fee_components_in_wei": { + "data_cost": 36, + "gas_cost": 36130194, + "proving_cost": 5427521795, + "congestion_cost": 20184915177, + "congestion_multiplier": 4694399842 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 383, + "gas_cost": 385302217, + "proving_cost": 57880568848, + "congestion_cost": 215257426269, + "congestion_multiplier": 4694399842 + } + } + }, + { + "l1_block_number": 20973854, + "l1_fees": { + "blob_fee": 7422, + "base_fee": 9545453468 + }, + "parent_header": { + "excess_mana": 1321683995, + "mana_used": 108674213, + "proving_cost_per_mana_numerator": 293389751, + "fee_asset_price_numerator": 5928393552 + }, + "header": { + "excess_mana": 1330358208, + "mana_used": 97567357, + "proving_cost_per_mana_numerator": 358988705, + "fee_asset_price_numerator": 5941926306 + }, + "oracle_input": { + "proving_cost_modifier": 65598954, + "fee_asset_price_modifier": 13532754 + }, + "outputs": { + "fee_asset_price_at_execution": 10610764752, + "mana_base_fee_components_in_wei": { + "data_cost": 29, + "gas_cost": 31619314, + "proving_cost": 5431269390, + "congestion_cost": 20443687015, + "congestion_multiplier": 4742285083 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 307, + "gas_cost": 335505102, + "proving_cost": 57629921802, + "congestion_cost": 216923153579, + "congestion_multiplier": 4742285083 + } + } + }, + { + "l1_block_number": 20973857, + "l1_fees": { + "blob_fee": 7422, + "base_fee": 10287223911 + }, + "parent_header": { + "excess_mana": 1330358208, + "mana_used": 97567357, + "proving_cost_per_mana_numerator": 358988705, + "fee_asset_price_numerator": 5941926306 + }, + "header": { + "excess_mana": 1327925565, + "mana_used": 94180350, + "proving_cost_per_mana_numerator": 559496247, + "fee_asset_price_numerator": 5925072455 + }, + "oracle_input": { + "proving_cost_modifier": 200507542, + "fee_asset_price_modifier": -16853851 + }, + "outputs": { + "fee_asset_price_at_execution": 10612200778, + "mana_base_fee_components_in_wei": { + "data_cost": 29, + "gas_cost": 34076429, + "proving_cost": 5434833414, + "congestion_cost": 20392508412, + "congestion_multiplier": 4728806817 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 307, + "gas_cost": 361625906, + "proving_cost": 57675543384, + "congestion_cost": 216409393635, + "congestion_multiplier": 4728806817 + } + } + }, + { + "l1_block_number": 20973860, + "l1_fees": { + "blob_fee": 8350, + "base_fee": 10427086319 + }, + "parent_header": { + "excess_mana": 1327925565, + "mana_used": 94180350, + "proving_cost_per_mana_numerator": 559496247, + "fee_asset_price_numerator": 5925072455 + }, + "header": { + "excess_mana": 1322105915, + "mana_used": 109300669, + "proving_cost_per_mana_numerator": 478003486, + "fee_asset_price_numerator": 5647205267 + }, + "oracle_input": { + "proving_cost_modifier": -81492761, + "fee_asset_price_modifier": -277867188 + }, + "outputs": { + "fee_asset_price_at_execution": 10610412364, + "mana_base_fee_components_in_wei": { + "data_cost": 32, + "gas_cost": 34539723, + "proving_cost": 5445741597, + "congestion_cost": 20259053557, + "congestion_multiplier": 4696717788 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 339, + "gas_cost": 366480703, + "proving_cost": 57781563971, + "congestion_cost": 214956912344, + "congestion_multiplier": 4696717788 + } + } + }, + { + "l1_block_number": 20973863, + "l1_fees": { + "blob_fee": 8684, + "base_fee": 9924491355 + }, + "parent_header": { + "excess_mana": 1322105915, + "mana_used": 109300669, + "proving_cost_per_mana_numerator": 478003486, + "fee_asset_price_numerator": 5647205267 + }, + "header": { + "excess_mana": 1331406584, + "mana_used": 85994446, + "proving_cost_per_mana_numerator": 530330013, + "fee_asset_price_numerator": 5789146465 + }, + "oracle_input": { + "proving_cost_modifier": 52326527, + "fee_asset_price_modifier": 141941198 + }, + "outputs": { + "fee_asset_price_at_execution": 10580970433, + "mana_base_fee_components_in_wei": { + "data_cost": 34, + "gas_cost": 32874877, + "proving_cost": 5441305520, + "congestion_cost": 20517805989, + "congestion_multiplier": 4748105538 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 359, + "gas_cost": 347848101, + "proving_cost": 57574292824, + "congestion_cost": 217098298519, + "congestion_multiplier": 4748105538 + } + } + }, + { + "l1_block_number": 20973866, + "l1_fees": { + "blob_fee": 8028, + "base_fee": 9354627250 + }, + "parent_header": { + "excess_mana": 1331406584, + "mana_used": 85994446, + "proving_cost_per_mana_numerator": 530330013, + "fee_asset_price_numerator": 5789146465 + }, + "header": { + "excess_mana": 1317401030, + "mana_used": 115714558, + "proving_cost_per_mana_numerator": 545799712, + "fee_asset_price_numerator": 6088022736 + }, + "oracle_input": { + "proving_cost_modifier": 15469699, + "fee_asset_price_modifier": 298876271 + }, + "outputs": { + "fee_asset_price_at_execution": 10595999854, + "mana_base_fee_components_in_wei": { + "data_cost": 31, + "gas_cost": 30987202, + "proving_cost": 5444153511, + "congestion_cost": 20098884264, + "congestion_multiplier": 4670934722 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 328, + "gas_cost": 328340387, + "proving_cost": 57686249807, + "congestion_cost": 212967774726, + "congestion_multiplier": 4670934722 + } + } + }, + { + "l1_block_number": 20973869, + "l1_fees": { + "blob_fee": 8028, + "base_fee": 9518637418 + }, + "parent_header": { + "excess_mana": 1317401030, + "mana_used": 115714558, + "proving_cost_per_mana_numerator": 545799712, + "fee_asset_price_numerator": 6088022736 + }, + "header": { + "excess_mana": 1333115588, + "mana_used": 80109579, + "proving_cost_per_mana_numerator": 517094254, + "fee_asset_price_numerator": 5088022736 + }, + "oracle_input": { + "proving_cost_modifier": -28705458, + "fee_asset_price_modifier": -1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10627716156, + "mana_base_fee_components_in_wei": { + "data_cost": 31, + "gas_cost": 31530486, + "proving_cost": 5444995771, + "congestion_cost": 20578644676, + "congestion_multiplier": 4757609038 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 329, + "gas_cost": 335097055, + "proving_cost": 57867869524, + "congestion_cost": 218703994491, + "congestion_multiplier": 4757609038 + } + } + }, + { + "l1_block_number": 20973872, + "l1_fees": { + "blob_fee": 7136, + "base_fee": 9000307024 + }, + "parent_header": { + "excess_mana": 1333115588, + "mana_used": 80109579, + "proving_cost_per_mana_numerator": 517094254, + "fee_asset_price_numerator": 5088022736 + }, + "header": { + "excess_mana": 1313225167, + "mana_used": 104097263, + "proving_cost_per_mana_numerator": 663259335, + "fee_asset_price_numerator": 5536783075 + }, + "oracle_input": { + "proving_cost_modifier": 146165081, + "fee_asset_price_modifier": 448760339 + }, + "outputs": { + "fee_asset_price_at_execution": 10521968613, + "mana_base_fee_components_in_wei": { + "data_cost": 28, + "gas_cost": 29813517, + "proving_cost": 5443432984, + "congestion_cost": 19967330046, + "congestion_multiplier": 4648169316 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 294, + "gas_cost": 313696890, + "proving_cost": 57275631004, + "congestion_cost": 210095620029, + "congestion_multiplier": 4648169316 + } + } + }, + { + "l1_block_number": 20973875, + "l1_fees": { + "blob_fee": 7136, + "base_fee": 9715580015 + }, + "parent_header": { + "excess_mana": 1313225167, + "mana_used": 104097263, + "proving_cost_per_mana_numerator": 663259335, + "fee_asset_price_numerator": 5536783075 + }, + "header": { + "excess_mana": 1317322430, + "mana_used": 99293585, + "proving_cost_per_mana_numerator": 616335512, + "fee_asset_price_numerator": 6206207375 + }, + "oracle_input": { + "proving_cost_modifier": -46923823, + "fee_asset_price_modifier": 669424300 + }, + "outputs": { + "fee_asset_price_at_execution": 10569293142, + "mana_base_fee_components_in_wei": { + "data_cost": 28, + "gas_cost": 32182858, + "proving_cost": 5451395200, + "congestion_cost": 20127501840, + "congestion_multiplier": 4670505193 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 295, + "gas_cost": 340150060, + "proving_cost": 57617393901, + "congestion_cost": 212733467163, + "congestion_multiplier": 4670505193 + } + } + }, + { + "l1_block_number": 20973878, + "l1_fees": { + "blob_fee": 6099, + "base_fee": 8927204530 + }, + "parent_header": { + "excess_mana": 1317322430, + "mana_used": 99293585, + "proving_cost_per_mana_numerator": 616335512, + "fee_asset_price_numerator": 6206207375 + }, + "header": { + "excess_mana": 1316616015, + "mana_used": 101973942, + "proving_cost_per_mana_numerator": 744096576, + "fee_asset_price_numerator": 6298133503 + }, + "oracle_input": { + "proving_cost_modifier": 127761064, + "fee_asset_price_modifier": 91926128 + }, + "outputs": { + "fee_asset_price_at_execution": 10640283909, + "mana_base_fee_components_in_wei": { + "data_cost": 23, + "gas_cost": 29571365, + "proving_cost": 5448837797, + "congestion_cost": 20087390356, + "congestion_multiplier": 4666646590 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 244, + "gas_cost": 314647719, + "proving_cost": 57977181134, + "congestion_cost": 213735536378, + "congestion_multiplier": 4666646590 + } + } + }, + { + "l1_block_number": 20973881, + "l1_fees": { + "blob_fee": 5421, + "base_fee": 10606716360 + }, + "parent_header": { + "excess_mana": 1316616015, + "mana_used": 101973942, + "proving_cost_per_mana_numerator": 744096576, + "fee_asset_price_numerator": 6298133503 + }, + "header": { + "excess_mana": 1318589957, + "mana_used": 108359431, + "proving_cost_per_mana_numerator": 823483761, + "fee_asset_price_numerator": 7008616691 + }, + "oracle_input": { + "proving_cost_modifier": 79387185, + "fee_asset_price_modifier": 710483188 + }, + "outputs": { + "fee_asset_price_at_execution": 10650069607, + "mana_base_fee_components_in_wei": { + "data_cost": 21, + "gas_cost": 35134747, + "proving_cost": 5455803739, + "congestion_cost": 20192578903, + "congestion_multiplier": 4677436722 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 223, + "gas_cost": 374187501, + "proving_cost": 58104689582, + "congestion_cost": 215052370861, + "congestion_multiplier": 4677436722 + } + } + }, + { + "l1_block_number": 20973884, + "l1_fees": { + "blob_fee": 6597, + "base_fee": 10633601318 + }, + "parent_header": { + "excess_mana": 1318589957, + "mana_used": 108359431, + "proving_cost_per_mana_numerator": 823483761, + "fee_asset_price_numerator": 7008616691 + }, + "header": { + "excess_mana": 1326949388, + "mana_used": 93769846, + "proving_cost_per_mana_numerator": 804692960, + "fee_asset_price_numerator": 6632734847 + }, + "oracle_input": { + "proving_cost_modifier": -18790801, + "fee_asset_price_modifier": -375881844 + }, + "outputs": { + "fee_asset_price_at_execution": 10726005999, + "mana_base_fee_components_in_wei": { + "data_cost": 25, + "gas_cost": 35223804, + "proving_cost": 5460136668, + "congestion_cost": 20461474743, + "congestion_multiplier": 4723409002 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 268, + "gas_cost": 377810733, + "proving_cost": 58565458656, + "congestion_cost": 219469900841, + "congestion_multiplier": 4723409002 + } + } + }, + { + "l1_block_number": 20973887, + "l1_fees": { + "blob_fee": 5638, + "base_fee": 10484045237 + }, + "parent_header": { + "excess_mana": 1326949388, + "mana_used": 93769846, + "proving_cost_per_mana_numerator": 804692960, + "fee_asset_price_numerator": 6632734847 + }, + "header": { + "excess_mana": 1320719234, + "mana_used": 103746665, + "proving_cost_per_mana_numerator": 679575357, + "fee_asset_price_numerator": 6735831846 + }, + "oracle_input": { + "proving_cost_modifier": -125117603, + "fee_asset_price_modifier": 103096999 + }, + "outputs": { + "fee_asset_price_at_execution": 10685764567, + "mana_base_fee_components_in_wei": { + "data_cost": 22, + "gas_cost": 34728399, + "proving_cost": 5459110761, + "congestion_cost": 20267343728, + "congestion_multiplier": 4689103932 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 235, + "gas_cost": 371099495, + "proving_cost": 58334772337, + "congestion_cost": 216572063475, + "congestion_multiplier": 4689103932 + } + } + }, + { + "l1_block_number": 20973890, + "l1_fees": { + "blob_fee": 5012, + "base_fee": 10168986743 + }, + "parent_header": { + "excess_mana": 1320719234, + "mana_used": 103746665, + "proving_cost_per_mana_numerator": 679575357, + "fee_asset_price_numerator": 6735831846 + }, + "header": { + "excess_mana": 1324465899, + "mana_used": 90509291, + "proving_cost_per_mana_numerator": 739167168, + "fee_asset_price_numerator": 6908356568 + }, + "oracle_input": { + "proving_cost_modifier": 59591811, + "fee_asset_price_modifier": 172524722 + }, + "outputs": { + "fee_asset_price_at_execution": 10696786951, + "mana_base_fee_components_in_wei": { + "data_cost": 19, + "gas_cost": 33684768, + "proving_cost": 5452284723, + "congestion_cost": 20351324121, + "congestion_multiplier": 4709704198 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 203, + "gas_cost": 360318786, + "proving_cost": 58321928078, + "congestion_cost": 217693778293, + "congestion_multiplier": 4709704198 + } + } + }, + { + "l1_block_number": 20973893, + "l1_fees": { + "blob_fee": 5212, + "base_fee": 10173503699 + }, + "parent_header": { + "excess_mana": 1324465899, + "mana_used": 90509291, + "proving_cost_per_mana_numerator": 739167168, + "fee_asset_price_numerator": 6908356568 + }, + "header": { + "excess_mana": 1314975190, + "mana_used": 95614584, + "proving_cost_per_mana_numerator": 803144628, + "fee_asset_price_numerator": 5992437132 + }, + "oracle_input": { + "proving_cost_modifier": 63977460, + "fee_asset_price_modifier": -915919436 + }, + "outputs": { + "fee_asset_price_at_execution": 10715257481, + "mana_base_fee_components_in_wei": { + "data_cost": 20, + "gas_cost": 33699731, + "proving_cost": 5455534807, + "congestion_cost": 20077953031, + "congestion_multiplier": 4657696318 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 214, + "gas_cost": 361101294, + "proving_cost": 58457460153, + "congestion_cost": 215140436418, + "congestion_multiplier": 4657696318 + } + } + }, + { + "l1_block_number": 20973896, + "l1_fees": { + "blob_fee": 4633, + "base_fee": 9849078319 + }, + "parent_header": { + "excess_mana": 1314975190, + "mana_used": 95614584, + "proving_cost_per_mana_numerator": 803144628, + "fee_asset_price_numerator": 5992437132 + }, + "header": { + "excess_mana": 1310589774, + "mana_used": 118091830, + "proving_cost_per_mana_numerator": 902000402, + "fee_asset_price_numerator": 5439598060 + }, + "oracle_input": { + "proving_cost_modifier": 98855774, + "fee_asset_price_modifier": -552839072 + }, + "outputs": { + "fee_asset_price_at_execution": 10617562442, + "mana_base_fee_components_in_wei": { + "data_cost": 18, + "gas_cost": 32625071, + "proving_cost": 5459026236, + "congestion_cost": 19955887569, + "congestion_multiplier": 4633859178 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 191, + "gas_cost": 346398728, + "proving_cost": 57961551933, + "congestion_cost": 211882882349, + "congestion_multiplier": 4633859178 + } + } + }, + { + "l1_block_number": 20973899, + "l1_fees": { + "blob_fee": 3960, + "base_fee": 9095741753 + }, + "parent_header": { + "excess_mana": 1310589774, + "mana_used": 118091830, + "proving_cost_per_mana_numerator": 902000402, + "fee_asset_price_numerator": 5439598060 + }, + "header": { + "excess_mana": 1328681604, + "mana_used": 98625135, + "proving_cost_per_mana_numerator": 877969508, + "fee_asset_price_numerator": 5844735540 + }, + "oracle_input": { + "proving_cost_modifier": -24030894, + "fee_asset_price_modifier": 405137480 + }, + "outputs": { + "fee_asset_price_at_execution": 10559026363, + "mana_base_fee_components_in_wei": { + "data_cost": 15, + "gas_cost": 30129644, + "proving_cost": 5464425467, + "congestion_cost": 20511128175, + "congestion_multiplier": 4732991608 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 158, + "gas_cost": 318139705, + "proving_cost": 57699012564, + "congestion_cost": 216577543134, + "congestion_multiplier": 4732991608 + } + } + }, + { + "l1_block_number": 20973902, + "l1_fees": { + "blob_fee": 5638, + "base_fee": 10224559786 + }, + "parent_header": { + "excess_mana": 1328681604, + "mana_used": 98625135, + "proving_cost_per_mana_numerator": 877969508, + "fee_asset_price_numerator": 5844735540 + }, + "header": { + "excess_mana": 1327306739, + "mana_used": 106256841, + "proving_cost_per_mana_numerator": 1003946519, + "fee_asset_price_numerator": 6652818122 + }, + "oracle_input": { + "proving_cost_modifier": 125977011, + "fee_asset_price_modifier": 808082582 + }, + "outputs": { + "fee_asset_price_at_execution": 10601891709, + "mana_base_fee_components_in_wei": { + "data_cost": 22, + "gas_cost": 33868854, + "proving_cost": 5463112474, + "congestion_cost": 20478367886, + "congestion_multiplier": 4725384276 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 233, + "gas_cost": 359073922, + "proving_cost": 57919326843, + "congestion_cost": 217109438704, + "congestion_multiplier": 4725384276 + } + } + }, + { + "l1_block_number": 20973905, + "l1_fees": { + "blob_fee": 6343, + "base_fee": 9839987831 + }, + "parent_header": { + "excess_mana": 1327306739, + "mana_used": 106256841, + "proving_cost_per_mana_numerator": 1003946519, + "fee_asset_price_numerator": 6652818122 + }, + "header": { + "excess_mana": 1333563580, + "mana_used": 80690418, + "proving_cost_per_mana_numerator": 944388983, + "fee_asset_price_numerator": 7269251791 + }, + "oracle_input": { + "proving_cost_modifier": -59557536, + "fee_asset_price_modifier": 616433669 + }, + "outputs": { + "fee_asset_price_at_execution": 10687910834, + "mana_base_fee_components_in_wei": { + "data_cost": 24, + "gas_cost": 32594959, + "proving_cost": 5469999077, + "congestion_cost": 20690322611, + "congestion_multiplier": 4760103396 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 256, + "gas_cost": 348372015, + "proving_cost": 58462862397, + "congestion_cost": 221136323193, + "congestion_multiplier": 4760103396 + } + } + }, + { + "l1_block_number": 20973908, + "l1_fees": { + "blob_fee": 5638, + "base_fee": 9805616497 + }, + "parent_header": { + "excess_mana": 1333563580, + "mana_used": 80690418, + "proving_cost_per_mana_numerator": 944388983, + "fee_asset_price_numerator": 7269251791 + }, + "header": { + "excess_mana": 1314253998, + "mana_used": 94413917, + "proving_cost_per_mana_numerator": 1122815630, + "fee_asset_price_numerator": 7087350090 + }, + "oracle_input": { + "proving_cost_modifier": 178426647, + "fee_asset_price_modifier": -181901701 + }, + "outputs": { + "fee_asset_price_at_execution": 10753998198, + "mana_base_fee_components_in_wei": { + "data_cost": 22, + "gas_cost": 32481104, + "proving_cost": 5466742250, + "congestion_cost": 20092885494, + "congestion_multiplier": 4653767836 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 236, + "gas_cost": 349301733, + "proving_cost": 58789336305, + "congestion_cost": 216078854395, + "congestion_multiplier": 4653767836 + } + } + }, + { + "l1_block_number": 20973911, + "l1_fees": { + "blob_fee": 6861, + "base_fee": 10431780206 + }, + "parent_header": { + "excess_mana": 1314253998, + "mana_used": 94413917, + "proving_cost_per_mana_numerator": 1122815630, + "fee_asset_price_numerator": 7087350090 + }, + "header": { + "excess_mana": 1308667915, + "mana_used": 94607795, + "proving_cost_per_mana_numerator": 1062906274, + "fee_asset_price_numerator": 7390849530 + }, + "oracle_input": { + "proving_cost_modifier": -59909356, + "fee_asset_price_modifier": 303499440 + }, + "outputs": { + "fee_asset_price_at_execution": 10734454273, + "mana_base_fee_components_in_wei": { + "data_cost": 26, + "gas_cost": 34555271, + "proving_cost": 5476505082, + "congestion_cost": 19969058916, + "congestion_multiplier": 4623451304 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 279, + "gas_cost": 370931976, + "proving_cost": 58787293378, + "congestion_cost": 214356949808, + "congestion_multiplier": 4623451304 + } + } + }, + { + "l1_block_number": 20973914, + "l1_fees": { + "blob_fee": 5638, + "base_fee": 9780268893 + }, + "parent_header": { + "excess_mana": 1308667915, + "mana_used": 94607795, + "proving_cost_per_mana_numerator": 1062906274, + "fee_asset_price_numerator": 7390849530 + }, + "header": { + "excess_mana": 1303275710, + "mana_used": 102054688, + "proving_cost_per_mana_numerator": 1109743580, + "fee_asset_price_numerator": 7115220745 + }, + "oracle_input": { + "proving_cost_modifier": 46837306, + "fee_asset_price_modifier": -275628785 + }, + "outputs": { + "fee_asset_price_at_execution": 10767082771, + "mana_base_fee_components_in_wei": { + "data_cost": 22, + "gas_cost": 32397140, + "proving_cost": 5473225126, + "congestion_cost": 19789267384, + "congestion_multiplier": 4594374323 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 236, + "gas_cost": 348822687, + "proving_cost": 58930667955, + "congestion_cost": 213072679900, + "congestion_multiplier": 4594374323 + } + } + }, + { + "l1_block_number": 20973917, + "l1_fees": { + "blob_fee": 5421, + "base_fee": 9759622835 + }, + "parent_header": { + "excess_mana": 1303275710, + "mana_used": 102054688, + "proving_cost_per_mana_numerator": 1109743580, + "fee_asset_price_numerator": 7115220745 + }, + "header": { + "excess_mana": 1305330398, + "mana_used": 111328474, + "proving_cost_per_mana_numerator": 1232702340, + "fee_asset_price_numerator": 6300753413 + }, + "oracle_input": { + "proving_cost_modifier": 122958760, + "fee_asset_price_modifier": -814467332 + }, + "outputs": { + "fee_asset_price_at_execution": 10737446453, + "mana_base_fee_components_in_wei": { + "data_cost": 21, + "gas_cost": 32328750, + "proving_cost": 5475789238, + "congestion_cost": 19859147220, + "congestion_multiplier": 4605432416 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 225, + "gas_cost": 347128222, + "proving_cost": 58795993730, + "congestion_cost": 213236529876, + "congestion_multiplier": 4605432416 + } + } + }, + { + "l1_block_number": 20973920, + "l1_fees": { + "blob_fee": 5421, + "base_fee": 9073108440 + }, + "parent_header": { + "excess_mana": 1305330398, + "mana_used": 111328474, + "proving_cost_per_mana_numerator": 1232702340, + "fee_asset_price_numerator": 6300753413 + }, + "header": { + "excess_mana": 1316658872, + "mana_used": 100397610, + "proving_cost_per_mana_numerator": 1217180126, + "fee_asset_price_numerator": 6073245524 + }, + "oracle_input": { + "proving_cost_modifier": -15522214, + "fee_asset_price_modifier": -227507889 + }, + "outputs": { + "fee_asset_price_at_execution": 10650348633, + "mana_base_fee_components_in_wei": { + "data_cost": 21, + "gas_cost": 30054671, + "proving_cost": 5482526341, + "congestion_cost": 20213976412, + "congestion_multiplier": 4666880594 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 223, + "gas_cost": 320092724, + "proving_cost": 58390816921, + "congestion_cost": 215285896047, + "congestion_multiplier": 4666880594 + } + } + }, + { + "l1_block_number": 20973923, + "l1_fees": { + "blob_fee": 5638, + "base_fee": 9354730809 + }, + "parent_header": { + "excess_mana": 1316658872, + "mana_used": 100397610, + "proving_cost_per_mana_numerator": 1217180126, + "fee_asset_price_numerator": 6073245524 + }, + "header": { + "excess_mana": 1317056482, + "mana_used": 124200577, + "proving_cost_per_mana_numerator": 1270767834, + "fee_asset_price_numerator": 6054705245 + }, + "oracle_input": { + "proving_cost_modifier": 53587708, + "fee_asset_price_modifier": -18540279 + }, + "outputs": { + "fee_asset_price_at_execution": 10626145791, + "mana_base_fee_components_in_wei": { + "data_cost": 22, + "gas_cost": 30987545, + "proving_cost": 5481675398, + "congestion_cost": 20226247898, + "congestion_multiplier": 4669052149 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 233, + "gas_cost": 329278170, + "proving_cost": 58249081958, + "congestion_cost": 214927058969, + "congestion_multiplier": 4669052149 + } + } + }, + { + "l1_block_number": 20973926, + "l1_fees": { + "blob_fee": 4819, + "base_fee": 9798923863 + }, + "parent_header": { + "excess_mana": 1317056482, + "mana_used": 124200577, + "proving_cost_per_mana_numerator": 1270767834, + "fee_asset_price_numerator": 6054705245 + }, + "header": { + "excess_mana": 1341257059, + "mana_used": 90324589, + "proving_cost_per_mana_numerator": 1657418320, + "fee_asset_price_numerator": 5270904101 + }, + "oracle_input": { + "proving_cost_modifier": 386650486, + "fee_asset_price_modifier": -783801144 + }, + "outputs": { + "fee_asset_price_at_execution": 10624175857, + "mana_base_fee_components_in_wei": { + "data_cost": 18, + "gas_cost": 32458935, + "proving_cost": 5484613689, + "congestion_cost": 20982223216, + "congestion_multiplier": 4803144272 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 191, + "gas_cost": 344849433, + "proving_cost": 58269500339, + "congestion_cost": 222918829317, + "congestion_multiplier": 4803144272 + } + } + }, + { + "l1_block_number": 20973929, + "l1_fees": { + "blob_fee": 5012, + "base_fee": 9491280379 + }, + "parent_header": { + "excess_mana": 1341257059, + "mana_used": 90324589, + "proving_cost_per_mana_numerator": 1657418320, + "fee_asset_price_numerator": 5270904101 + }, + "header": { + "excess_mana": 1331581648, + "mana_used": 83908793, + "proving_cost_per_mana_numerator": 1571081596, + "fee_asset_price_numerator": 5007899122 + }, + "oracle_input": { + "proving_cost_modifier": -86336724, + "fee_asset_price_modifier": -263004979 + }, + "outputs": { + "fee_asset_price_at_execution": 10541228939, + "mana_base_fee_components_in_wei": { + "data_cost": 19, + "gas_cost": 31439866, + "proving_cost": 5505861025, + "congestion_cost": 20759773951, + "congestion_multiplier": 4749078168 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 200, + "gas_cost": 331414825, + "proving_cost": 58038541570, + "congestion_cost": 218833529939, + "congestion_multiplier": 4749078168 + } + } + }, + { + "l1_block_number": 20973932, + "l1_fees": { + "blob_fee": 4455, + "base_fee": 9788598711 + }, + "parent_header": { + "excess_mana": 1331581648, + "mana_used": 83908793, + "proving_cost_per_mana_numerator": 1571081596, + "fee_asset_price_numerator": 5007899122 + }, + "header": { + "excess_mana": 1315490441, + "mana_used": 98745137, + "proving_cost_per_mana_numerator": 1657954574, + "fee_asset_price_numerator": 4495793528 + }, + "oracle_input": { + "proving_cost_modifier": 86872978, + "fee_asset_price_modifier": -512105594 + }, + "outputs": { + "fee_asset_price_at_execution": 10513541408, + "mana_base_fee_components_in_wei": { + "data_cost": 17, + "gas_cost": 32424733, + "proving_cost": 5501109496, + "congestion_cost": 20255529924, + "congestion_multiplier": 4660505027 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 178, + "gas_cost": 340898773, + "proving_cost": 57836142476, + "congestion_cost": 212957352596, + "congestion_multiplier": 4660505027 + } + } + }, + { + "l1_block_number": 20973935, + "l1_fees": { + "blob_fee": 5421, + "base_fee": 9503524710 + }, + "parent_header": { + "excess_mana": 1315490441, + "mana_used": 98745137, + "proving_cost_per_mana_numerator": 1657954574, + "fee_asset_price_numerator": 4495793528 + }, + "header": { + "excess_mana": 1314235578, + "mana_used": 115661879, + "proving_cost_per_mana_numerator": 1655074242, + "fee_asset_price_numerator": 4636831107 + }, + "oracle_input": { + "proving_cost_modifier": -2880332, + "fee_asset_price_modifier": 141037579 + }, + "outputs": { + "fee_asset_price_at_execution": 10459838599, + "mana_base_fee_components_in_wei": { + "data_cost": 21, + "gas_cost": 31480425, + "proving_cost": 5505890550, + "congestion_cost": 20231712676, + "congestion_multiplier": 4653667542 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 219, + "gas_cost": 329280164, + "proving_cost": 57590726496, + "congestion_cost": 211620449172, + "congestion_multiplier": 4653667542 + } + } + }, + { + "l1_block_number": 20973938, + "l1_fees": { + "blob_fee": 4455, + "base_fee": 9905469541 + }, + "parent_header": { + "excess_mana": 1314235578, + "mana_used": 115661879, + "proving_cost_per_mana_numerator": 1655074242, + "fee_asset_price_numerator": 4636831107 + }, + "header": { + "excess_mana": 1329897457, + "mana_used": 99047538, + "proving_cost_per_mana_numerator": 1660322455, + "fee_asset_price_numerator": 3636831107 + }, + "oracle_input": { + "proving_cost_modifier": 5248213, + "fee_asset_price_modifier": -1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10474601310, + "mana_base_fee_components_in_wei": { + "data_cost": 17, + "gas_cost": 32811867, + "proving_cost": 5505731965, + "congestion_cost": 20712654750, + "congestion_multiplier": 4739729307 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 178, + "gas_cost": 343691225, + "proving_cost": 57670347253, + "congestion_cost": 216956800577, + "congestion_multiplier": 4739729307 + } + } + }, + { + "l1_block_number": 20973941, + "l1_fees": { + "blob_fee": 5864, + "base_fee": 9492348783 + }, + "parent_header": { + "excess_mana": 1329897457, + "mana_used": 99047538, + "proving_cost_per_mana_numerator": 1660322455, + "fee_asset_price_numerator": 3636831107 + }, + "header": { + "excess_mana": 1328944995, + "mana_used": 94579490, + "proving_cost_per_mana_numerator": 1590454455, + "fee_asset_price_numerator": 3398858887 + }, + "oracle_input": { + "proving_cost_modifier": -69868000, + "fee_asset_price_modifier": -237972220 + }, + "outputs": { + "fee_asset_price_at_execution": 10370377286, + "mana_base_fee_components_in_wei": { + "data_cost": 23, + "gas_cost": 31443405, + "proving_cost": 5506020925, + "congestion_cost": 20679385896, + "congestion_multiplier": 4734450387 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 238, + "gas_cost": 326079973, + "proving_cost": 57099514336, + "congestion_cost": 214453033784, + "congestion_multiplier": 4734450387 + } + } + }, + { + "l1_block_number": 20973944, + "l1_fees": { + "blob_fee": 5421, + "base_fee": 9491302205 + }, + "parent_header": { + "excess_mana": 1328944995, + "mana_used": 94579490, + "proving_cost_per_mana_numerator": 1590454455, + "fee_asset_price_numerator": 3398858887 + }, + "header": { + "excess_mana": 1323524485, + "mana_used": 99099030, + "proving_cost_per_mana_numerator": 1570502674, + "fee_asset_price_numerator": 2562088416 + }, + "oracle_input": { + "proving_cost_modifier": -19951781, + "fee_asset_price_modifier": -836770471 + }, + "outputs": { + "fee_asset_price_at_execution": 10345728010, + "mana_base_fee_components_in_wei": { + "data_cost": 21, + "gas_cost": 31439938, + "proving_cost": 5502175322, + "congestion_cost": 20499385874, + "congestion_multiplier": 4704519529 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 217, + "gas_cost": 325269047, + "proving_cost": 56924009344, + "congestion_cost": 212081070624, + "congestion_multiplier": 4704519529 + } + } + }, + { + "l1_block_number": 20973947, + "l1_fees": { + "blob_fee": 6343, + "base_fee": 9257844367 + }, + "parent_header": { + "excess_mana": 1323524485, + "mana_used": 99099030, + "proving_cost_per_mana_numerator": 1570502674, + "fee_asset_price_numerator": 2562088416 + }, + "header": { + "excess_mana": 1322623515, + "mana_used": 93079232, + "proving_cost_per_mana_numerator": 1555242058, + "fee_asset_price_numerator": 2926917934 + }, + "oracle_input": { + "proving_cost_modifier": -15260616, + "fee_asset_price_modifier": 364829518 + }, + "outputs": { + "fee_asset_price_at_execution": 10259519201, + "mana_base_fee_components_in_wei": { + "data_cost": 24, + "gas_cost": 30666609, + "proving_cost": 5501077649, + "congestion_cost": 20465036161, + "congestion_multiplier": 4699562944 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 246, + "gas_cost": 314624663, + "proving_cost": 56438411766, + "congestion_cost": 209961431442, + "congestion_multiplier": 4699562944 + } + } + }, + { + "l1_block_number": 20973950, + "l1_fees": { + "blob_fee": 5638, + "base_fee": 9626673028 + }, + "parent_header": { + "excess_mana": 1322623515, + "mana_used": 93079232, + "proving_cost_per_mana_numerator": 1555242058, + "fee_asset_price_numerator": 2926917934 + }, + "header": { + "excess_mana": 1315702747, + "mana_used": 96637310, + "proving_cost_per_mana_numerator": 1584358417, + "fee_asset_price_numerator": 3926917934 + }, + "oracle_input": { + "proving_cost_modifier": 29116359, + "fee_asset_price_modifier": 1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10297017316, + "mana_base_fee_components_in_wei": { + "data_cost": 22, + "gas_cost": 31888354, + "proving_cost": 5500238215, + "congestion_cost": 20256782314, + "congestion_multiplier": 4661662831 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 226, + "gas_cost": 328354933, + "proving_cost": 56636048141, + "congestion_cost": 208584438253, + "congestion_multiplier": 4661662831 + } + } + }, + { + "l1_block_number": 20973953, + "l1_fees": { + "blob_fee": 6099, + "base_fee": 9541396841 + }, + "parent_header": { + "excess_mana": 1315702747, + "mana_used": 96637310, + "proving_cost_per_mana_numerator": 1584358417, + "fee_asset_price_numerator": 3926917934 + }, + "header": { + "excess_mana": 1312340057, + "mana_used": 125044278, + "proving_cost_per_mana_numerator": 1579456904, + "fee_asset_price_numerator": 3734805086 + }, + "oracle_input": { + "proving_cost_modifier": -4901513, + "fee_asset_price_modifier": -192112848 + }, + "outputs": { + "fee_asset_price_at_execution": 10400504060, + "mana_base_fee_components_in_wei": { + "data_cost": 23, + "gas_cost": 31605877, + "proving_cost": 5501839917, + "congestion_cost": 20160325534, + "congestion_multiplier": 4643358262 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 239, + "gas_cost": 328717052, + "proving_cost": 57221908394, + "congestion_cost": 209677547567, + "congestion_multiplier": 4643358262 + } + } + }, + { + "l1_block_number": 20973956, + "l1_fees": { + "blob_fee": 6861, + "base_fee": 9340810233 + }, + "parent_header": { + "excess_mana": 1312340057, + "mana_used": 125044278, + "proving_cost_per_mana_numerator": 1579456904, + "fee_asset_price_numerator": 3734805086 + }, + "header": { + "excess_mana": 1337384335, + "mana_used": 92840403, + "proving_cost_per_mana_numerator": 1533184551, + "fee_asset_price_numerator": 4050526531 + }, + "oracle_input": { + "proving_cost_modifier": -46272353, + "fee_asset_price_modifier": 315721445 + }, + "outputs": { + "fee_asset_price_at_execution": 10380542536, + "mana_base_fee_components_in_wei": { + "data_cost": 26, + "gas_cost": 30941433, + "proving_cost": 5501570250, + "congestion_cost": 20920805967, + "congestion_multiplier": 4781430039 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 269, + "gas_cost": 321188861, + "proving_cost": 57109283994, + "congestion_cost": 217169316227, + "congestion_multiplier": 4781430039 + } + } + }, + { + "l1_block_number": 20973959, + "l1_fees": { + "blob_fee": 7422, + "base_fee": 9311121822 + }, + "parent_header": { + "excess_mana": 1337384335, + "mana_used": 92840403, + "proving_cost_per_mana_numerator": 1533184551, + "fee_asset_price_numerator": 4050526531 + }, + "header": { + "excess_mana": 1330224738, + "mana_used": 92611181, + "proving_cost_per_mana_numerator": 1542731920, + "fee_asset_price_numerator": 3926603946 + }, + "oracle_input": { + "proving_cost_modifier": 9547369, + "fee_asset_price_modifier": -123922585 + }, + "outputs": { + "fee_asset_price_at_execution": 10413367926, + "mana_base_fee_components_in_wei": { + "data_cost": 29, + "gas_cost": 30843091, + "proving_cost": 5499025133, + "congestion_cost": 20690248623, + "congestion_multiplier": 4741544586 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 301, + "gas_cost": 321180454, + "proving_cost": 57263371944, + "congestion_cost": 215455171391, + "congestion_multiplier": 4741544586 + } + } + }, + { + "l1_block_number": 20973962, + "l1_fees": { + "blob_fee": 8684, + "base_fee": 9375527733 + }, + "parent_header": { + "excess_mana": 1330224738, + "mana_used": 92611181, + "proving_cost_per_mana_numerator": 1542731920, + "fee_asset_price_numerator": 3926603946 + }, + "header": { + "excess_mana": 1322835919, + "mana_used": 103198759, + "proving_cost_per_mana_numerator": 1476736516, + "fee_asset_price_numerator": 2927316841 + }, + "oracle_input": { + "proving_cost_modifier": -65995404, + "fee_asset_price_modifier": -999287105 + }, + "outputs": { + "fee_asset_price_at_execution": 10400471404, + "mana_base_fee_components_in_wei": { + "data_cost": 34, + "gas_cost": 31056435, + "proving_cost": 5499550171, + "congestion_cost": 20467287386, + "congestion_multiplier": 4700730990 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 353, + "gas_cost": 323001564, + "proving_cost": 57197914288, + "congestion_cost": 212869437175, + "congestion_multiplier": 4700730990 + } + } + }, + { + "l1_block_number": 20973965, + "l1_fees": { + "blob_fee": 8350, + "base_fee": 8792547319 + }, + "parent_header": { + "excess_mana": 1322835919, + "mana_used": 103198759, + "proving_cost_per_mana_numerator": 1476736516, + "fee_asset_price_numerator": 2927316841 + }, + "header": { + "excess_mana": 1326034678, + "mana_used": 92233494, + "proving_cost_per_mana_numerator": 1472519754, + "fee_asset_price_numerator": 3313885765 + }, + "oracle_input": { + "proving_cost_modifier": -4216762, + "fee_asset_price_modifier": 386568924 + }, + "outputs": { + "fee_asset_price_at_execution": 10297058391, + "mana_base_fee_components_in_wei": { + "data_cost": 32, + "gas_cost": 29125312, + "proving_cost": 5495921918, + "congestion_cost": 20544096300, + "congestion_multiplier": 4718356663 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 329, + "gas_cost": 299905038, + "proving_cost": 56591828902, + "congestion_cost": 211543759191, + "congestion_multiplier": 4718356663 + } + } + }, + { + "l1_block_number": 20973968, + "l1_fees": { + "blob_fee": 6099, + "base_fee": 9043161445 + }, + "parent_header": { + "excess_mana": 1326034678, + "mana_used": 92233494, + "proving_cost_per_mana_numerator": 1472519754, + "fee_asset_price_numerator": 3313885765 + }, + "header": { + "excess_mana": 1318268172, + "mana_used": 101693104, + "proving_cost_per_mana_numerator": 1551966076, + "fee_asset_price_numerator": 3766445324 + }, + "oracle_input": { + "proving_cost_modifier": 79446322, + "fee_asset_price_modifier": 452559559 + }, + "outputs": { + "fee_asset_price_at_execution": 10336940656, + "mana_base_fee_components_in_wei": { + "data_cost": 23, + "gas_cost": 29955472, + "proving_cost": 5495690172, + "congestion_cost": 20310483450, + "congestion_multiplier": 4675676052 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 237, + "gas_cost": 309647936, + "proving_cost": 56808623171, + "congestion_cost": 209948262117, + "congestion_multiplier": 4675676052 + } + } + }, + { + "l1_block_number": 20973971, + "l1_fees": { + "blob_fee": 8684, + "base_fee": 8911568646 + }, + "parent_header": { + "excess_mana": 1318268172, + "mana_used": 101693104, + "proving_cost_per_mana_numerator": 1551966076, + "fee_asset_price_numerator": 3766445324 + }, + "header": { + "excess_mana": 1319961276, + "mana_used": 102102019, + "proving_cost_per_mana_numerator": 1468317618, + "fee_asset_price_numerator": 4300917324 + }, + "oracle_input": { + "proving_cost_modifier": -83648458, + "fee_asset_price_modifier": 534472000 + }, + "outputs": { + "fee_asset_price_at_execution": 10383827484, + "mana_base_fee_components_in_wei": { + "data_cost": 34, + "gas_cost": 29519571, + "proving_cost": 5500058031, + "congestion_cost": 20376202882, + "congestion_multiplier": 4684947427 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 353, + "gas_cost": 306526132, + "proving_cost": 57111653745, + "congestion_cost": 211582975505, + "congestion_multiplier": 4684947427 + } + } + }, + { + "l1_block_number": 20973974, + "l1_fees": { + "blob_fee": 9770, + "base_fee": 9868061066 + }, + "parent_header": { + "excess_mana": 1319961276, + "mana_used": 102102019, + "proving_cost_per_mana_numerator": 1468317618, + "fee_asset_price_numerator": 4300917324 + }, + "header": { + "excess_mana": 1322063295, + "mana_used": 102474076, + "proving_cost_per_mana_numerator": 1511499768, + "fee_asset_price_numerator": 4227336050 + }, + "oracle_input": { + "proving_cost_modifier": 43182150, + "fee_asset_price_modifier": -73581274 + }, + "outputs": { + "fee_asset_price_at_execution": 10439474711, + "mana_base_fee_components_in_wei": { + "data_cost": 38, + "gas_cost": 32687952, + "proving_cost": 5495459241, + "congestion_cost": 20434705522, + "congestion_multiplier": 4696483590 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 396, + "gas_cost": 341245048, + "proving_cost": 57369707771, + "congestion_cost": 213327591523, + "congestion_multiplier": 4696483590 + } + } + }, + { + "l1_block_number": 20973977, + "l1_fees": { + "blob_fee": 11889, + "base_fee": 10572529939 + }, + "parent_header": { + "excess_mana": 1322063295, + "mana_used": 102474076, + "proving_cost_per_mana_numerator": 1511499768, + "fee_asset_price_numerator": 4227336050 + }, + "header": { + "excess_mana": 1324537371, + "mana_used": 105245190, + "proving_cost_per_mana_numerator": 1609749354, + "fee_asset_price_numerator": 4807977124 + }, + "oracle_input": { + "proving_cost_modifier": 98249586, + "fee_asset_price_modifier": 580641074 + }, + "outputs": { + "fee_asset_price_at_execution": 10431796038, + "mana_base_fee_components_in_wei": { + "data_cost": 46, + "gas_cost": 35021505, + "proving_cost": 5497832811, + "congestion_cost": 20527432179, + "congestion_multiplier": 4710098050 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 479, + "gas_cost": 365337197, + "proving_cost": 57352270535, + "congestion_cost": 214137985675, + "congestion_multiplier": 4710098050 + } + } + }, + { + "l1_block_number": 20973980, + "l1_fees": { + "blob_fee": 13375, + "base_fee": 9920545956 + }, + "parent_header": { + "excess_mana": 1324537371, + "mana_used": 105245190, + "proving_cost_per_mana_numerator": 1609749354, + "fee_asset_price_numerator": 4807977124 + }, + "header": { + "excess_mana": 1329782561, + "mana_used": 48176168, + "proving_cost_per_mana_numerator": 1671284806, + "fee_asset_price_numerator": 4979384835 + }, + "oracle_input": { + "proving_cost_modifier": 61535452, + "fee_asset_price_modifier": 171407711 + }, + "outputs": { + "fee_asset_price_at_execution": 10492543523, + "mana_base_fee_components_in_wei": { + "data_cost": 52, + "gas_cost": 32861808, + "proving_cost": 5503237063, + "congestion_cost": 20699984279, + "congestion_multiplier": 4739092196 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 545, + "gas_cost": 344803950, + "proving_cost": 57742954400, + "congestion_cost": 217195485972, + "congestion_multiplier": 4739092196 + } + } + }, + { + "l1_block_number": 20973983, + "l1_fees": { + "blob_fee": 12860, + "base_fee": 9493896905 + }, + "parent_header": { + "excess_mana": 1329782561, + "mana_used": 48176168, + "proving_cost_per_mana_numerator": 1671284806, + "fee_asset_price_numerator": 4979384835 + }, + "header": { + "excess_mana": 1277958729, + "mana_used": 143539543, + "proving_cost_per_mana_numerator": 1636083342, + "fee_asset_price_numerator": 5620347702 + }, + "oracle_input": { + "proving_cost_modifier": -35201464, + "fee_asset_price_modifier": 640962867 + }, + "outputs": { + "fee_asset_price_at_execution": 10510543974, + "mana_base_fee_components_in_wei": { + "data_cost": 50, + "gas_cost": 31448533, + "proving_cost": 5506624547, + "congestion_cost": 19163287882, + "congestion_multiplier": 4460280757 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 525, + "gas_cost": 330541189, + "proving_cost": 57877619449, + "congestion_cost": 201416579970, + "congestion_multiplier": 4460280757 + } + } + }, + { + "l1_block_number": 20973986, + "l1_fees": { + "blob_fee": 15047, + "base_fee": 10231684676 + }, + "parent_header": { + "excess_mana": 1277958729, + "mana_used": 143539543, + "proving_cost_per_mana_numerator": 1636083342, + "fee_asset_price_numerator": 5620347702 + }, + "header": { + "excess_mana": 1321498272, + "mana_used": 106821640, + "proving_cost_per_mana_numerator": 1535185490, + "fee_asset_price_numerator": 5430436092 + }, + "oracle_input": { + "proving_cost_modifier": -100897852, + "fee_asset_price_modifier": -189911610 + }, + "outputs": { + "fee_asset_price_at_execution": 10578129024, + "mana_base_fee_components_in_wei": { + "data_cost": 59, + "gas_cost": 33892455, + "proving_cost": 5504686476, + "congestion_cost": 20456076199, + "congestion_multiplier": 4693379879 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 624, + "gas_cost": 358518761, + "proving_cost": 58229283779, + "congestion_cost": 216387013357, + "congestion_multiplier": 4693379879 + } + } + }, + { + "l1_block_number": 20973989, + "l1_fees": { + "blob_fee": 13910, + "base_fee": 10687936636 + }, + "parent_header": { + "excess_mana": 1321498272, + "mana_used": 106821640, + "proving_cost_per_mana_numerator": 1535185490, + "fee_asset_price_numerator": 5430436092 + }, + "header": { + "excess_mana": 1328319912, + "mana_used": 97504621, + "proving_cost_per_mana_numerator": 1734574868, + "fee_asset_price_numerator": 5466526012 + }, + "oracle_input": { + "proving_cost_modifier": 199389378, + "fee_asset_price_modifier": 36089920 + }, + "outputs": { + "fee_asset_price_at_execution": 10558058993, + "mana_base_fee_components_in_wei": { + "data_cost": 54, + "gas_cost": 35403790, + "proving_cost": 5499135166, + "congestion_cost": 20649304863, + "congestion_multiplier": 4730989126 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 570, + "gas_cost": 373795303, + "proving_cost": 58060193493, + "congestion_cost": 218016578907, + "congestion_multiplier": 4730989126 + } + } + }, + { + "l1_block_number": 20973992, + "l1_fees": { + "blob_fee": 12860, + "base_fee": 9937916645 + }, + "parent_header": { + "excess_mana": 1328319912, + "mana_used": 97504621, + "proving_cost_per_mana_numerator": 1734574868, + "fee_asset_price_numerator": 5466526012 + }, + "header": { + "excess_mana": 1325824533, + "mana_used": 99530321, + "proving_cost_per_mana_numerator": 1721795670, + "fee_asset_price_numerator": 6329274402 + }, + "oracle_input": { + "proving_cost_modifier": -12779198, + "fee_asset_price_modifier": 862748390 + }, + "outputs": { + "fee_asset_price_at_execution": 10561870075, + "mana_base_fee_components_in_wei": { + "data_cost": 50, + "gas_cost": 32919348, + "proving_cost": 5510110796, + "congestion_cost": 20604533572, + "congestion_multiplier": 4717196705 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 528, + "gas_cost": 347689876, + "proving_cost": 58197074326, + "congestion_cost": 217622406543, + "congestion_multiplier": 4717196705 + } + } + }, + { + "l1_block_number": 20973995, + "l1_fees": { + "blob_fee": 16276, + "base_fee": 9399164298 + }, + "parent_header": { + "excess_mana": 1325824533, + "mana_used": 99530321, + "proving_cost_per_mana_numerator": 1721795670, + "fee_asset_price_numerator": 6329274402 + }, + "header": { + "excess_mana": 1325354854, + "mana_used": 96817789, + "proving_cost_per_mana_numerator": 1836689389, + "fee_asset_price_numerator": 7008968044 + }, + "oracle_input": { + "proving_cost_modifier": 114893719, + "fee_asset_price_modifier": 679693642 + }, + "outputs": { + "fee_asset_price_at_execution": 10653386651, + "mana_base_fee_components_in_wei": { + "data_cost": 63, + "gas_cost": 31134731, + "proving_cost": 5509406693, + "congestion_cost": 20580924235, + "congestion_multiplier": 4714605203 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 671, + "gas_cost": 331690327, + "proving_cost": 58693839718, + "congestion_cost": 219256543510, + "congestion_multiplier": 4714605203 + } + } + }, + { + "l1_block_number": 20973998, + "l1_fees": { + "blob_fee": 16928, + "base_fee": 9340485439 + }, + "parent_header": { + "excess_mana": 1325354854, + "mana_used": 96817789, + "proving_cost_per_mana_numerator": 1836689389, + "fee_asset_price_numerator": 7008968044 + }, + "header": { + "excess_mana": 1322172643, + "mana_used": 101220698, + "proving_cost_per_mana_numerator": 1881114566, + "fee_asset_price_numerator": 7096178621 + }, + "oracle_input": { + "proving_cost_modifier": 44425177, + "fee_asset_price_modifier": 87210577 + }, + "outputs": { + "fee_asset_price_at_execution": 10726043685, + "mana_base_fee_components_in_wei": { + "data_cost": 66, + "gas_cost": 30940358, + "proving_cost": 5515740293, + "congestion_cost": 20506547210, + "congestion_multiplier": 4697084483 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 707, + "gas_cost": 331867631, + "proving_cost": 59162071337, + "congestion_cost": 219954121202, + "congestion_multiplier": 4697084483 + } + } + }, + { + "l1_block_number": 20974001, + "l1_fees": { + "blob_fee": 16276, + "base_fee": 9254721351 + }, + "parent_header": { + "excess_mana": 1322172643, + "mana_used": 101220698, + "proving_cost_per_mana_numerator": 1881114566, + "fee_asset_price_numerator": 7096178621 + }, + "header": { + "excess_mana": 1323393341, + "mana_used": 106226548, + "proving_cost_per_mana_numerator": 1946421425, + "fee_asset_price_numerator": 6322662659 + }, + "oracle_input": { + "proving_cost_modifier": 65306859, + "fee_asset_price_modifier": -773515962 + }, + "outputs": { + "fee_asset_price_at_execution": 10735402010, + "mana_base_fee_components_in_wei": { + "data_cost": 63, + "gas_cost": 30656264, + "proving_cost": 5518191215, + "congestion_cost": 20551808930, + "congestion_multiplier": 4703797730 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 676, + "gas_cost": 329107318, + "proving_cost": 59240001061, + "congestion_cost": 220631930896, + "congestion_multiplier": 4703797730 + } + } + }, + { + "l1_block_number": 20974004, + "l1_fees": { + "blob_fee": 15047, + "base_fee": 8967315970 + }, + "parent_header": { + "excess_mana": 1323393341, + "mana_used": 106226548, + "proving_cost_per_mana_numerator": 1946421425, + "fee_asset_price_numerator": 6322662659 + }, + "header": { + "excess_mana": 1329619889, + "mana_used": 96207687, + "proving_cost_per_mana_numerator": 1796145148, + "fee_asset_price_numerator": 6222816783 + }, + "oracle_input": { + "proving_cost_modifier": -150276277, + "fee_asset_price_modifier": -99845876 + }, + "outputs": { + "fee_asset_price_at_execution": 10652682299, + "mana_base_fee_components_in_wei": { + "data_cost": 59, + "gas_cost": 29704234, + "proving_cost": 5521796150, + "congestion_cost": 20752565150, + "congestion_multiplier": 4738190308 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 628, + "gas_cost": 316429767, + "proving_cost": 58821940105, + "congestion_cost": 221070483432, + "congestion_multiplier": 4738190308 + } + } + }, + { + "l1_block_number": 20974007, + "l1_fees": { + "blob_fee": 19806, + "base_fee": 8078456063 + }, + "parent_header": { + "excess_mana": 1329619889, + "mana_used": 96207687, + "proving_cost_per_mana_numerator": 1796145148, + "fee_asset_price_numerator": 6222816783 + }, + "header": { + "excess_mana": 1325827576, + "mana_used": 95453902, + "proving_cost_per_mana_numerator": 1888136398, + "fee_asset_price_numerator": 5673515616 + }, + "oracle_input": { + "proving_cost_modifier": 91991250, + "fee_asset_price_modifier": -549301167 + }, + "outputs": { + "fee_asset_price_at_execution": 10642051344, + "mana_base_fee_components_in_wei": { + "data_cost": 77, + "gas_cost": 26759885, + "proving_cost": 5513504432, + "congestion_cost": 20594345598, + "congestion_multiplier": 4717213500 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 819, + "gas_cost": 284780070, + "proving_cost": 58674997250, + "congestion_cost": 219166083249, + "congestion_multiplier": 4717213500 + } + } + }, + { + "l1_block_number": 20974010, + "l1_fees": { + "blob_fee": 25067, + "base_fee": 9018975363 + }, + "parent_header": { + "excess_mana": 1325827576, + "mana_used": 95453902, + "proving_cost_per_mana_numerator": 1888136398, + "fee_asset_price_numerator": 5673515616 + }, + "header": { + "excess_mana": 1321281478, + "mana_used": 104937181, + "proving_cost_per_mana_numerator": 2039920330, + "fee_asset_price_numerator": 5051607601 + }, + "oracle_input": { + "proving_cost_modifier": 151783932, + "fee_asset_price_modifier": -621908015 + }, + "outputs": { + "fee_asset_price_at_execution": 10583754690, + "mana_base_fee_components_in_wei": { + "data_cost": 98, + "gas_cost": 29875355, + "proving_cost": 5518578707, + "congestion_cost": 20485944518, + "congestion_multiplier": 4692189559 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1037, + "gas_cost": 316193428, + "proving_cost": 58407283272, + "congestion_cost": 216818211371, + "congestion_multiplier": 4692189559 + } + } + }, + { + "l1_block_number": 20974013, + "l1_fees": { + "blob_fee": 28201, + "base_fee": 9158435578 + }, + "parent_header": { + "excess_mana": 1321281478, + "mana_used": 104937181, + "proving_cost_per_mana_numerator": 2039920330, + "fee_asset_price_numerator": 5051607601 + }, + "header": { + "excess_mana": 1326218659, + "mana_used": 101453540, + "proving_cost_per_mana_numerator": 1852905038, + "fee_asset_price_numerator": 4399385648 + }, + "oracle_input": { + "proving_cost_modifier": -187015292, + "fee_asset_price_modifier": -652221953 + }, + "outputs": { + "fee_asset_price_at_execution": 10518137721, + "mana_base_fee_components_in_wei": { + "data_cost": 110, + "gas_cost": 30337317, + "proving_cost": 5526961383, + "congestion_cost": 20669664012, + "congestion_multiplier": 4719372436 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1156, + "gas_cost": 319092078, + "proving_cost": 58133341005, + "congestion_cost": 217406372725, + "congestion_multiplier": 4719372436 + } + } + }, + { + "l1_block_number": 20974016, + "l1_fees": { + "blob_fee": 37121, + "base_fee": 9951217330 + }, + "parent_header": { + "excess_mana": 1326218659, + "mana_used": 101453540, + "proving_cost_per_mana_numerator": 1852905038, + "fee_asset_price_numerator": 4399385648 + }, + "header": { + "excess_mana": 1327672199, + "mana_used": 92561346, + "proving_cost_per_mana_numerator": 1919364892, + "fee_asset_price_numerator": 4334899474 + }, + "oracle_input": { + "proving_cost_modifier": 66459854, + "fee_asset_price_modifier": -64486174 + }, + "outputs": { + "fee_asset_price_at_execution": 10449759350, + "mana_base_fee_components_in_wei": { + "data_cost": 145, + "gas_cost": 32963407, + "proving_cost": 5516634779, + "congestion_cost": 20685601821, + "congestion_multiplier": 4727405226 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1515, + "gas_cost": 344459670, + "proving_cost": 57647505862, + "congestion_cost": 216159561039, + "congestion_multiplier": 4727405226 + } + } + }, + { + "l1_block_number": 20974019, + "l1_fees": { + "blob_fee": 32996, + "base_fee": 9879258021 + }, + "parent_header": { + "excess_mana": 1327672199, + "mana_used": 92561346, + "proving_cost_per_mana_numerator": 1919364892, + "fee_asset_price_numerator": 4334899474 + }, + "header": { + "excess_mana": 1320233545, + "mana_used": 103870747, + "proving_cost_per_mana_numerator": 1888407636, + "fee_asset_price_numerator": 4717096533 + }, + "oracle_input": { + "proving_cost_modifier": -30957256, + "fee_asset_price_modifier": 382197059 + }, + "outputs": { + "fee_asset_price_at_execution": 10443022872, + "mana_base_fee_components_in_wei": { + "data_cost": 129, + "gas_cost": 32725042, + "proving_cost": 5520302345, + "congestion_cost": 20470903183, + "congestion_multiplier": 4686440077 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1347, + "gas_cost": 341748362, + "proving_cost": 57648643649, + "congestion_cost": 213778110150, + "congestion_multiplier": 4686440077 + } + } + }, + { + "l1_block_number": 20974022, + "l1_fees": { + "blob_fee": 35692, + "base_fee": 9794908709 + }, + "parent_header": { + "excess_mana": 1320233545, + "mana_used": 103870747, + "proving_cost_per_mana_numerator": 1888407636, + "fee_asset_price_numerator": 4717096533 + }, + "header": { + "excess_mana": 1324104292, + "mana_used": 102289492, + "proving_cost_per_mana_numerator": 1853045549, + "fee_asset_price_numerator": 4428560011 + }, + "oracle_input": { + "proving_cost_modifier": -35362087, + "fee_asset_price_modifier": -288536522 + }, + "outputs": { + "fee_asset_price_at_execution": 10483012169, + "mana_base_fee_components_in_wei": { + "data_cost": 140, + "gas_cost": 32445635, + "proving_cost": 5518593675, + "congestion_cost": 20581655781, + "congestion_multiplier": 4707712036 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1467, + "gas_cost": 340127986, + "proving_cost": 57851484650, + "congestion_cost": 215757748010, + "congestion_multiplier": 4707712036 + } + } + }, + { + "l1_block_number": 20974025, + "l1_fees": { + "blob_fee": 41761, + "base_fee": 10075139545 + }, + "parent_header": { + "excess_mana": 1324104292, + "mana_used": 102289492, + "proving_cost_per_mana_numerator": 1853045549, + "fee_asset_price_numerator": 4428560011 + }, + "header": { + "excess_mana": 1326393784, + "mana_used": 89592734, + "proving_cost_per_mana_numerator": 1892499027, + "fee_asset_price_numerator": 5175900812 + }, + "oracle_input": { + "proving_cost_modifier": 39453478, + "fee_asset_price_modifier": 747340801 + }, + "outputs": { + "fee_asset_price_at_execution": 10452808445, + "mana_base_fee_components_in_wei": { + "data_cost": 164, + "gas_cost": 33373899, + "proving_cost": 5516642530, + "congestion_cost": 20647946045, + "congestion_multiplier": 4720339516 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1714, + "gas_cost": 348850973, + "proving_cost": 57664407625, + "congestion_cost": 215829024791, + "congestion_multiplier": 4720339516 + } + } + }, + { + "l1_block_number": 20974028, + "l1_fees": { + "blob_fee": 46981, + "base_fee": 9477608461 + }, + "parent_header": { + "excess_mana": 1326393784, + "mana_used": 89592734, + "proving_cost_per_mana_numerator": 1892499027, + "fee_asset_price_numerator": 5175900812 + }, + "header": { + "excess_mana": 1315986518, + "mana_used": 102069463, + "proving_cost_per_mana_numerator": 1945964437, + "fee_asset_price_numerator": 5637447585 + }, + "oracle_input": { + "proving_cost_modifier": 53465410, + "fee_asset_price_modifier": 461546773 + }, + "outputs": { + "fee_asset_price_at_execution": 10531219180, + "mana_base_fee_components_in_wei": { + "data_cost": 184, + "gas_cost": 31394578, + "proving_cost": 5518819467, + "congestion_cost": 20331604794, + "congestion_multiplier": 4663210816 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1937, + "gas_cost": 330623181, + "proving_cost": 58119897421, + "congestion_cost": 214116586366, + "congestion_multiplier": 4663210816 + } + } + }, + { + "l1_block_number": 20974031, + "l1_fees": { + "blob_fee": 59461, + "base_fee": 9019167943 + }, + "parent_header": { + "excess_mana": 1315986518, + "mana_used": 102069463, + "proving_cost_per_mana_numerator": 1945964437, + "fee_asset_price_numerator": 5637447585 + }, + "header": { + "excess_mana": 1318055981, + "mana_used": 97994787, + "proving_cost_per_mana_numerator": 1936088689, + "fee_asset_price_numerator": 5007018649 + }, + "oracle_input": { + "proving_cost_modifier": -9875748, + "fee_asset_price_modifier": -630428936 + }, + "outputs": { + "fee_asset_price_at_execution": 10579938026, + "mana_base_fee_components_in_wei": { + "data_cost": 233, + "gas_cost": 29875993, + "proving_cost": 5521770916, + "congestion_cost": 20399612901, + "congestion_multiplier": 4674515397 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 2465, + "gas_cost": 316086154, + "proving_cost": 58419994085, + "congestion_cost": 215826640246, + "congestion_multiplier": 4674515397 + } + } + }, + { + "l1_block_number": 20974034, + "l1_fees": { + "blob_fee": 72358, + "base_fee": 9324283056 + }, + "parent_header": { + "excess_mana": 1318055981, + "mana_used": 97994787, + "proving_cost_per_mana_numerator": 1936088689, + "fee_asset_price_numerator": 5007018649 + }, + "header": { + "excess_mana": 1316050768, + "mana_used": 99918209, + "proving_cost_per_mana_numerator": 1958868996, + "fee_asset_price_numerator": 5270966323 + }, + "oracle_input": { + "proving_cost_modifier": 22780307, + "fee_asset_price_modifier": 263947674 + }, + "outputs": { + "fee_asset_price_at_execution": 10513448839, + "mana_base_fee_components_in_wei": { + "data_cost": 284, + "gas_cost": 30886687, + "proving_cost": 5521225626, + "congestion_cost": 20340505260, + "congestion_multiplier": 4663561375 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 2985, + "gas_cost": 324725603, + "proving_cost": 58047123147, + "congestion_cost": 213848861410, + "congestion_multiplier": 4663561375 + } + } + }, + { + "l1_block_number": 20974037, + "l1_fees": { + "blob_fee": 75255, + "base_fee": 9492816563 + }, + "parent_header": { + "excess_mana": 1316050768, + "mana_used": 99918209, + "proving_cost_per_mana_numerator": 1958868996, + "fee_asset_price_numerator": 5270966323 + }, + "header": { + "excess_mana": 1315968977, + "mana_used": 99985093, + "proving_cost_per_mana_numerator": 1994790733, + "fee_asset_price_numerator": 4558441443 + }, + "oracle_input": { + "proving_cost_modifier": 35921737, + "fee_asset_price_modifier": -712524880 + }, + "outputs": { + "fee_asset_price_at_execution": 10541235498, + "mana_base_fee_components_in_wei": { + "data_cost": 295, + "gas_cost": 31444954, + "proving_cost": 5522483522, + "congestion_cost": 20344680423, + "congestion_multiplier": 4663115114 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 3109, + "gas_cost": 331468665, + "proving_cost": 58213799339, + "congestion_cost": 214458067470, + "congestion_multiplier": 4663115114 + } + } + }, + { + "l1_block_number": 20974040, + "l1_fees": { + "blob_fee": 66894, + "base_fee": 9282090683 + }, + "parent_header": { + "excess_mana": 1315968977, + "mana_used": 99985093, + "proving_cost_per_mana_numerator": 1994790733, + "fee_asset_price_numerator": 4558441443 + }, + "header": { + "excess_mana": 1315954070, + "mana_used": 110668432, + "proving_cost_per_mana_numerator": 1762277778, + "fee_asset_price_numerator": 5018819856 + }, + "oracle_input": { + "proving_cost_modifier": -232512955, + "fee_asset_price_modifier": 460378413 + }, + "outputs": { + "fee_asset_price_at_execution": 10466393523, + "mana_base_fee_components_in_wei": { + "data_cost": 263, + "gas_cost": 30746925, + "proving_cost": 5524467650, + "congestion_cost": 20348939634, + "congestion_multiplier": 4663033785 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 2752, + "gas_cost": 321809416, + "proving_cost": 57821252429, + "congestion_cost": 212980009985, + "congestion_multiplier": 4663033785 + } + } + }, + { + "l1_block_number": 20974043, + "l1_fees": { + "blob_fee": 52854, + "base_fee": 9331294615 + }, + "parent_header": { + "excess_mana": 1315954070, + "mana_used": 110668432, + "proving_cost_per_mana_numerator": 1762277778, + "fee_asset_price_numerator": 5018819856 + }, + "header": { + "excess_mana": 1326622502, + "mana_used": 94321207, + "proving_cost_per_mana_numerator": 1584325470, + "fee_asset_price_numerator": 4350620895 + }, + "oracle_input": { + "proving_cost_modifier": -177952308, + "fee_asset_price_modifier": -668198961 + }, + "outputs": { + "fee_asset_price_at_execution": 10514689627, + "mana_base_fee_components_in_wei": { + "data_cost": 207, + "gas_cost": 30909913, + "proving_cost": 5511637469, + "congestion_cost": 20627160897, + "congestion_multiplier": 4721602849 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 2176, + "gas_cost": 325008141, + "proving_cost": 57953157323, + "congestion_cost": 216888194718, + "congestion_multiplier": 4721602849 + } + } + }, + { + "l1_block_number": 20974046, + "l1_fees": { + "blob_fee": 54971, + "base_fee": 9208669518 + }, + "parent_header": { + "excess_mana": 1326622502, + "mana_used": 94321207, + "proving_cost_per_mana_numerator": 1584325470, + "fee_asset_price_numerator": 4350620895 + }, + "header": { + "excess_mana": 1320943709, + "mana_used": 92582756, + "proving_cost_per_mana_numerator": 1701387963, + "fee_asset_price_numerator": 4237511017 + }, + "oracle_input": { + "proving_cost_modifier": 117062493, + "fee_asset_price_modifier": -113109878 + }, + "outputs": { + "fee_asset_price_at_execution": 10444664793, + "mana_base_fee_components_in_wei": { + "data_cost": 216, + "gas_cost": 30503717, + "proving_cost": 5501838104, + "congestion_cost": 20416198881, + "congestion_multiplier": 4690335620 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 2256, + "gas_cost": 318601099, + "proving_cost": 57464854741, + "congestion_cost": 213240353659, + "congestion_multiplier": 4690335620 + } + } + }, + { + "l1_block_number": 20974049, + "l1_fees": { + "blob_fee": 41761, + "base_fee": 9312230602 + }, + "parent_header": { + "excess_mana": 1320943709, + "mana_used": 92582756, + "proving_cost_per_mana_numerator": 1701387963, + "fee_asset_price_numerator": 4237511017 + }, + "header": { + "excess_mana": 1313526465, + "mana_used": 110100940, + "proving_cost_per_mana_numerator": 1786169668, + "fee_asset_price_numerator": 4586868437 + }, + "oracle_input": { + "proving_cost_modifier": 84781705, + "fee_asset_price_modifier": 349357420 + }, + "outputs": { + "fee_asset_price_at_execution": 10432857524, + "mana_base_fee_components_in_wei": { + "data_cost": 164, + "gas_cost": 30846763, + "proving_cost": 5508282465, + "congestion_cost": 20216759715, + "congestion_multiplier": 4649808171 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1710, + "gas_cost": 321819883, + "proving_cost": 57467126159, + "congestion_cost": 210918573703, + "congestion_multiplier": 4649808171 + } + } + }, + { + "l1_block_number": 20974052, + "l1_fees": { + "blob_fee": 41761, + "base_fee": 9243837121 + }, + "parent_header": { + "excess_mana": 1313526465, + "mana_used": 110100940, + "proving_cost_per_mana_numerator": 1786169668, + "fee_asset_price_numerator": 4586868437 + }, + "header": { + "excess_mana": 1323627405, + "mana_used": 91251238, + "proving_cost_per_mana_numerator": 1733491217, + "fee_asset_price_numerator": 4656046491 + }, + "oracle_input": { + "proving_cost_modifier": -52678451, + "fee_asset_price_modifier": 69178054 + }, + "outputs": { + "fee_asset_price_at_execution": 10469369227, + "mana_base_fee_components_in_wei": { + "data_cost": 164, + "gas_cost": 30620210, + "proving_cost": 5512954461, + "congestion_cost": 20539421871, + "congestion_multiplier": 4705086065 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1716, + "gas_cost": 320574284, + "proving_cost": 57717155783, + "congestion_cost": 215034791276, + "congestion_multiplier": 4705086065 + } + } + }, + { + "l1_block_number": 20974055, + "l1_fees": { + "blob_fee": 35692, + "base_fee": 8867356451 + }, + "parent_header": { + "excess_mana": 1323627405, + "mana_used": 91251238, + "proving_cost_per_mana_numerator": 1733491217, + "fee_asset_price_numerator": 4656046491 + }, + "header": { + "excess_mana": 1314878643, + "mana_used": 117778673, + "proving_cost_per_mana_numerator": 1558279507, + "fee_asset_price_numerator": 4221180692 + }, + "oracle_input": { + "proving_cost_modifier": -175211710, + "fee_asset_price_modifier": -434865799 + }, + "outputs": { + "fee_asset_price_at_execution": 10476614239, + "mana_base_fee_components_in_wei": { + "data_cost": 140, + "gas_cost": 29373118, + "proving_cost": 5510051086, + "congestion_cost": 20258617713, + "congestion_multiplier": 4657170214 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1466, + "gas_cost": 307730826, + "proving_cost": 57726679665, + "congestion_cost": 212241722794, + "congestion_multiplier": 4657170214 + } + } + }, + { + "l1_block_number": 20974058, + "l1_fees": { + "blob_fee": 30505, + "base_fee": 8944349837 + }, + "parent_header": { + "excess_mana": 1314878643, + "mana_used": 117778673, + "proving_cost_per_mana_numerator": 1558279507, + "fee_asset_price_numerator": 4221180692 + }, + "header": { + "excess_mana": 1332657316, + "mana_used": 94983045, + "proving_cost_per_mana_numerator": 1526777300, + "fee_asset_price_numerator": 4367616093 + }, + "oracle_input": { + "proving_cost_modifier": -31502207, + "fee_asset_price_modifier": 146435401 + }, + "outputs": { + "fee_asset_price_at_execution": 10431153944, + "mana_base_fee_components_in_wei": { + "data_cost": 119, + "gas_cost": 29628158, + "proving_cost": 5500405284, + "congestion_cost": 20765601159, + "congestion_multiplier": 4755058795 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1241, + "gas_cost": 309055877, + "proving_cost": 57375574271, + "congestion_cost": 216609182429, + "congestion_multiplier": 4755058795 + } + } + }, + { + "l1_block_number": 20974061, + "l1_fees": { + "blob_fee": 32996, + "base_fee": 9186237001 + }, + "parent_header": { + "excess_mana": 1332657316, + "mana_used": 94983045, + "proving_cost_per_mana_numerator": 1526777300, + "fee_asset_price_numerator": 4367616093 + }, + "header": { + "excess_mana": 1327640361, + "mana_used": 106363982, + "proving_cost_per_mana_numerator": 1463686342, + "fee_asset_price_numerator": 4520398689 + }, + "oracle_input": { + "proving_cost_modifier": -63090958, + "fee_asset_price_modifier": 152782596 + }, + "outputs": { + "fee_asset_price_at_execution": 10446440035, + "mana_base_fee_components_in_wei": { + "data_cost": 129, + "gas_cost": 30429410, + "proving_cost": 5498672808, + "congestion_cost": 20608231336, + "congestion_multiplier": 4727229131 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1347, + "gas_cost": 317879006, + "proving_cost": 57441555760, + "congestion_cost": 215282652878, + "congestion_multiplier": 4727229131 + } + } + }, + { + "l1_block_number": 20974064, + "l1_fees": { + "blob_fee": 28201, + "base_fee": 8647342222 + }, + "parent_header": { + "excess_mana": 1327640361, + "mana_used": 106363982, + "proving_cost_per_mana_numerator": 1463686342, + "fee_asset_price_numerator": 4520398689 + }, + "header": { + "excess_mana": 1334004343, + "mana_used": 96516464, + "proving_cost_per_mana_numerator": 1472271650, + "fee_asset_price_numerator": 4708785624 + }, + "oracle_input": { + "proving_cost_modifier": 8585308, + "fee_asset_price_modifier": 188386935 + }, + "outputs": { + "fee_asset_price_at_execution": 10462412576, + "mana_base_fee_components_in_wei": { + "data_cost": 110, + "gas_cost": 28644321, + "proving_cost": 5495204737, + "congestion_cost": 20783807180, + "congestion_multiplier": 4762558779 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1150, + "gas_cost": 299688704, + "proving_cost": 57493099148, + "congestion_cost": 217448765617, + "congestion_multiplier": 4762558779 + } + } + }, + { + "l1_block_number": 20974067, + "l1_fees": { + "blob_fee": 26071, + "base_fee": 9137278849 + }, + "parent_header": { + "excess_mana": 1334004343, + "mana_used": 96516464, + "proving_cost_per_mana_numerator": 1472271650, + "fee_asset_price_numerator": 4708785624 + }, + "header": { + "excess_mana": 1330520807, + "mana_used": 90569854, + "proving_cost_per_mana_numerator": 1289735269, + "fee_asset_price_numerator": 5085567680 + }, + "oracle_input": { + "proving_cost_modifier": -182536381, + "fee_asset_price_modifier": 376782056 + }, + "outputs": { + "fee_asset_price_at_execution": 10482140971, + "mana_base_fee_components_in_wei": { + "data_cost": 102, + "gas_cost": 30267236, + "proving_cost": 5495676537, + "congestion_cost": 20684643182, + "congestion_multiplier": 4743187345 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 1069, + "gas_cost": 317265434, + "proving_cost": 57606456191, + "congestion_cost": 216819345768, + "congestion_multiplier": 4743187345 + } + } + }, + { + "l1_block_number": 20974070, + "l1_fees": { + "blob_fee": 22282, + "base_fee": 8823926412 + }, + "parent_header": { + "excess_mana": 1330520807, + "mana_used": 90569854, + "proving_cost_per_mana_numerator": 1289735269, + "fee_asset_price_numerator": 5085567680 + }, + "header": { + "excess_mana": 1321090661, + "mana_used": 106526420, + "proving_cost_per_mana_numerator": 1281893651, + "fee_asset_price_numerator": 5053281775 + }, + "oracle_input": { + "proving_cost_modifier": -7841618, + "fee_asset_price_modifier": -32285905 + }, + "outputs": { + "fee_asset_price_at_execution": 10521710296, + "mana_base_fee_components_in_wei": { + "data_cost": 87, + "gas_cost": 29229256, + "proving_cost": 5485654079, + "congestion_cost": 20356218469, + "congestion_multiplier": 4691142117 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 915, + "gas_cost": 307541763, + "proving_cost": 57718463003, + "congestion_cost": 214182233452, + "congestion_multiplier": 4691142117 + } + } + }, + { + "l1_block_number": 20974073, + "l1_fees": { + "blob_fee": 16276, + "base_fee": 8118906685 + }, + "parent_header": { + "excess_mana": 1321090661, + "mana_used": 106526420, + "proving_cost_per_mana_numerator": 1281893651, + "fee_asset_price_numerator": 5053281775 + }, + "header": { + "excess_mana": 1327617081, + "mana_used": 109708384, + "proving_cost_per_mana_numerator": 1333514174, + "fee_asset_price_numerator": 5729363449 + }, + "oracle_input": { + "proving_cost_modifier": 51620523, + "fee_asset_price_modifier": 676081674 + }, + "outputs": { + "fee_asset_price_at_execution": 10518313815, + "mana_base_fee_components_in_wei": { + "data_cost": 63, + "gas_cost": 26893878, + "proving_cost": 5485223931, + "congestion_cost": 20544216587, + "congestion_multiplier": 4727100375 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 662, + "gas_cost": 282878248, + "proving_cost": 57695306651, + "congestion_cost": 216090517145, + "congestion_multiplier": 4727100375 + } + } + }, + { + "l1_block_number": 20974076, + "l1_fees": { + "blob_fee": 15649, + "base_fee": 8773229158 + }, + "parent_header": { + "excess_mana": 1327617081, + "mana_used": 109708384, + "proving_cost_per_mana_numerator": 1333514174, + "fee_asset_price_numerator": 5729363449 + }, + "header": { + "excess_mana": 1337325465, + "mana_used": 102116789, + "proving_cost_per_mana_numerator": 1262796025, + "fee_asset_price_numerator": 5693645457 + }, + "oracle_input": { + "proving_cost_modifier": -70718149, + "fee_asset_price_modifier": -35717992 + }, + "outputs": { + "fee_asset_price_at_execution": 10589667138, + "mana_base_fee_components_in_wei": { + "data_cost": 61, + "gas_cost": 29061321, + "proving_cost": 5488056164, + "congestion_cost": 20860777103, + "congestion_multiplier": 4781100716 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 645, + "gas_cost": 307749715, + "proving_cost": 58116688011, + "congestion_cost": 220908685760, + "congestion_multiplier": 4781100716 + } + } + }, + { + "l1_block_number": 20974079, + "l1_fees": { + "blob_fee": 14467, + "base_fee": 8811930844 + }, + "parent_header": { + "excess_mana": 1337325465, + "mana_used": 102116789, + "proving_cost_per_mana_numerator": 1262796025, + "fee_asset_price_numerator": 5693645457 + }, + "header": { + "excess_mana": 1339442254, + "mana_used": 86520455, + "proving_cost_per_mana_numerator": 1345831705, + "fee_asset_price_numerator": 5664501917 + }, + "oracle_input": { + "proving_cost_modifier": 83035680, + "fee_asset_price_modifier": -29143540 + }, + "outputs": { + "fee_asset_price_at_execution": 10585885397, + "mana_base_fee_components_in_wei": { + "data_cost": 56, + "gas_cost": 29189520, + "proving_cost": 5484176484, + "congestion_cost": 20911957474, + "congestion_multiplier": 4792956471 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 592, + "gas_cost": 308996913, + "proving_cost": 58054863756, + "congestion_cost": 221371585246, + "congestion_multiplier": 4792956471 + } + } + }, + { + "l1_block_number": 20974082, + "l1_fees": { + "blob_fee": 10568, + "base_fee": 8983995122 + }, + "parent_header": { + "excess_mana": 1339442254, + "mana_used": 86520455, + "proving_cost_per_mana_numerator": 1345831705, + "fee_asset_price_numerator": 5664501917 + }, + "header": { + "excess_mana": 1325962709, + "mana_used": 95650619, + "proving_cost_per_mana_numerator": 1431637765, + "fee_asset_price_numerator": 5095534826 + }, + "oracle_input": { + "proving_cost_modifier": 85806060, + "fee_asset_price_modifier": -568967091 + }, + "outputs": { + "fee_asset_price_at_execution": 10582800745, + "mana_base_fee_components_in_wei": { + "data_cost": 41, + "gas_cost": 29759483, + "proving_cost": 5488732198, + "congestion_cost": 20517528044, + "congestion_multiplier": 4717959377 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 433, + "gas_cost": 314938678, + "proving_cost": 58086159194, + "congestion_cost": 217132911069, + "congestion_multiplier": 4717959377 + } + } + }, + { + "l1_block_number": 20974085, + "l1_fees": { + "blob_fee": 9770, + "base_fee": 9107507567 + }, + "parent_header": { + "excess_mana": 1325962709, + "mana_used": 95650619, + "proving_cost_per_mana_numerator": 1431637765, + "fee_asset_price_numerator": 5095534826 + }, + "header": { + "excess_mana": 1321613328, + "mana_used": 100534579, + "proving_cost_per_mana_numerator": 1304815455, + "fee_asset_price_numerator": 5440940203 + }, + "oracle_input": { + "proving_cost_modifier": -126822310, + "fee_asset_price_modifier": 345405377 + }, + "outputs": { + "fee_asset_price_at_execution": 10522759062, + "mana_base_fee_components_in_wei": { + "data_cost": 38, + "gas_cost": 30168618, + "proving_cost": 5493443884, + "congestion_cost": 20404289476, + "congestion_multiplier": 4694011723 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 399, + "gas_cost": 317457098, + "proving_cost": 57806186411, + "congestion_cost": 214709421987, + "congestion_multiplier": 4694011723 + } + } + }, + { + "l1_block_number": 20974088, + "l1_fees": { + "blob_fee": 9770, + "base_fee": 8571228619 + }, + "parent_header": { + "excess_mana": 1321613328, + "mana_used": 100534579, + "proving_cost_per_mana_numerator": 1304815455, + "fee_asset_price_numerator": 5440940203 + }, + "header": { + "excess_mana": 1322147907, + "mana_used": 105255685, + "proving_cost_per_mana_numerator": 1331312627, + "fee_asset_price_numerator": 4921429737 + }, + "oracle_input": { + "proving_cost_modifier": 26497172, + "fee_asset_price_modifier": -519510466 + }, + "outputs": { + "fee_asset_price_at_execution": 10559168081, + "mana_base_fee_components_in_wei": { + "data_cost": 38, + "gas_cost": 28392194, + "proving_cost": 5486481388, + "congestion_cost": 20388204010, + "congestion_multiplier": 4696948546 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 401, + "gas_cost": 299797948, + "proving_cost": 57932679149, + "congestion_cost": 215282473011, + "congestion_multiplier": 4696948546 + } + } + }, + { + "l1_block_number": 20974091, + "l1_fees": { + "blob_fee": 8350, + "base_fee": 9165139797 + }, + "parent_header": { + "excess_mana": 1322147907, + "mana_used": 105255685, + "proving_cost_per_mana_numerator": 1331312627, + "fee_asset_price_numerator": 4921429737 + }, + "header": { + "excess_mana": 1327403592, + "mana_used": 101065209, + "proving_cost_per_mana_numerator": 1299439387, + "fee_asset_price_numerator": 4946730380 + }, + "oracle_input": { + "proving_cost_modifier": -31873240, + "fee_asset_price_modifier": 25300643 + }, + "outputs": { + "fee_asset_price_at_execution": 10504454343, + "mana_base_fee_components_in_wei": { + "data_cost": 32, + "gas_cost": 30359525, + "proving_cost": 5487935343, + "congestion_cost": 20560724103, + "congestion_multiplier": 4725919777 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 336, + "gas_cost": 318910244, + "proving_cost": 57647766247, + "congestion_cost": 215979187598, + "congestion_multiplier": 4725919777 + } + } + }, + { + "l1_block_number": 20974094, + "l1_fees": { + "blob_fee": 8350, + "base_fee": 9073892217 + }, + "parent_header": { + "excess_mana": 1327403592, + "mana_used": 101065209, + "proving_cost_per_mana_numerator": 1299439387, + "fee_asset_price_numerator": 4946730380 + }, + "header": { + "excess_mana": 1328468801, + "mana_used": 89728000, + "proving_cost_per_mana_numerator": 1308013303, + "fee_asset_price_numerator": 4925732676 + }, + "oracle_input": { + "proving_cost_modifier": 8573916, + "fee_asset_price_modifier": -20997704 + }, + "outputs": { + "fee_asset_price_at_execution": 10507112373, + "mana_base_fee_components_in_wei": { + "data_cost": 32, + "gas_cost": 30057267, + "proving_cost": 5486186439, + "congestion_cost": 20585591951, + "congestion_multiplier": 4731813337 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 336, + "gas_cost": 315815081, + "proving_cost": 57643977413, + "congestion_cost": 216295127893, + "congestion_multiplier": 4731813337 + } + } + }, + { + "l1_block_number": 20974097, + "l1_fees": { + "blob_fee": 7422, + "base_fee": 8775012304 + }, + "parent_header": { + "excess_mana": 1328468801, + "mana_used": 89728000, + "proving_cost_per_mana_numerator": 1308013303, + "fee_asset_price_numerator": 4925732676 + }, + "header": { + "excess_mana": 1318196801, + "mana_used": 110180461, + "proving_cost_per_mana_numerator": 1308611786, + "fee_asset_price_numerator": 4359061244 + }, + "oracle_input": { + "proving_cost_modifier": 598483, + "fee_asset_price_modifier": -566671432 + }, + "outputs": { + "fee_asset_price_at_execution": 10504906353, + "mana_base_fee_components_in_wei": { + "data_cost": 29, + "gas_cost": 29067228, + "proving_cost": 5486656840, + "congestion_cost": 20271861518, + "congestion_multiplier": 4675285631 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 304, + "gas_cost": 305348508, + "proving_cost": 57636816295, + "congestion_cost": 212954006847, + "congestion_multiplier": 4675285631 + } + } + }, + { + "l1_block_number": 20974100, + "l1_fees": { + "blob_fee": 7136, + "base_fee": 8687630284 + }, + "parent_header": { + "excess_mana": 1318196801, + "mana_used": 110180461, + "proving_cost_per_mana_numerator": 1308611786, + "fee_asset_price_numerator": 4359061244 + }, + "header": { + "excess_mana": 1328377262, + "mana_used": 118939145, + "proving_cost_per_mana_numerator": 1405119072, + "fee_asset_price_numerator": 3995754984 + }, + "oracle_input": { + "proving_cost_modifier": 96507286, + "fee_asset_price_modifier": -363306260 + }, + "outputs": { + "fee_asset_price_at_execution": 10445546396, + "mana_base_fee_components_in_wei": { + "data_cost": 28, + "gas_cost": 28777775, + "proving_cost": 5486689677, + "congestion_cost": 20579900121, + "congestion_multiplier": 4731306584 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 292, + "gas_cost": 300599583, + "proving_cost": 57311471581, + "congestion_cost": 214968301538, + "congestion_multiplier": 4731306584 + } + } + }, + { + "l1_block_number": 20974103, + "l1_fees": { + "blob_fee": 6343, + "base_fee": 8779992851 + }, + "parent_header": { + "excess_mana": 1328377262, + "mana_used": 118939145, + "proving_cost_per_mana_numerator": 1405119072, + "fee_asset_price_numerator": 3995754984 + }, + "header": { + "excess_mana": 1347316407, + "mana_used": 83523832, + "proving_cost_per_mana_numerator": 1432998603, + "fee_asset_price_numerator": 4308644264 + }, + "oracle_input": { + "proving_cost_modifier": 27879531, + "fee_asset_price_modifier": 312889280 + }, + "outputs": { + "fee_asset_price_at_execution": 10407665925, + "mana_base_fee_components_in_wei": { + "data_cost": 24, + "gas_cost": 29083726, + "proving_cost": 5491987288, + "congestion_cost": 21186098929, + "congestion_multiplier": 4837316851 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 249, + "gas_cost": 302693704, + "proving_cost": 57158768957, + "congestion_cost": 220497839907, + "congestion_multiplier": 4837316851 + } + } + }, + { + "l1_block_number": 20974106, + "l1_fees": { + "blob_fee": 6343, + "base_fee": 9971002047 + }, + "parent_header": { + "excess_mana": 1347316407, + "mana_used": 83523832, + "proving_cost_per_mana_numerator": 1432998603, + "fee_asset_price_numerator": 4308644264 + }, + "header": { + "excess_mana": 1330840239, + "mana_used": 88135080, + "proving_cost_per_mana_numerator": 1595042674, + "fee_asset_price_numerator": 4514596152 + }, + "oracle_input": { + "proving_cost_modifier": 162044071, + "fee_asset_price_modifier": 205951888 + }, + "outputs": { + "fee_asset_price_at_execution": 10440281394, + "mana_base_fee_components_in_wei": { + "data_cost": 24, + "gas_cost": 33028944, + "proving_cost": 5493518642, + "congestion_cost": 20696701798, + "congestion_multiplier": 4744960373 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 250, + "gas_cost": 344831469, + "proving_cost": 57353880465, + "congestion_cost": 216079390698, + "congestion_multiplier": 4744960373 + } + } + }, + { + "l1_block_number": 20974109, + "l1_fees": { + "blob_fee": 5638, + "base_fee": 9495549897 + }, + "parent_header": { + "excess_mana": 1330840239, + "mana_used": 88135080, + "proving_cost_per_mana_numerator": 1595042674, + "fee_asset_price_numerator": 4514596152 + }, + "header": { + "excess_mana": 1318975319, + "mana_used": 103366901, + "proving_cost_per_mana_numerator": 1576902899, + "fee_asset_price_numerator": 4393549612 + }, + "oracle_input": { + "proving_cost_modifier": -18139775, + "fee_asset_price_modifier": -121046540 + }, + "outputs": { + "fee_asset_price_at_execution": 10461805508, + "mana_base_fee_components_in_wei": { + "data_cost": 22, + "gas_cost": 31454009, + "proving_cost": 5502427779, + "congestion_cost": 20362173397, + "congestion_multiplier": 4679546130 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 230, + "gas_cost": 329065724, + "proving_cost": 57565329245, + "congestion_cost": 213025097799, + "congestion_multiplier": 4679546130 + } + } + }, + { + "l1_block_number": 20974112, + "l1_fees": { + "blob_fee": 5012, + "base_fee": 9531667424 + }, + "parent_header": { + "excess_mana": 1318975319, + "mana_used": 103366901, + "proving_cost_per_mana_numerator": 1576902899, + "fee_asset_price_numerator": 4393549612 + }, + "header": { + "excess_mana": 1322342220, + "mana_used": 105121839, + "proving_cost_per_mana_numerator": 1304053042, + "fee_asset_price_numerator": 5192433162 + }, + "oracle_input": { + "proving_cost_modifier": -272849857, + "fee_asset_price_modifier": 798883550 + }, + "outputs": { + "fee_asset_price_at_execution": 10449149516, + "mana_base_fee_components_in_wei": { + "data_cost": 19, + "gas_cost": 31573648, + "proving_cost": 5501429742, + "congestion_cost": 20461137906, + "congestion_multiplier": 4698016501 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 198, + "gas_cost": 329917768, + "proving_cost": 57485261925, + "congestion_cost": 213801489247, + "congestion_multiplier": 4698016501 + } + } + }, + { + "l1_block_number": 20974115, + "l1_fees": { + "blob_fee": 4819, + "base_fee": 10731011935 + }, + "parent_header": { + "excess_mana": 1322342220, + "mana_used": 105121839, + "proving_cost_per_mana_numerator": 1304053042, + "fee_asset_price_numerator": 5192433162 + }, + "header": { + "excess_mana": 1327464059, + "mana_used": 108840687, + "proving_cost_per_mana_numerator": 1179553844, + "fee_asset_price_numerator": 4891944810 + }, + "oracle_input": { + "proving_cost_modifier": -124499198, + "fee_asset_price_modifier": -300488352 + }, + "outputs": { + "fee_asset_price_at_execution": 10532960382, + "mana_base_fee_components_in_wei": { + "data_cost": 18, + "gas_cost": 35546477, + "proving_cost": 5486439558, + "congestion_cost": 20576323341, + "congestion_multiplier": 4726254131 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 189, + "gas_cost": 374409633, + "proving_cost": 57788450502, + "congestion_cost": 216729598557, + "congestion_multiplier": 4726254131 + } + } + }, + { + "l1_block_number": 20974118, + "l1_fees": { + "blob_fee": 5212, + "base_fee": 10880046233 + }, + "parent_header": { + "excess_mana": 1327464059, + "mana_used": 108840687, + "proving_cost_per_mana_numerator": 1179553844, + "fee_asset_price_numerator": 4891944810 + }, + "header": { + "excess_mana": 1336304746, + "mana_used": 73668457, + "proving_cost_per_mana_numerator": 1313673273, + "fee_asset_price_numerator": 4922105240 + }, + "oracle_input": { + "proving_cost_modifier": 134119429, + "fee_asset_price_modifier": 30160430 + }, + "outputs": { + "fee_asset_price_at_execution": 10501357569, + "mana_base_fee_components_in_wei": { + "data_cost": 20, + "gas_cost": 36040153, + "proving_cost": 5479613235, + "congestion_cost": 20823766635, + "congestion_multiplier": 4775394336 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 210, + "gas_cost": 378470533, + "proving_cost": 57543377920, + "congestion_cost": 218677819367, + "congestion_multiplier": 4775394336 + } + } + }, + { + "l1_block_number": 20974121, + "l1_fees": { + "blob_fee": 3960, + "base_fee": 10929199366 + }, + "parent_header": { + "excess_mana": 1336304746, + "mana_used": 73668457, + "proving_cost_per_mana_numerator": 1313673273, + "fee_asset_price_numerator": 4922105240 + }, + "header": { + "excess_mana": 1309973203, + "mana_used": 114284930, + "proving_cost_per_mana_numerator": 1217891954, + "fee_asset_price_numerator": 4382088410 + }, + "oracle_input": { + "proving_cost_modifier": -95781319, + "fee_asset_price_modifier": -540016830 + }, + "outputs": { + "fee_asset_price_at_execution": 10504525301, + "mana_base_fee_components_in_wei": { + "data_cost": 15, + "gas_cost": 36202972, + "proving_cost": 5486967392, + "congestion_cost": 20051967119, + "congestion_multiplier": 4630517573 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 157, + "gas_cost": 380295035, + "proving_cost": 57637987795, + "congestion_cost": 210636395936, + "congestion_multiplier": 4630517573 + } + } + }, + { + "l1_block_number": 20974124, + "l1_fees": { + "blob_fee": 3661, + "base_fee": 10608376541 + }, + "parent_header": { + "excess_mana": 1309973203, + "mana_used": 114284930, + "proving_cost_per_mana_numerator": 1217891954, + "fee_asset_price_numerator": 4382088410 + }, + "header": { + "excess_mana": 1324258133, + "mana_used": 104636722, + "proving_cost_per_mana_numerator": 1276217998, + "fee_asset_price_numerator": 4279528698 + }, + "oracle_input": { + "proving_cost_modifier": 58326044, + "fee_asset_price_modifier": -102559712 + }, + "outputs": { + "fee_asset_price_at_execution": 10447951986, + "mana_base_fee_components_in_wei": { + "data_cost": 14, + "gas_cost": 35140247, + "proving_cost": 5481714418, + "congestion_cost": 20459583680, + "congestion_multiplier": 4708559473 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 146, + "gas_cost": 367143613, + "proving_cost": 57272689040, + "congestion_cost": 213760747942, + "congestion_multiplier": 4708559473 + } + } + }, + { + "l1_block_number": 20974127, + "l1_fees": { + "blob_fee": 2781, + "base_fee": 10777238232 + }, + "parent_header": { + "excess_mana": 1324258133, + "mana_used": 104636722, + "proving_cost_per_mana_numerator": 1276217998, + "fee_asset_price_numerator": 4279528698 + }, + "header": { + "excess_mana": 1328894855, + "mana_used": 83656362, + "proving_cost_per_mana_numerator": 1180049967, + "fee_asset_price_numerator": 3780652926 + }, + "oracle_input": { + "proving_cost_modifier": -96168031, + "fee_asset_price_modifier": -498875772 + }, + "outputs": { + "fee_asset_price_at_execution": 10437242090, + "mana_base_fee_components_in_wei": { + "data_cost": 10, + "gas_cost": 35699601, + "proving_cost": 5484912618, + "congestion_cost": 20614919218, + "congestion_multiplier": 4734172654 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 104, + "gas_cost": 372605378, + "proving_cost": 57247360836, + "congestion_cost": 215162902544, + "congestion_multiplier": 4734172654 + } + } + }, + { + "l1_block_number": 20974130, + "l1_fees": { + "blob_fee": 2571, + "base_fee": 11304295945 + }, + "parent_header": { + "excess_mana": 1328894855, + "mana_used": 83656362, + "proving_cost_per_mana_numerator": 1180049967, + "fee_asset_price_numerator": 3780652926 + }, + "header": { + "excess_mana": 1312551217, + "mana_used": 128278391, + "proving_cost_per_mana_numerator": 1224832645, + "fee_asset_price_numerator": 3584705140 + }, + "oracle_input": { + "proving_cost_modifier": 44782678, + "fee_asset_price_modifier": -195947786 + }, + "outputs": { + "fee_asset_price_at_execution": 10385302882, + "mana_base_fee_components_in_wei": { + "data_cost": 10, + "gas_cost": 37445480, + "proving_cost": 5479640421, + "congestion_cost": 20107050382, + "congestion_multiplier": 4644505579 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 103, + "gas_cost": 388882651, + "proving_cost": 56907725456, + "congestion_cost": 208817808280, + "congestion_multiplier": 4644505579 + } + } + }, + { + "l1_block_number": 20974133, + "l1_fees": { + "blob_fee": 2285, + "base_fee": 10659083042 + }, + "parent_header": { + "excess_mana": 1312551217, + "mana_used": 128278391, + "proving_cost_per_mana_numerator": 1224832645, + "fee_asset_price_numerator": 3584705140 + }, + "header": { + "excess_mana": 1340829608, + "mana_used": 96867550, + "proving_cost_per_mana_numerator": 1260260737, + "fee_asset_price_numerator": 3246488766 + }, + "oracle_input": { + "proving_cost_modifier": 35428092, + "fee_asset_price_modifier": -338216374 + }, + "outputs": { + "fee_asset_price_at_execution": 10364973035, + "mana_base_fee_components_in_wei": { + "data_cost": 8, + "gas_cost": 35308212, + "proving_cost": 5482094900, + "congestion_cost": 20970229829, + "congestion_multiplier": 4800742736 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 82, + "gas_cost": 365968665, + "proving_cost": 56821765813, + "congestion_cost": 217355866715, + "congestion_multiplier": 4800742736 + } + } + }, + { + "l1_block_number": 20974136, + "l1_fees": { + "blob_fee": 2031, + "base_fee": 9963610155 + }, + "parent_header": { + "excess_mana": 1340829608, + "mana_used": 96867550, + "proving_cost_per_mana_numerator": 1260260737, + "fee_asset_price_numerator": 3246488766 + }, + "header": { + "excess_mana": 1337697158, + "mana_used": 89334588, + "proving_cost_per_mana_numerator": 1221780971, + "fee_asset_price_numerator": 3082804055 + }, + "oracle_input": { + "proving_cost_modifier": -38479766, + "fee_asset_price_modifier": -163684711 + }, + "outputs": { + "fee_asset_price_at_execution": 10329976215, + "mana_base_fee_components_in_wei": { + "data_cost": 7, + "gas_cost": 33004458, + "proving_cost": 5484037446, + "congestion_cost": 20871964696, + "congestion_multiplier": 4783180377 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 72, + "gas_cost": 340935266, + "proving_cost": 56649976379, + "congestion_cost": 215606898869, + "congestion_multiplier": 4783180377 + } + } + }, + { + "l1_block_number": 20974139, + "l1_fees": { + "blob_fee": 1736, + "base_fee": 10028608487 + }, + "parent_header": { + "excess_mana": 1337697158, + "mana_used": 89334588, + "proving_cost_per_mana_numerator": 1221780971, + "fee_asset_price_numerator": 3082804055 + }, + "header": { + "excess_mana": 1327031746, + "mana_used": 99486098, + "proving_cost_per_mana_numerator": 1490272456, + "fee_asset_price_numerator": 2527104241 + }, + "oracle_input": { + "proving_cost_modifier": 268491485, + "fee_asset_price_modifier": -555699814 + }, + "outputs": { + "fee_asset_price_at_execution": 10313081454, + "mana_base_fee_components_in_wei": { + "data_cost": 6, + "gas_cost": 33219765, + "proving_cost": 5481927607, + "congestion_cost": 20537659691, + "congestion_multiplier": 4723864166 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 61, + "gas_cost": 342598142, + "proving_cost": 56535565935, + "congestion_cost": 211806557267, + "congestion_multiplier": 4723864166 + } + } + }, + { + "l1_block_number": 20974142, + "l1_fees": { + "blob_fee": 1953, + "base_fee": 9542754428 + }, + "parent_header": { + "excess_mana": 1327031746, + "mana_used": 99486098, + "proving_cost_per_mana_numerator": 1490272456, + "fee_asset_price_numerator": 2527104241 + }, + "header": { + "excess_mana": 1326517844, + "mana_used": 108694901, + "proving_cost_per_mana_numerator": 1574032256, + "fee_asset_price_numerator": 3142134000 + }, + "oracle_input": { + "proving_cost_modifier": 83759800, + "fee_asset_price_modifier": 615029759 + }, + "outputs": { + "fee_asset_price_at_execution": 10255930620, + "mana_base_fee_components_in_wei": { + "data_cost": 7, + "gas_cost": 31610374, + "proving_cost": 5496665893, + "congestion_cost": 20570852696, + "congestion_multiplier": 4721024724 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 71, + "gas_cost": 324193802, + "proving_cost": 56373424039, + "congestion_cost": 210973238044, + "congestion_multiplier": 4721024724 + } + } + }, + { + "l1_block_number": 20974145, + "l1_fees": { + "blob_fee": 1484, + "base_fee": 9528375984 + }, + "parent_header": { + "excess_mana": 1326517844, + "mana_used": 108694901, + "proving_cost_per_mana_numerator": 1574032256, + "fee_asset_price_numerator": 3142134000 + }, + "header": { + "excess_mana": 1335212745, + "mana_used": 74816411, + "proving_cost_per_mana_numerator": 1482684488, + "fee_asset_price_numerator": 3536744697 + }, + "oracle_input": { + "proving_cost_modifier": -91347768, + "fee_asset_price_modifier": 394610697 + }, + "outputs": { + "fee_asset_price_at_execution": 10319202015, + "mana_base_fee_components_in_wei": { + "data_cost": 5, + "gas_cost": 31562745, + "proving_cost": 5501271818, + "congestion_cost": 20854896694, + "congestion_multiplier": 4769296992 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 51, + "gas_cost": 325702341, + "proving_cost": 56768735229, + "congestion_cost": 215205891987, + "congestion_multiplier": 4769296992 + } + } + }, + { + "l1_block_number": 20974148, + "l1_fees": { + "blob_fee": 1543, + "base_fee": 9131788018 + }, + "parent_header": { + "excess_mana": 1335212745, + "mana_used": 74816411, + "proving_cost_per_mana_numerator": 1482684488, + "fee_asset_price_numerator": 3536744697 + }, + "header": { + "excess_mana": 1310029156, + "mana_used": 104983478, + "proving_cost_per_mana_numerator": 1414641441, + "fee_asset_price_numerator": 3308538546 + }, + "oracle_input": { + "proving_cost_modifier": -68043047, + "fee_asset_price_modifier": -228206151 + }, + "outputs": { + "fee_asset_price_at_execution": 10360003140, + "mana_base_fee_components_in_wei": { + "data_cost": 6, + "gas_cost": 30249047, + "proving_cost": 5496248823, + "congestion_cost": 20065722997, + "congestion_multiplier": 4630820720 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 62, + "gas_cost": 313380221, + "proving_cost": 56941155064, + "congestion_cost": 207880953255, + "congestion_multiplier": 4630820720 + } + } + }, + { + "l1_block_number": 20974151, + "l1_fees": { + "blob_fee": 1543, + "base_fee": 9146141907 + }, + "parent_header": { + "excess_mana": 1310029156, + "mana_used": 104983478, + "proving_cost_per_mana_numerator": 1414641441, + "fee_asset_price_numerator": 3308538546 + }, + "header": { + "excess_mana": 1315012634, + "mana_used": 107439287, + "proving_cost_per_mana_numerator": 1389165965, + "fee_asset_price_numerator": 4165704660 + }, + "oracle_input": { + "proving_cost_modifier": -25475476, + "fee_asset_price_modifier": 857166114 + }, + "outputs": { + "fee_asset_price_at_execution": 10336387931, + "mana_base_fee_components_in_wei": { + "data_cost": 6, + "gas_cost": 30296595, + "proving_cost": 5492510280, + "congestion_cost": 20201877350, + "congestion_multiplier": 4657900373 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 62, + "gas_cost": 313157358, + "proving_cost": 56772716969, + "congestion_cost": 208814441224, + "congestion_multiplier": 4657900373 + } + } + }, + { + "l1_block_number": 20974154, + "l1_fees": { + "blob_fee": 1605, + "base_fee": 8760412288 + }, + "parent_header": { + "excess_mana": 1315012634, + "mana_used": 107439287, + "proving_cost_per_mana_numerator": 1389165965, + "fee_asset_price_numerator": 4165704660 + }, + "header": { + "excess_mana": 1322451921, + "mana_used": 18730895, + "proving_cost_per_mana_numerator": 1407055898, + "fee_asset_price_numerator": 4506427180 + }, + "oracle_input": { + "proving_cost_modifier": 17889933, + "fee_asset_price_modifier": 340722520 + }, + "outputs": { + "fee_asset_price_at_execution": 10425368758, + "mana_base_fee_components_in_wei": { + "data_cost": 6, + "gas_cost": 29018865, + "proving_cost": 5491111215, + "congestion_cost": 20416860949, + "congestion_multiplier": 4698619531 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 62, + "gas_cost": 302532368, + "proving_cost": 57246859307, + "congestion_cost": 212853304274, + "congestion_multiplier": 4698619531 + } + } + }, + { + "l1_block_number": 20974157, + "l1_fees": { + "blob_fee": 1426, + "base_fee": 8436997127 + }, + "parent_header": { + "excess_mana": 1322451921, + "mana_used": 18730895, + "proving_cost_per_mana_numerator": 1407055898, + "fee_asset_price_numerator": 4506427180 + }, + "header": { + "excess_mana": 1241182816, + "mana_used": 157332552, + "proving_cost_per_mana_numerator": 1287220253, + "fee_asset_price_numerator": 5099720058 + }, + "oracle_input": { + "proving_cost_modifier": -119835645, + "fee_asset_price_modifier": 593292878 + }, + "outputs": { + "fee_asset_price_at_execution": 10460950921, + "mana_base_fee_components_in_wei": { + "data_cost": 5, + "gas_cost": 27947552, + "proving_cost": 5492093659, + "congestion_cost": 18063975452, + "congestion_multiplier": 4272434887 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 52, + "gas_cost": 292357969, + "proving_cost": 57452522220, + "congestion_cost": 188966360641, + "congestion_multiplier": 4272434887 + } + } + }, + { + "l1_block_number": 20974160, + "l1_fees": { + "blob_fee": 1219, + "base_fee": 10808069079 + }, + "parent_header": { + "excess_mana": 1241182816, + "mana_used": 157332552, + "proving_cost_per_mana_numerator": 1287220253, + "fee_asset_price_numerator": 5099720058 + }, + "header": { + "excess_mana": 1298515368, + "mana_used": 118327080, + "proving_cost_per_mana_numerator": 1088996923, + "fee_asset_price_numerator": 5193259556 + }, + "oracle_input": { + "proving_cost_modifier": -198223330, + "fee_asset_price_modifier": 93539498 + }, + "outputs": { + "fee_asset_price_at_execution": 10523199473, + "mana_base_fee_components_in_wei": { + "data_cost": 4, + "gas_cost": 35801728, + "proving_cost": 5485516115, + "congestion_cost": 19704791765, + "congestion_multiplier": 4568856623 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 42, + "gas_cost": 376748725, + "proving_cost": 57725180290, + "congestion_cost": 207357454317, + "congestion_multiplier": 4568856623 + } + } + }, + { + "l1_block_number": 20974163, + "l1_fees": { + "blob_fee": 1084, + "base_fee": 10151808592 + }, + "parent_header": { + "excess_mana": 1298515368, + "mana_used": 118327080, + "proving_cost_per_mana_numerator": 1088996923, + "fee_asset_price_numerator": 5193259556 + }, + "header": { + "excess_mana": 1316842448, + "mana_used": 89473864, + "proving_cost_per_mana_numerator": 1164598933, + "fee_asset_price_numerator": 5476749594 + }, + "oracle_input": { + "proving_cost_modifier": 75602010, + "fee_asset_price_modifier": 283490038 + }, + "outputs": { + "fee_asset_price_at_execution": 10533047427, + "mana_base_fee_components_in_wei": { + "data_cost": 4, + "gas_cost": 33627865, + "proving_cost": 5474653312, + "congestion_cost": 20203731299, + "congestion_multiplier": 4667883072 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 42, + "gas_cost": 354203896, + "proving_cost": 57664782981, + "congestion_cost": 212806859974, + "congestion_multiplier": 4667883072 + } + } + }, + { + "l1_block_number": 20974166, + "l1_fees": { + "blob_fee": 823, + "base_fee": 9893170338 + }, + "parent_header": { + "excess_mana": 1316842448, + "mana_used": 89473864, + "proving_cost_per_mana_numerator": 1164598933, + "fee_asset_price_numerator": 5476749594 + }, + "header": { + "excess_mana": 1306316312, + "mana_used": 57418796, + "proving_cost_per_mana_numerator": 1202744964, + "fee_asset_price_numerator": 5218827127 + }, + "oracle_input": { + "proving_cost_modifier": 38146031, + "fee_asset_price_modifier": -257922467 + }, + "outputs": { + "fee_asset_price_at_execution": 10562949932, + "mana_base_fee_components_in_wei": { + "data_cost": 3, + "gas_cost": 32771126, + "proving_cost": 5478793825, + "congestion_cost": 19900871787, + "congestion_multiplier": 4610747937 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 31, + "gas_cost": 346159763, + "proving_cost": 57872224861, + "congestion_cost": 210211912289, + "congestion_multiplier": 4610747937 + } + } + }, + { + "l1_block_number": 20974169, + "l1_fees": { + "blob_fee": 926, + "base_fee": 9477902554 + }, + "parent_header": { + "excess_mana": 1306316312, + "mana_used": 57418796, + "proving_cost_per_mana_numerator": 1202744964, + "fee_asset_price_numerator": 5218827127 + }, + "header": { + "excess_mana": 1263735108, + "mana_used": 144445614, + "proving_cost_per_mana_numerator": 1275483706, + "fee_asset_price_numerator": 5255608628 + }, + "oracle_input": { + "proving_cost_modifier": 72738742, + "fee_asset_price_modifier": 36781501 + }, + "outputs": { + "fee_asset_price_at_execution": 10535740815, + "mana_base_fee_components_in_wei": { + "data_cost": 3, + "gas_cost": 31395552, + "proving_cost": 5480884166, + "congestion_cost": 18668264634, + "congestion_multiplier": 4386668598 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 31, + "gas_cost": 330775398, + "proving_cost": 57745175010, + "congestion_cost": 196683997649, + "congestion_multiplier": 4386668598 + } + } + }, + { + "l1_block_number": 20974172, + "l1_fees": { + "blob_fee": 890, + "base_fee": 8894215403 + }, + "parent_header": { + "excess_mana": 1263735108, + "mana_used": 144445614, + "proving_cost_per_mana_numerator": 1275483706, + "fee_asset_price_numerator": 5255608628 + }, + "header": { + "excess_mana": 1308180722, + "mana_used": 113971510, + "proving_cost_per_mana_numerator": 1254728663, + "fee_asset_price_numerator": 4448615753 + }, + "oracle_input": { + "proving_cost_modifier": -20755043, + "fee_asset_price_modifier": -806992875 + }, + "outputs": { + "fee_asset_price_at_execution": 10539616732, + "mana_base_fee_components_in_wei": { + "data_cost": 3, + "gas_cost": 29462088, + "proving_cost": 5484872343, + "congestion_cost": 19966393739, + "congestion_multiplier": 4620816615 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 31, + "gas_cost": 310519115, + "proving_cost": 57808452319, + "congestion_cost": 210438137529, + "congestion_multiplier": 4620816615 + } + } + }, + { + "l1_block_number": 20974175, + "l1_fees": { + "blob_fee": 1042, + "base_fee": 8477418490 + }, + "parent_header": { + "excess_mana": 1308180722, + "mana_used": 113971510, + "proving_cost_per_mana_numerator": 1254728663, + "fee_asset_price_numerator": 4448615753 + }, + "header": { + "excess_mana": 1322152232, + "mana_used": 107289899, + "proving_cost_per_mana_numerator": 1284412021, + "fee_asset_price_numerator": 3610717908 + }, + "oracle_input": { + "proving_cost_modifier": 29683358, + "fee_asset_price_modifier": -837897845 + }, + "outputs": { + "fee_asset_price_at_execution": 10454905044, + "mana_base_fee_components_in_wei": { + "data_cost": 4, + "gas_cost": 28081448, + "proving_cost": 5483734073, + "congestion_cost": 20377029395, + "congestion_multiplier": 4696972314 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 41, + "gas_cost": 293588872, + "proving_cost": 57331919019, + "congestion_cost": 213039907403, + "congestion_multiplier": 4696972314 + } + } + }, + { + "l1_block_number": 20974178, + "l1_fees": { + "blob_fee": 761, + "base_fee": 9568615682 + }, + "parent_header": { + "excess_mana": 1322152232, + "mana_used": 107289899, + "proving_cost_per_mana_numerator": 1284412021, + "fee_asset_price_numerator": 3610717908 + }, + "header": { + "excess_mana": 1329442131, + "mana_used": 88045123, + "proving_cost_per_mana_numerator": 1371214073, + "fee_asset_price_numerator": 3074238422 + }, + "oracle_input": { + "proving_cost_modifier": 86802052, + "fee_asset_price_modifier": -536479486 + }, + "outputs": { + "fee_asset_price_at_execution": 10367669602, + "mana_base_fee_components_in_wei": { + "data_cost": 2, + "gas_cost": 31696039, + "proving_cost": 5485362071, + "congestion_cost": 20618377034, + "congestion_multiplier": 4737204977 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 20, + "gas_cost": 328614060, + "proving_cost": 56870421599, + "congestion_cost": 213764520817, + "congestion_multiplier": 4737204977 + } + } + }, + { + "l1_block_number": 20974181, + "l1_fees": { + "blob_fee": 761, + "base_fee": 9315023234 + }, + "parent_header": { + "excess_mana": 1329442131, + "mana_used": 88045123, + "proving_cost_per_mana_numerator": 1371214073, + "fee_asset_price_numerator": 3074238422 + }, + "header": { + "excess_mana": 1317487254, + "mana_used": 108329434, + "proving_cost_per_mana_numerator": 1403657471, + "fee_asset_price_numerator": 3193055101 + }, + "oracle_input": { + "proving_cost_modifier": 32443398, + "fee_asset_price_modifier": 118816679 + }, + "outputs": { + "fee_asset_price_at_execution": 10312198111, + "mana_base_fee_components_in_wei": { + "data_cost": 2, + "gas_cost": 30856014, + "proving_cost": 5490125545, + "congestion_cost": 20269764602, + "congestion_multiplier": 4671405959 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 20, + "gas_cost": 318193329, + "proving_cost": 56615262274, + "congestion_cost": 209025828239, + "congestion_multiplier": 4671405959 + } + } + }, + { + "l1_block_number": 20974184, + "l1_fees": { + "blob_fee": 703, + "base_fee": 9674041257 + }, + "parent_header": { + "excess_mana": 1317487254, + "mana_used": 108329434, + "proving_cost_per_mana_numerator": 1403657471, + "fee_asset_price_numerator": 3193055101 + }, + "header": { + "excess_mana": 1325816688, + "mana_used": 95514331, + "proving_cost_per_mana_numerator": 1448230411, + "fee_asset_price_numerator": 3108372249 + }, + "oracle_input": { + "proving_cost_modifier": 44572940, + "fee_asset_price_modifier": -84682852 + }, + "outputs": { + "fee_asset_price_at_execution": 10324458004, + "mana_base_fee_components_in_wei": { + "data_cost": 2, + "gas_cost": 32045261, + "proving_cost": 5491907017, + "congestion_cost": 20533378043, + "congestion_multiplier": 4717153408 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 20, + "gas_cost": 330849951, + "proving_cost": 56700963358, + "congestion_cost": 211995999285, + "congestion_multiplier": 4717153408 + } + } + }, + { + "l1_block_number": 20974187, + "l1_fees": { + "blob_fee": 625, + "base_fee": 10003788198 + }, + "parent_header": { + "excess_mana": 1325816688, + "mana_used": 95514331, + "proving_cost_per_mana_numerator": 1448230411, + "fee_asset_price_numerator": 3108372249 + }, + "header": { + "excess_mana": 1321331019, + "mana_used": 108247087, + "proving_cost_per_mana_numerator": 1370678469, + "fee_asset_price_numerator": 3067437500 + }, + "oracle_input": { + "proving_cost_modifier": -77551942, + "fee_asset_price_modifier": -40934749 + }, + "outputs": { + "fee_asset_price_at_execution": 10315718660, + "mana_base_fee_components_in_wei": { + "data_cost": 2, + "gas_cost": 33137548, + "proving_cost": 5494355468, + "congestion_cost": 20410055381, + "congestion_multiplier": 4692461540 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 20, + "gas_cost": 341837622, + "proving_cost": 56678225225, + "congestion_cost": 210544389145, + "congestion_multiplier": 4692461540 + } + } + }, + { + "l1_block_number": 20974190, + "l1_fees": { + "blob_fee": 534, + "base_fee": 9982107079 + }, + "parent_header": { + "excess_mana": 1321331019, + "mana_used": 108247087, + "proving_cost_per_mana_numerator": 1370678469, + "fee_asset_price_numerator": 3067437500 + }, + "header": { + "excess_mana": 1329578106, + "mana_used": 94836752, + "proving_cost_per_mana_numerator": 1315359805, + "fee_asset_price_numerator": 2072392464 + }, + "oracle_input": { + "proving_cost_modifier": -55318664, + "fee_asset_price_modifier": -995045036 + }, + "outputs": { + "fee_asset_price_at_execution": 10311496810, + "mana_base_fee_components_in_wei": { + "data_cost": 2, + "gas_cost": 33065729, + "proving_cost": 5490096140, + "congestion_cost": 20645350867, + "congestion_multiplier": 4737958682 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 20, + "gas_cost": 340957159, + "proving_cost": 56611108834, + "congestion_cost": 212884469606, + "congestion_multiplier": 4737958682 + } + } + }, + { + "l1_block_number": 20974193, + "l1_fees": { + "blob_fee": 439, + "base_fee": 9835913437 + }, + "parent_header": { + "excess_mana": 1329578106, + "mana_used": 94836752, + "proving_cost_per_mana_numerator": 1315359805, + "fee_asset_price_numerator": 2072392464 + }, + "header": { + "excess_mana": 1324414858, + "mana_used": 99286901, + "proving_cost_per_mana_numerator": 1200670532, + "fee_asset_price_numerator": 2044356545 + }, + "oracle_input": { + "proving_cost_modifier": -114689273, + "fee_asset_price_modifier": -28035919 + }, + "outputs": { + "fee_asset_price_at_execution": 10209401563, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 32581463, + "proving_cost": 5487059932, + "congestion_cost": 20474684481, + "congestion_multiplier": 4709422952 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 332637239, + "proving_cost": 56019598246, + "congestion_cost": 209034275742, + "congestion_multiplier": 4709422952 + } + } + }, + { + "l1_block_number": 20974196, + "l1_fees": { + "blob_fee": 556, + "base_fee": 10115073494 + }, + "parent_header": { + "excess_mana": 1324414858, + "mana_used": 99286901, + "proving_cost_per_mana_numerator": 1200670532, + "fee_asset_price_numerator": 2044356545 + }, + "header": { + "excess_mana": 1323701759, + "mana_used": 96289879, + "proving_cost_per_mana_numerator": 1147361388, + "fee_asset_price_numerator": 1998932862 + }, + "oracle_input": { + "proving_cost_modifier": -53309144, + "fee_asset_price_modifier": -45423683 + }, + "outputs": { + "fee_asset_price_at_execution": 10206539664, + "mana_base_fee_components_in_wei": { + "data_cost": 2, + "gas_cost": 33506180, + "proving_cost": 5480770470, + "congestion_cost": 20433126751, + "congestion_multiplier": 4705495397 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 20, + "gas_cost": 341982155, + "proving_cost": 55939701191, + "congestion_cost": 208551518643, + "congestion_multiplier": 4705495397 + } + } + }, + { + "l1_block_number": 20974199, + "l1_fees": { + "blob_fee": 475, + "base_fee": 10075372811 + }, + "parent_header": { + "excess_mana": 1323701759, + "mana_used": 96289879, + "proving_cost_per_mana_numerator": 1147361388, + "fee_asset_price_numerator": 1998932862 + }, + "header": { + "excess_mana": 1319991638, + "mana_used": 89782724, + "proving_cost_per_mana_numerator": 1200037686, + "fee_asset_price_numerator": 1805396846 + }, + "oracle_input": { + "proving_cost_modifier": 52676298, + "fee_asset_price_modifier": -193536016 + }, + "outputs": { + "fee_asset_price_at_execution": 10201904531, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 33374672, + "proving_cost": 5477849497, + "congestion_cost": 20309488552, + "congestion_multiplier": 4685113856 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 340485217, + "proving_cost": 55884497603, + "congestion_cost": 207195463280, + "congestion_multiplier": 4685113856 + } + } + }, + { + "l1_block_number": 20974202, + "l1_fees": { + "blob_fee": 439, + "base_fee": 9814380947 + }, + "parent_header": { + "excess_mana": 1319991638, + "mana_used": 89782724, + "proving_cost_per_mana_numerator": 1200037686, + "fee_asset_price_numerator": 1805396846 + }, + "header": { + "excess_mana": 1309774362, + "mana_used": 103450185, + "proving_cost_per_mana_numerator": 1346901685, + "fee_asset_price_numerator": 2325955733 + }, + "oracle_input": { + "proving_cost_modifier": 146863999, + "fee_asset_price_modifier": 520558887 + }, + "outputs": { + "fee_asset_price_at_execution": 10182179265, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 32510136, + "proving_cost": 5480735786, + "congestion_cost": 20009997686, + "congestion_multiplier": 4629440436 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 331024032, + "proving_cost": 55805834277, + "congestion_cost": 203745383531, + "congestion_multiplier": 4629440436 + } + } + }, + { + "l1_block_number": 20974205, + "l1_fees": { + "blob_fee": 333, + "base_fee": 9109952895 + }, + "parent_header": { + "excess_mana": 1309774362, + "mana_used": 103450185, + "proving_cost_per_mana_numerator": 1346901685, + "fee_asset_price_numerator": 2325955733 + }, + "header": { + "excess_mana": 1313224547, + "mana_used": 98620120, + "proving_cost_per_mana_numerator": 1479876845, + "fee_asset_price_numerator": 2117602111 + }, + "oracle_input": { + "proving_cost_modifier": 132975160, + "fee_asset_price_modifier": -208353622 + }, + "outputs": { + "fee_asset_price_at_execution": 10235321703, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 30176718, + "proving_cost": 5488790927, + "congestion_cost": 20134109812, + "congestion_multiplier": 4648165944 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 308868416, + "proving_cost": 56179540898, + "congestion_cost": 206079091129, + "congestion_multiplier": 4648165944 + } + } + }, + { + "l1_block_number": 20974208, + "l1_fees": { + "blob_fee": 347, + "base_fee": 9950819786 + }, + "parent_header": { + "excess_mana": 1313224547, + "mana_used": 98620120, + "proving_cost_per_mana_numerator": 1479876845, + "fee_asset_price_numerator": 2117602111 + }, + "header": { + "excess_mana": 1311844667, + "mana_used": 108251001, + "proving_cost_per_mana_numerator": 1268393069, + "fee_asset_price_numerator": 1217566793 + }, + "oracle_input": { + "proving_cost_modifier": -211483776, + "fee_asset_price_modifier": -900035318 + }, + "outputs": { + "fee_asset_price_at_execution": 10214018240, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 32962090, + "proving_cost": 5496094510, + "congestion_cost": 20129457900, + "congestion_multiplier": 4640667722 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 336675388, + "proving_cost": 56137209573, + "congestion_cost": 205602650151, + "congestion_multiplier": 4640667722 + } + } + }, + { + "l1_block_number": 20974211, + "l1_fees": { + "blob_fee": 263, + "base_fee": 9969692206 + }, + "parent_header": { + "excess_mana": 1311844667, + "mana_used": 108251001, + "proving_cost_per_mana_numerator": 1268393069, + "fee_asset_price_numerator": 1217566793 + }, + "header": { + "excess_mana": 1320095668, + "mana_used": 101607200, + "proving_cost_per_mana_numerator": 1217358203, + "fee_asset_price_numerator": 2217566793 + }, + "oracle_input": { + "proving_cost_modifier": -51034866, + "fee_asset_price_modifier": 1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10122500931, + "mana_base_fee_components_in_wei": { + "data_cost": 1, + "gas_cost": 33024605, + "proving_cost": 5484483444, + "congestion_cost": 20335791912, + "congestion_multiplier": 4685684140 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 10, + "gas_cost": 334291594, + "proving_cost": 55516688767, + "congestion_cost": 205849072561, + "congestion_multiplier": 4685684140 + } + } + }, + { + "l1_block_number": 20974214, + "l1_fees": { + "blob_fee": 243, + "base_fee": 9652277053 + }, + "parent_header": { + "excess_mana": 1320095668, + "mana_used": 101607200, + "proving_cost_per_mana_numerator": 1217358203, + "fee_asset_price_numerator": 2217566793 + }, + "header": { + "excess_mana": 1321702868, + "mana_used": 99783600, + "proving_cost_per_mana_numerator": 1135291698, + "fee_asset_price_numerator": 2179707139 + }, + "oracle_input": { + "proving_cost_modifier": -82066505, + "fee_asset_price_modifier": -37859654 + }, + "outputs": { + "fee_asset_price_at_execution": 10224233756, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31973167, + "proving_cost": 5481685160, + "congestion_cost": 20370229997, + "congestion_multiplier": 4694503502 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 326901133, + "proving_cost": 56046030452, + "congestion_cost": 208269993152, + "congestion_multiplier": 4694503502 + } + } + }, + { + "l1_block_number": 20974217, + "l1_fees": { + "blob_fee": 225, + "base_fee": 9865412617 + }, + "parent_header": { + "excess_mana": 1321702868, + "mana_used": 99783600, + "proving_cost_per_mana_numerator": 1135291698, + "fee_asset_price_numerator": 2179707139 + }, + "header": { + "excess_mana": 1321486468, + "mana_used": 98596813, + "proving_cost_per_mana_numerator": 1094238523, + "fee_asset_price_numerator": 1388857516 + }, + "oracle_input": { + "proving_cost_modifier": -41053175, + "fee_asset_price_modifier": -790849623 + }, + "outputs": { + "fee_asset_price_at_execution": 10220363630, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32679179, + "proving_cost": 5477188378, + "congestion_cost": 20349676832, + "congestion_multiplier": 4693315061 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 333993092, + "proving_cost": 55978856893, + "congestion_cost": 207981096976, + "congestion_multiplier": 4693315061 + } + } + }, + { + "l1_block_number": 20974220, + "l1_fees": { + "blob_fee": 253, + "base_fee": 9818833574 + }, + "parent_header": { + "excess_mana": 1321486468, + "mana_used": 98596813, + "proving_cost_per_mana_numerator": 1094238523, + "fee_asset_price_numerator": 1388857516 + }, + "header": { + "excess_mana": 1320083281, + "mana_used": 92508710, + "proving_cost_per_mana_numerator": 978809119, + "fee_asset_price_numerator": 1109991750 + }, + "oracle_input": { + "proving_cost_modifier": -115429404, + "fee_asset_price_modifier": -278865766 + }, + "outputs": { + "fee_asset_price_at_execution": 10139854694, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32524886, + "proving_cost": 5474940279, + "congestion_cost": 20298403009, + "congestion_multiplier": 4685616232 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 329797617, + "proving_cost": 55515098887, + "congestion_cost": 205822857031, + "congestion_multiplier": 4685616232 + } + } + }, + { + "l1_block_number": 20974223, + "l1_fees": { + "blob_fee": 192, + "base_fee": 9384598617 + }, + "parent_header": { + "excess_mana": 1320083281, + "mana_used": 92508710, + "proving_cost_per_mana_numerator": 978809119, + "fee_asset_price_numerator": 1109991750 + }, + "header": { + "excess_mana": 1312591991, + "mana_used": 106413231, + "proving_cost_per_mana_numerator": 816457518, + "fee_asset_price_numerator": 1325809432 + }, + "oracle_input": { + "proving_cost_modifier": -162351601, + "fee_asset_price_modifier": 215817682 + }, + "outputs": { + "fee_asset_price_at_execution": 10111617501, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31086482, + "proving_cost": 5468624234, + "congestion_cost": 20044944980, + "congestion_multiplier": 4644727153 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 314334615, + "proving_cost": 55296636510, + "congestion_cost": 202686816466, + "congestion_multiplier": 4644727153 + } + } + }, + { + "l1_block_number": 20974226, + "l1_fees": { + "blob_fee": 152, + "base_fee": 8938087949 + }, + "parent_header": { + "excess_mana": 1312591991, + "mana_used": 106413231, + "proving_cost_per_mana_numerator": 816457518, + "fee_asset_price_numerator": 1325809432 + }, + "header": { + "excess_mana": 1319005222, + "mana_used": 99107098, + "proving_cost_per_mana_numerator": 745722018, + "fee_asset_price_numerator": 1445651906 + }, + "oracle_input": { + "proving_cost_modifier": -70735500, + "fee_asset_price_modifier": 119842474 + }, + "outputs": { + "fee_asset_price_at_execution": 10133463725, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29607416, + "proving_cost": 5459753039, + "congestion_cost": 20199253758, + "congestion_multiplier": 4679709854 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 300025676, + "proving_cost": 55326209368, + "congestion_cost": 204688405228, + "congestion_multiplier": 4679709854 + } + } + }, + { + "l1_block_number": 20974229, + "l1_fees": { + "blob_fee": 185, + "base_fee": 9200504098 + }, + "parent_header": { + "excess_mana": 1319005222, + "mana_used": 99107098, + "proving_cost_per_mana_numerator": 745722018, + "fee_asset_price_numerator": 1445651906 + }, + "header": { + "excess_mana": 1318112320, + "mana_used": 103217114, + "proving_cost_per_mana_numerator": 746372879, + "fee_asset_price_numerator": 1519902006 + }, + "oracle_input": { + "proving_cost_modifier": 650861, + "fee_asset_price_modifier": 74250100 + }, + "outputs": { + "fee_asset_price_at_execution": 10145615199, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30476669, + "proving_cost": 5455892420, + "congestion_cost": 20161438249, + "congestion_multiplier": 4674823535 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 309204556, + "proving_cost": 55353385060, + "congestion_cost": 204550194332, + "congestion_multiplier": 4674823535 + } + } + }, + { + "l1_block_number": 20974232, + "l1_fees": { + "blob_fee": 140, + "base_fee": 9021763235 + }, + "parent_header": { + "excess_mana": 1318112320, + "mana_used": 103217114, + "proving_cost_per_mana_numerator": 746372879, + "fee_asset_price_numerator": 1519902006 + }, + "header": { + "excess_mana": 1321329434, + "mana_used": 84219796, + "proving_cost_per_mana_numerator": 788129718, + "fee_asset_price_numerator": 1463242432 + }, + "oracle_input": { + "proving_cost_modifier": 41756839, + "fee_asset_price_modifier": -56659574 + }, + "outputs": { + "fee_asset_price_at_execution": 10153151125, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29884590, + "proving_cost": 5455927931, + "congestion_cost": 20256104011, + "congestion_multiplier": 4692452838 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 303422758, + "proving_cost": 55394860810, + "congestion_cost": 205663285227, + "congestion_multiplier": 4692452838 + } + } + }, + { + "l1_block_number": 20974235, + "l1_fees": { + "blob_fee": 140, + "base_fee": 9164923160 + }, + "parent_header": { + "excess_mana": 1321329434, + "mana_used": 84219796, + "proving_cost_per_mana_numerator": 788129718, + "fee_asset_price_numerator": 1463242432 + }, + "header": { + "excess_mana": 1305549230, + "mana_used": 98726224, + "proving_cost_per_mana_numerator": 891349908, + "fee_asset_price_numerator": 1143970606 + }, + "oracle_input": { + "proving_cost_modifier": 103220190, + "fee_asset_price_modifier": -319271826 + }, + "outputs": { + "fee_asset_price_at_execution": 10147400023, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30358807, + "proving_cost": 5458206630, + "congestion_cost": 19795124387, + "congestion_multiplier": 4606611712 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 308062958, + "proving_cost": 55386606082, + "congestion_cost": 200869045659, + "congestion_multiplier": 4606611712 + } + } + }, + { + "l1_block_number": 20974238, + "l1_fees": { + "blob_fee": 106, + "base_fee": 8939418809 + }, + "parent_header": { + "excess_mana": 1305549230, + "mana_used": 98726224, + "proving_cost_per_mana_numerator": 891349908, + "fee_asset_price_numerator": 1143970606 + }, + "header": { + "excess_mana": 1304275454, + "mana_used": 114376447, + "proving_cost_per_mana_numerator": 917752670, + "fee_asset_price_numerator": 1702129583 + }, + "oracle_input": { + "proving_cost_modifier": 26402762, + "fee_asset_price_modifier": 558158977 + }, + "outputs": { + "fee_asset_price_at_execution": 10115053897, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29611824, + "proving_cost": 5463843510, + "congestion_cost": 19775074128, + "congestion_multiplier": 4599751509 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 299525195, + "proving_cost": 55267071588, + "congestion_cost": 200025940621, + "congestion_multiplier": 4599751509 + } + } + }, + { + "l1_block_number": 20974241, + "l1_fees": { + "blob_fee": 120, + "base_fee": 8940268760 + }, + "parent_header": { + "excess_mana": 1304275454, + "mana_used": 114376447, + "proving_cost_per_mana_numerator": 917752670, + "fee_asset_price_numerator": 1702129583 + }, + "header": { + "excess_mana": 1318651901, + "mana_used": 97571146, + "proving_cost_per_mana_numerator": 1019116089, + "fee_asset_price_numerator": 1481195032 + }, + "oracle_input": { + "proving_cost_modifier": 101363419, + "fee_asset_price_modifier": -220934551 + }, + "outputs": { + "fee_asset_price_at_execution": 10171669835, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29614640, + "proving_cost": 5465286306, + "congestion_cost": 20209013332, + "congestion_multiplier": 4677775729 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 301230340, + "proving_cost": 55591087858, + "congestion_cost": 205559411304, + "congestion_multiplier": 4677775729 + } + } + }, + { + "l1_block_number": 20974244, + "l1_fees": { + "blob_fee": 106, + "base_fee": 9460271090 + }, + "parent_header": { + "excess_mana": 1318651901, + "mana_used": 97571146, + "proving_cost_per_mana_numerator": 1019116089, + "fee_asset_price_numerator": 1481195032 + }, + "header": { + "excess_mana": 1316223047, + "mana_used": 32027503, + "proving_cost_per_mana_numerator": 1187087490, + "fee_asset_price_numerator": 1394617026 + }, + "oracle_input": { + "proving_cost_modifier": 167971401, + "fee_asset_price_modifier": -86578006 + }, + "outputs": { + "fee_asset_price_at_execution": 10149221908, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31337147, + "proving_cost": 5470828915, + "congestion_cost": 20162695715, + "congestion_multiplier": 4664501487 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 318047658, + "proving_cost": 55524656679, + "congestion_cost": 204635673075, + "congestion_multiplier": 4664501487 + } + } + }, + { + "l1_block_number": 20974247, + "l1_fees": { + "blob_fee": 102, + "base_fee": 9031372745 + }, + "parent_header": { + "excess_mana": 1316223047, + "mana_used": 32027503, + "proving_cost_per_mana_numerator": 1187087490, + "fee_asset_price_numerator": 1394617026 + }, + "header": { + "excess_mana": 1248250550, + "mana_used": 145636650, + "proving_cost_per_mana_numerator": 1106794821, + "fee_asset_price_numerator": 394617026 + }, + "oracle_input": { + "proving_cost_modifier": -80292669, + "fee_asset_price_modifier": -1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10140438717, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29916422, + "proving_cost": 5480026065, + "congestion_cost": 18226400425, + "congestion_multiplier": 4307911193 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 303365643, + "proving_cost": 55569868479, + "congestion_cost": 184823696541, + "congestion_multiplier": 4307911193 + } + } + }, + { + "l1_block_number": 20974250, + "l1_fees": { + "blob_fee": 95, + "base_fee": 9218102281 + }, + "parent_header": { + "excess_mana": 1248250550, + "mana_used": 145636650, + "proving_cost_per_mana_numerator": 1106794821, + "fee_asset_price_numerator": 394617026 + }, + "header": { + "excess_mana": 1293887200, + "mana_used": 111223594, + "proving_cost_per_mana_numerator": 1143972617, + "fee_asset_price_numerator": 893140627 + }, + "oracle_input": { + "proving_cost_modifier": 37177796, + "fee_asset_price_modifier": 498523601 + }, + "outputs": { + "fee_asset_price_at_execution": 10039539666, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30534963, + "proving_cost": 5475627772, + "congestion_cost": 19514850155, + "congestion_multiplier": 4544183326 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 306556972, + "proving_cost": 54972782213, + "congestion_cost": 195920112207, + "congestion_multiplier": 4544183326 + } + } + }, + { + "l1_block_number": 20974253, + "l1_fees": { + "blob_fee": 84, + "base_fee": 8858491309 + }, + "parent_header": { + "excess_mana": 1293887200, + "mana_used": 111223594, + "proving_cost_per_mana_numerator": 1143972617, + "fee_asset_price_numerator": 893140627 + }, + "header": { + "excess_mana": 1305110794, + "mana_used": 92953174, + "proving_cost_per_mana_numerator": 1132317302, + "fee_asset_price_numerator": 1632530897 + }, + "oracle_input": { + "proving_cost_modifier": -11655315, + "fee_asset_price_modifier": 739390270 + }, + "outputs": { + "fee_asset_price_at_execution": 10089714102, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29343752, + "proving_cost": 5477663868, + "congestion_cost": 19848628161, + "congestion_multiplier": 4604249264 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 296070068, + "proving_cost": 55268062374, + "congestion_cost": 200266983461, + "congestion_multiplier": 4604249264 + } + } + }, + { + "l1_block_number": 20974256, + "l1_fees": { + "blob_fee": 95, + "base_fee": 9136766129 + }, + "parent_header": { + "excess_mana": 1305110794, + "mana_used": 92953174, + "proving_cost_per_mana_numerator": 1132317302, + "fee_asset_price_numerator": 1632530897 + }, + "header": { + "excess_mana": 1298063968, + "mana_used": 107189994, + "proving_cost_per_mana_numerator": 1165670304, + "fee_asset_price_numerator": 2616929052 + }, + "oracle_input": { + "proving_cost_modifier": 33353002, + "fee_asset_price_modifier": 984398155 + }, + "outputs": { + "fee_asset_price_at_execution": 10164592949, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30265537, + "proving_cost": 5477025467, + "congestion_cost": 19641446460, + "congestion_multiplier": 4566444273 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 307636863, + "proving_cost": 55671734443, + "congestion_cost": 199647308195, + "congestion_multiplier": 4566444273 + } + } + }, + { + "l1_block_number": 20974259, + "l1_fees": { + "blob_fee": 66, + "base_fee": 8691734272 + }, + "parent_header": { + "excess_mana": 1298063968, + "mana_used": 107189994, + "proving_cost_per_mana_numerator": 1165670304, + "fee_asset_price_numerator": 2616929052 + }, + "header": { + "excess_mana": 1305253962, + "mana_used": 112260026, + "proving_cost_per_mana_numerator": 1055123064, + "fee_asset_price_numerator": 1699841887 + }, + "oracle_input": { + "proving_cost_modifier": -110547240, + "fee_asset_price_modifier": -917087165 + }, + "outputs": { + "fee_asset_price_at_execution": 10265147129, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 28791369, + "proving_cost": 5478852524, + "congestion_cost": 19855169526, + "congestion_multiplier": 4605020570 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 295547638, + "proving_cost": 56241227256, + "congestion_cost": 203816236455, + "congestion_multiplier": 4605020570 + } + } + }, + { + "l1_block_number": 20974262, + "l1_fees": { + "blob_fee": 69, + "base_fee": 8321749796 + }, + "parent_header": { + "excess_mana": 1305253962, + "mana_used": 112260026, + "proving_cost_per_mana_numerator": 1055123064, + "fee_asset_price_numerator": 1699841887 + }, + "header": { + "excess_mana": 1317513988, + "mana_used": 109487908, + "proving_cost_per_mana_numerator": 1052148096, + "fee_asset_price_numerator": 1967593911 + }, + "oracle_input": { + "proving_cost_modifier": -2974968, + "fee_asset_price_modifier": 267752024 + }, + "outputs": { + "fee_asset_price_at_execution": 10171437140, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 27565796, + "proving_cost": 5472799150, + "congestion_cost": 20194876347, + "congestion_multiplier": 4671552078 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 280383761, + "proving_cost": 55666232534, + "congestion_cost": 205410915313, + "congestion_multiplier": 4671552078 + } + } + }, + { + "l1_block_number": 20974265, + "l1_fees": { + "blob_fee": 57, + "base_fee": 9442998411 + }, + "parent_header": { + "excess_mana": 1317513988, + "mana_used": 109487908, + "proving_cost_per_mana_numerator": 1052148096, + "fee_asset_price_numerator": 1967593911 + }, + "header": { + "excess_mana": 1327001896, + "mana_used": 114634510, + "proving_cost_per_mana_numerator": 960116821, + "fee_asset_price_numerator": 2366369325 + }, + "oracle_input": { + "proving_cost_modifier": -92031275, + "fee_asset_price_modifier": 398775414 + }, + "outputs": { + "fee_asset_price_at_execution": 10198707862, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31279932, + "proving_cost": 5472636338, + "congestion_cost": 20494928561, + "congestion_multiplier": 4723699191 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 319014888, + "proving_cost": 55813819246, + "congestion_cost": 209021789046, + "congestion_multiplier": 4723699191 + } + } + }, + { + "l1_block_number": 20974268, + "l1_fees": { + "blob_fee": 64, + "base_fee": 9012000240 + }, + "parent_header": { + "excess_mana": 1327001896, + "mana_used": 114634510, + "proving_cost_per_mana_numerator": 960116821, + "fee_asset_price_numerator": 2366369325 + }, + "header": { + "excess_mana": 1341636406, + "mana_used": 89366688, + "proving_cost_per_mana_numerator": 925777547, + "fee_asset_price_numerator": 2157703337 + }, + "oracle_input": { + "proving_cost_modifier": -34339274, + "fee_asset_price_modifier": -208665988 + }, + "outputs": { + "fee_asset_price_at_execution": 10239459000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29852250, + "proving_cost": 5467602118, + "congestion_cost": 20919334213, + "congestion_multiplier": 4805276554 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 305670889, + "proving_cost": 55985287715, + "congestion_cost": 214202664981, + "congestion_multiplier": 4805276554 + } + } + }, + { + "l1_block_number": 20974271, + "l1_fees": { + "blob_fee": 59, + "base_fee": 9481407782 + }, + "parent_header": { + "excess_mana": 1341636406, + "mana_used": 89366688, + "proving_cost_per_mana_numerator": 925777547, + "fee_asset_price_numerator": 2157703337 + }, + "header": { + "excess_mana": 1331003094, + "mana_used": 89635246, + "proving_cost_per_mana_numerator": 923560611, + "fee_asset_price_numerator": 1942813050 + }, + "oracle_input": { + "proving_cost_modifier": -2216936, + "fee_asset_price_modifier": -214890287 + }, + "outputs": { + "fee_asset_price_at_execution": 10218115008, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31407163, + "proving_cost": 5465724906, + "congestion_cost": 20591512231, + "congestion_multiplier": 4745864566 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 320922003, + "proving_cost": 55849405691, + "congestion_cost": 210406440164, + "congestion_multiplier": 4745864566 + } + } + }, + { + "l1_block_number": 20974274, + "l1_fees": { + "blob_fee": 54, + "base_fee": 9203478287 + }, + "parent_header": { + "excess_mana": 1331003094, + "mana_used": 89635246, + "proving_cost_per_mana_numerator": 923560611, + "fee_asset_price_numerator": 1942813050 + }, + "header": { + "excess_mana": 1320638340, + "mana_used": 91836527, + "proving_cost_per_mana_numerator": 1042882656, + "fee_asset_price_numerator": 2648789941 + }, + "oracle_input": { + "proving_cost_modifier": 119322045, + "fee_asset_price_modifier": 705976891 + }, + "outputs": { + "fee_asset_price_at_execution": 10196180847, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30486521, + "proving_cost": 5465603735, + "congestion_cost": 20273209097, + "congestion_multiplier": 4688660148 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 310846081, + "proving_cost": 55728284120, + "congestion_cost": 206709306302, + "congestion_multiplier": 4688660148 + } + } + }, + { + "l1_block_number": 20974277, + "l1_fees": { + "blob_fee": 43, + "base_fee": 9064503000 + }, + "parent_header": { + "excess_mana": 1320638340, + "mana_used": 91836527, + "proving_cost_per_mana_numerator": 1042882656, + "fee_asset_price_numerator": 2648789941 + }, + "header": { + "excess_mana": 1312474867, + "mana_used": 111243703, + "proving_cost_per_mana_numerator": 1078349352, + "fee_asset_price_numerator": 3011021132 + }, + "oracle_input": { + "proving_cost_modifier": 35466696, + "fee_asset_price_modifier": 362231191 + }, + "outputs": { + "fee_asset_price_at_execution": 10268418217, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30026166, + "proving_cost": 5472129298, + "congestion_cost": 20050353589, + "congestion_multiplier": 4644090706 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 308321229, + "proving_cost": 56190112169, + "congestion_cost": 205885416050, + "congestion_multiplier": 4644090706 + } + } + }, + { + "l1_block_number": 20974280, + "l1_fees": { + "blob_fee": 50, + "base_fee": 9027090063 + }, + "parent_header": { + "excess_mana": 1312474867, + "mana_used": 111243703, + "proving_cost_per_mana_numerator": 1078349352, + "fee_asset_price_numerator": 3011021132 + }, + "header": { + "excess_mana": 1323718570, + "mana_used": 114041429, + "proving_cost_per_mana_numerator": 1072397891, + "fee_asset_price_numerator": 3131769371 + }, + "oracle_input": { + "proving_cost_modifier": -5951461, + "fee_asset_price_modifier": 120748239 + }, + "outputs": { + "fee_asset_price_at_execution": 10305681079, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29902235, + "proving_cost": 5474070426, + "congestion_cost": 20395454769, + "congestion_multiplier": 4705587950 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 308162897, + "proving_cost": 56414024014, + "congestion_cost": 210189052310, + "congestion_multiplier": 4705587950 + } + } + }, + { + "l1_block_number": 20974283, + "l1_fees": { + "blob_fee": 38, + "base_fee": 9084972090 + }, + "parent_header": { + "excess_mana": 1323718570, + "mana_used": 114041429, + "proving_cost_per_mana_numerator": 1072397891, + "fee_asset_price_numerator": 3131769371 + }, + "header": { + "excess_mana": 1337759999, + "mana_used": 78419505, + "proving_cost_per_mana_numerator": 936551251, + "fee_asset_price_numerator": 2673481901 + }, + "oracle_input": { + "proving_cost_modifier": -135846640, + "fee_asset_price_modifier": -458287470 + }, + "outputs": { + "fee_asset_price_at_execution": 10318132524, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30093970, + "proving_cost": 5473744648, + "congestion_cost": 20823949908, + "congestion_multiplier": 4783532068 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 310513570, + "proving_cost": 56478822680, + "congestion_cost": 214864274823, + "congestion_multiplier": 4783532068 + } + } + }, + { + "l1_block_number": 20974286, + "l1_fees": { + "blob_fee": 35, + "base_fee": 8666650959 + }, + "parent_header": { + "excess_mana": 1337759999, + "mana_used": 78419505, + "proving_cost_per_mana_numerator": 936551251, + "fee_asset_price_numerator": 2673481901 + }, + "header": { + "excess_mana": 1316179504, + "mana_used": 103490229, + "proving_cost_per_mana_numerator": 998373423, + "fee_asset_price_numerator": 2663921959 + }, + "oracle_input": { + "proving_cost_modifier": 61822172, + "fee_asset_price_modifier": -9559942 + }, + "outputs": { + "fee_asset_price_at_execution": 10270954004, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 28708281, + "proving_cost": 5466313799, + "congestion_cost": 20135210806, + "congestion_multiplier": 4664263858 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 294861433, + "proving_cost": 56144257600, + "congestion_cost": 206807824049, + "congestion_multiplier": 4664263858 + } + } + }, + { + "l1_block_number": 20974289, + "l1_fees": { + "blob_fee": 38, + "base_fee": 8614468929 + }, + "parent_header": { + "excess_mana": 1316179504, + "mana_used": 103490229, + "proving_cost_per_mana_numerator": 998373423, + "fee_asset_price_numerator": 2663921959 + }, + "header": { + "excess_mana": 1319669733, + "mana_used": 98929763, + "proving_cost_per_mana_numerator": 1036853456, + "fee_asset_price_numerator": 2157225896 + }, + "oracle_input": { + "proving_cost_modifier": 38480033, + "fee_asset_price_modifier": -506696063 + }, + "outputs": { + "fee_asset_price_at_execution": 10269972154, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 28535428, + "proving_cost": 5469694237, + "congestion_cost": 20251902251, + "congestion_multiplier": 4683349639 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 293058050, + "proving_cost": 56173607504, + "congestion_cost": 207986472183, + "congestion_multiplier": 4683349639 + } + } + }, + { + "l1_block_number": 20974292, + "l1_fees": { + "blob_fee": 38, + "base_fee": 8495067114 + }, + "parent_header": { + "excess_mana": 1319669733, + "mana_used": 98929763, + "proving_cost_per_mana_numerator": 1036853456, + "fee_asset_price_numerator": 2157225896 + }, + "header": { + "excess_mana": 1318599496, + "mana_used": 98480109, + "proving_cost_per_mana_numerator": 1068580002, + "fee_asset_price_numerator": 2099518642 + }, + "oracle_input": { + "proving_cost_modifier": 31726546, + "fee_asset_price_modifier": -57707254 + }, + "outputs": { + "fee_asset_price_at_execution": 10218066223, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 28139909, + "proving_cost": 5471799382, + "congestion_cost": 20225965830, + "congestion_multiplier": 4677488925 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 287535453, + "proving_cost": 55911208444, + "congestion_cost": 206670258275, + "congestion_multiplier": 4677488925 + } + } + }, + { + "l1_block_number": 20974295, + "l1_fees": { + "blob_fee": 35, + "base_fee": 7894600668 + }, + "parent_header": { + "excess_mana": 1318599496, + "mana_used": 98480109, + "proving_cost_per_mana_numerator": 1068580002, + "fee_asset_price_numerator": 2099518642 + }, + "header": { + "excess_mana": 1317079605, + "mana_used": 102788618, + "proving_cost_per_mana_numerator": 1126364944, + "fee_asset_price_numerator": 1862921956 + }, + "oracle_input": { + "proving_cost_modifier": 57784942, + "fee_asset_price_modifier": -236596686 + }, + "outputs": { + "fee_asset_price_at_execution": 10212171359, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 26150864, + "proving_cost": 5473535671, + "congestion_cost": 20179331409, + "congestion_multiplier": 4669178467 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 267057104, + "proving_cost": 55896684211, + "congestion_cost": 206074790258, + "congestion_multiplier": 4669178467 + } + } + }, + { + "l1_block_number": 20974298, + "l1_fees": { + "blob_fee": 29, + "base_fee": 9295653283 + }, + "parent_header": { + "excess_mana": 1317079605, + "mana_used": 102788618, + "proving_cost_per_mana_numerator": 1126364944, + "fee_asset_price_numerator": 1862921956 + }, + "header": { + "excess_mana": 1319868223, + "mana_used": 67256254, + "proving_cost_per_mana_numerator": 1099051796, + "fee_asset_price_numerator": 2373592741 + }, + "oracle_input": { + "proving_cost_modifier": -27313148, + "fee_asset_price_modifier": 510670785 + }, + "outputs": { + "fee_asset_price_at_execution": 10188038260, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30791851, + "proving_cost": 5476699464, + "congestion_cost": 20292006953, + "congestion_multiplier": 4684437395 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 313708556, + "proving_cost": 55796823677, + "congestion_cost": 206735743209, + "congestion_multiplier": 4684437395 + } + } + }, + { + "l1_block_number": 20974301, + "l1_fees": { + "blob_fee": 29, + "base_fee": 8488500665 + }, + "parent_header": { + "excess_mana": 1319868223, + "mana_used": 67256254, + "proving_cost_per_mana_numerator": 1099051796, + "fee_asset_price_numerator": 2373592741 + }, + "header": { + "excess_mana": 1287124477, + "mana_used": 139548221, + "proving_cost_per_mana_numerator": 1173630933, + "fee_asset_price_numerator": 2320168027 + }, + "oracle_input": { + "proving_cost_modifier": 74579137, + "fee_asset_price_modifier": -53424714 + }, + "outputs": { + "fee_asset_price_at_execution": 10240198666, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 28118158, + "proving_cost": 5475203809, + "congestion_cost": 19307688946, + "congestion_multiplier": 4508369865 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 287935524, + "proving_cost": 56067174740, + "congestion_cost": 197714570588, + "congestion_multiplier": 4508369865 + } + } + }, + { + "l1_block_number": 20974304, + "l1_fees": { + "blob_fee": 27, + "base_fee": 8290746738 + }, + "parent_header": { + "excess_mana": 1287124477, + "mana_used": 139548221, + "proving_cost_per_mana_numerator": 1173630933, + "fee_asset_price_numerator": 2320168027 + }, + "header": { + "excess_mana": 1326672698, + "mana_used": 93161620, + "proving_cost_per_mana_numerator": 1280813726, + "fee_asset_price_numerator": 2140695673 + }, + "oracle_input": { + "proving_cost_modifier": 107182793, + "fee_asset_price_modifier": -179472354 + }, + "outputs": { + "fee_asset_price_at_execution": 10234729330, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 27463098, + "proving_cost": 5479288692, + "congestion_cost": 20495470194, + "congestion_multiplier": 4721880153 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 281077374, + "proving_cost": 56079036683, + "congestion_cost": 209765589926, + "congestion_multiplier": 4721880153 + } + } + }, + { + "l1_block_number": 20974307, + "l1_fees": { + "blob_fee": 24, + "base_fee": 8892201701 + }, + "parent_header": { + "excess_mana": 1326672698, + "mana_used": 93161620, + "proving_cost_per_mana_numerator": 1280813726, + "fee_asset_price_numerator": 2140695673 + }, + "header": { + "excess_mana": 1319834318, + "mana_used": 87306878, + "proving_cost_per_mana_numerator": 1345813509, + "fee_asset_price_numerator": 1808374966 + }, + "oracle_input": { + "proving_cost_modifier": 64999783, + "fee_asset_price_modifier": -332320707 + }, + "outputs": { + "fee_asset_price_at_execution": 10216377293, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29455418, + "proving_cost": 5485164695, + "congestion_cost": 20317247825, + "congestion_multiplier": 4684251573 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 300927663, + "proving_cost": 56038512038, + "congestion_cost": 207568669335, + "congestion_multiplier": 4684251573 + } + } + }, + { + "l1_block_number": 20974310, + "l1_fees": { + "blob_fee": 23, + "base_fee": 8265977323 + }, + "parent_header": { + "excess_mana": 1319834318, + "mana_used": 87306878, + "proving_cost_per_mana_numerator": 1345813509, + "fee_asset_price_numerator": 1808374966 + }, + "header": { + "excess_mana": 1307141196, + "mana_used": 108136345, + "proving_cost_per_mana_numerator": 1474632566, + "fee_asset_price_numerator": 1328322599 + }, + "oracle_input": { + "proving_cost_modifier": 128819057, + "fee_asset_price_modifier": -480052367 + }, + "outputs": { + "fee_asset_price_at_execution": 10182482507, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 27381049, + "proving_cost": 5488731199, + "congestion_cost": 19941848910, + "congestion_multiplier": 4615199984 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 278807052, + "proving_cost": 55888909419, + "congestion_cost": 203057527683, + "congestion_multiplier": 4615199984 + } + } + }, + { + "l1_block_number": 20974313, + "l1_fees": { + "blob_fee": 22, + "base_fee": 9126618125 + }, + "parent_header": { + "excess_mana": 1307141196, + "mana_used": 108136345, + "proving_cost_per_mana_numerator": 1474632566, + "fee_asset_price_numerator": 1328322599 + }, + "header": { + "excess_mana": 1315277541, + "mana_used": 110084780, + "proving_cost_per_mana_numerator": 1508104099, + "fee_asset_price_numerator": 1315266421 + }, + "oracle_input": { + "proving_cost_modifier": 33471533, + "fee_asset_price_modifier": -13056178 + }, + "outputs": { + "fee_asset_price_at_execution": 10133718399, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30231922, + "proving_cost": 5495806287, + "congestion_cost": 20221676266, + "congestion_multiplier": 4659344272 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 306361784, + "proving_cost": 55692953287, + "congestion_cost": 204920772835, + "congestion_multiplier": 4659344272 + } + } + }, + { + "l1_block_number": 20974316, + "l1_fees": { + "blob_fee": 24, + "base_fee": 9501279935 + }, + "parent_header": { + "excess_mana": 1315277541, + "mana_used": 110084780, + "proving_cost_per_mana_numerator": 1508104099, + "fee_asset_price_numerator": 1315266421 + }, + "header": { + "excess_mana": 1325362321, + "mana_used": 99455031, + "proving_cost_per_mana_numerator": 1658641650, + "fee_asset_price_numerator": 906040862 + }, + "oracle_input": { + "proving_cost_modifier": 150537551, + "fee_asset_price_modifier": -409225559 + }, + "outputs": { + "fee_asset_price_at_execution": 10132395409, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31472989, + "proving_cost": 5497646126, + "congestion_cost": 20538722365, + "congestion_multiplier": 4714646391 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 318896769, + "proving_cost": 55704324367, + "congestion_cost": 208106456197, + "congestion_multiplier": 4714646391 + } + } + }, + { + "l1_block_number": 20974319, + "l1_fees": { + "blob_fee": 24, + "base_fee": 10745149155 + }, + "parent_header": { + "excess_mana": 1325362321, + "mana_used": 99455031, + "proving_cost_per_mana_numerator": 1658641650, + "fee_asset_price_numerator": 906040862 + }, + "header": { + "excess_mana": 1324817352, + "mana_used": 105869692, + "proving_cost_per_mana_numerator": 1757611722, + "fee_asset_price_numerator": 1253906944 + }, + "oracle_input": { + "proving_cost_modifier": 98970072, + "fee_asset_price_modifier": 347866082 + }, + "outputs": { + "fee_asset_price_at_execution": 10091015783, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35593306, + "proving_cost": 5505928380, + "congestion_cost": 20568140344, + "congestion_multiplier": 4711641226 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 359172612, + "proving_cost": 55560410182, + "congestion_cost": 207553428838, + "congestion_multiplier": 4711641226 + } + } + }, + { + "l1_block_number": 20974322, + "l1_fees": { + "blob_fee": 26, + "base_fee": 10241684423 + }, + "parent_header": { + "excess_mana": 1324817352, + "mana_used": 105869692, + "proving_cost_per_mana_numerator": 1757611722, + "fee_asset_price_numerator": 1253906944 + }, + "header": { + "excess_mana": 1330687044, + "mana_used": 39552574, + "proving_cost_per_mana_numerator": 1660840076, + "fee_asset_price_numerator": 1440977437 + }, + "oracle_input": { + "proving_cost_modifier": -96771646, + "fee_asset_price_modifier": 187070493 + }, + "outputs": { + "fee_asset_price_at_execution": 10126180131, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33925579, + "proving_cost": 5511380299, + "congestion_cost": 20762235035, + "congestion_multiplier": 4744109972 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 343536524, + "proving_cost": 55809229678, + "congestion_cost": 210242131886, + "congestion_multiplier": 4744109972 + } + } + }, + { + "l1_block_number": 20974325, + "l1_fees": { + "blob_fee": 19, + "base_fee": 10099236170 + }, + "parent_header": { + "excess_mana": 1330687044, + "mana_used": 39552574, + "proving_cost_per_mana_numerator": 1660840076, + "fee_asset_price_numerator": 1440977437 + }, + "header": { + "excess_mana": 1270239618, + "mana_used": 128754870, + "proving_cost_per_mana_numerator": 1769688662, + "fee_asset_price_numerator": 1403976904 + }, + "oracle_input": { + "proving_cost_modifier": 108848586, + "fee_asset_price_modifier": -37000533 + }, + "outputs": { + "fee_asset_price_at_execution": 10145140956, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33453719, + "proving_cost": 5506049425, + "congestion_cost": 18946096267, + "congestion_multiplier": 4420179712 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 339392694, + "proving_cost": 55859647527, + "congestion_cost": 192210817194, + "congestion_multiplier": 4420179712 + } + } + }, + { + "l1_block_number": 20974328, + "l1_fees": { + "blob_fee": 24, + "base_fee": 10714018785 + }, + "parent_header": { + "excess_mana": 1270239618, + "mana_used": 128754870, + "proving_cost_per_mana_numerator": 1769688662, + "fee_asset_price_numerator": 1403976904 + }, + "header": { + "excess_mana": 1298994488, + "mana_used": 122069543, + "proving_cost_per_mana_numerator": 1630222122, + "fee_asset_price_numerator": 1855086357 + }, + "oracle_input": { + "proving_cost_modifier": -139466540, + "fee_asset_price_modifier": 451109453 + }, + "outputs": { + "fee_asset_price_at_execution": 10141387894, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35490187, + "proving_cost": 5512045945, + "congestion_cost": 19812573210, + "congestion_multiplier": 4571418507 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 359919752, + "proving_cost": 55899796017, + "congestion_cost": 200926990100, + "congestion_multiplier": 4571418507 + } + } + }, + { + "l1_block_number": 20974331, + "l1_fees": { + "blob_fee": 20, + "base_fee": 9990102695 + }, + "parent_header": { + "excess_mana": 1298994488, + "mana_used": 122069543, + "proving_cost_per_mana_numerator": 1630222122, + "fee_asset_price_numerator": 1855086357 + }, + "header": { + "excess_mana": 1321064031, + "mana_used": 101851803, + "proving_cost_per_mana_numerator": 1671509921, + "fee_asset_price_numerator": 1964747298 + }, + "oracle_input": { + "proving_cost_modifier": 41287799, + "fee_asset_price_modifier": 109660941 + }, + "outputs": { + "fee_asset_price_at_execution": 10187239997, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33092215, + "proving_cost": 5504363844, + "congestion_cost": 20438727925, + "congestion_multiplier": 4690995957 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 337118336, + "proving_cost": 56074275509, + "congestion_cost": 208214226605, + "congestion_multiplier": 4690995957 + } + } + }, + { + "l1_block_number": 20974334, + "l1_fees": { + "blob_fee": 22, + "base_fee": 9894921586 + }, + "parent_header": { + "excess_mana": 1321064031, + "mana_used": 101851803, + "proving_cost_per_mana_numerator": 1671509921, + "fee_asset_price_numerator": 1964747298 + }, + "header": { + "excess_mana": 1322915834, + "mana_used": 96372923, + "proving_cost_per_mana_numerator": 1556471872, + "fee_asset_price_numerator": 1480377822 + }, + "oracle_input": { + "proving_cost_modifier": -115038049, + "fee_asset_price_modifier": -484369476 + }, + "outputs": { + "fee_asset_price_at_execution": 10198417548, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32776927, + "proving_cost": 5506636943, + "congestion_cost": 20502315374, + "congestion_multiplier": 4701170531 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 334272787, + "proving_cost": 56158982829, + "congestion_cost": 209091172884, + "congestion_multiplier": 4701170531 + } + } + }, + { + "l1_block_number": 20974337, + "l1_fees": { + "blob_fee": 23, + "base_fee": 9960455736 + }, + "parent_header": { + "excess_mana": 1322915834, + "mana_used": 96372923, + "proving_cost_per_mana_numerator": 1556471872, + "fee_asset_price_numerator": 1480377822 + }, + "header": { + "excess_mana": 1319288757, + "mana_used": 109308423, + "proving_cost_per_mana_numerator": 1597101767, + "fee_asset_price_numerator": 1899533473 + }, + "oracle_input": { + "proving_cost_modifier": 40629895, + "fee_asset_price_modifier": 419155651 + }, + "outputs": { + "fee_asset_price_at_execution": 10149138968, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32994009, + "proving_cost": 5500305858, + "congestion_cost": 20369529517, + "congestion_multiplier": 4681262539 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 334860782, + "proving_cost": 55823368519, + "congestion_cost": 206733185780, + "congestion_multiplier": 4681262539 + } + } + }, + { + "l1_block_number": 20974340, + "l1_fees": { + "blob_fee": 22, + "base_fee": 9964721878 + }, + "parent_header": { + "excess_mana": 1319288757, + "mana_used": 109308423, + "proving_cost_per_mana_numerator": 1597101767, + "fee_asset_price_numerator": 1899533473 + }, + "header": { + "excess_mana": 1328597180, + "mana_used": 102019767, + "proving_cost_per_mana_numerator": 1557408475, + "fee_asset_price_numerator": 2190235844 + }, + "oracle_input": { + "proving_cost_modifier": -39693292, + "fee_asset_price_modifier": 290702371 + }, + "outputs": { + "fee_asset_price_at_execution": 10191768938, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33008141, + "proving_cost": 5502541081, + "congestion_cost": 20661571016, + "congestion_multiplier": 4732524125 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 336411346, + "proving_cost": 56080627269, + "congestion_cost": 210577957691, + "congestion_multiplier": 4732524125 + } + } + }, + { + "l1_block_number": 20974343, + "l1_fees": { + "blob_fee": 19, + "base_fee": 9815866122 + }, + "parent_header": { + "excess_mana": 1328597180, + "mana_used": 102019767, + "proving_cost_per_mana_numerator": 1557408475, + "fee_asset_price_numerator": 2190235844 + }, + "header": { + "excess_mana": 1330616947, + "mana_used": 91158650, + "proving_cost_per_mana_numerator": 1599926904, + "fee_asset_price_numerator": 2259250132 + }, + "oracle_input": { + "proving_cost_modifier": 42518429, + "fee_asset_price_modifier": 69014288 + }, + "outputs": { + "fee_asset_price_at_execution": 10221439758, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32515056, + "proving_cost": 5500357374, + "congestion_cost": 20713530191, + "congestion_multiplier": 4743720907 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 332350686, + "proving_cost": 56221571545, + "congestion_cost": 211722101022, + "congestion_multiplier": 4743720907 + } + } + }, + { + "l1_block_number": 20974346, + "l1_fees": { + "blob_fee": 17, + "base_fee": 9039417707 + }, + "parent_header": { + "excess_mana": 1330616947, + "mana_used": 91158650, + "proving_cost_per_mana_numerator": 1599926904, + "fee_asset_price_numerator": 2259250132 + }, + "header": { + "excess_mana": 1321775597, + "mana_used": 107408210, + "proving_cost_per_mana_numerator": 1470245111, + "fee_asset_price_numerator": 2095941984 + }, + "oracle_input": { + "proving_cost_modifier": -129681793, + "fee_asset_price_modifier": -163308148 + }, + "outputs": { + "fee_asset_price_at_execution": 10228496447, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29943071, + "proving_cost": 5502696537, + "congestion_cost": 20442566619, + "congestion_multiplier": 4694902988 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 306272595, + "proving_cost": 56284311977, + "congestion_cost": 209096720030, + "congestion_multiplier": 4694902988 + } + } + }, + { + "l1_block_number": 20974349, + "l1_fees": { + "blob_fee": 15, + "base_fee": 8475102127 + }, + "parent_header": { + "excess_mana": 1321775597, + "mana_used": 107408210, + "proving_cost_per_mana_numerator": 1470245111, + "fee_asset_price_numerator": 2095941984 + }, + "header": { + "excess_mana": 1329183807, + "mana_used": 98319714, + "proving_cost_per_mana_numerator": 1375804603, + "fee_asset_price_numerator": 1850876842 + }, + "oracle_input": { + "proving_cost_modifier": -94440508, + "fee_asset_price_modifier": -245065142 + }, + "outputs": { + "fee_asset_price_at_execution": 10211806111, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 28073775, + "proving_cost": 5495565167, + "congestion_cost": 20635063568, + "congestion_multiplier": 4735773425 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 286683947, + "proving_cost": 56119645955, + "congestion_cost": 210721268244, + "congestion_multiplier": 4735773425 + } + } + }, + { + "l1_block_number": 20974352, + "l1_fees": { + "blob_fee": 14, + "base_fee": 9315624609 + }, + "parent_header": { + "excess_mana": 1329183807, + "mana_used": 98319714, + "proving_cost_per_mana_numerator": 1375804603, + "fee_asset_price_numerator": 1850876842 + }, + "header": { + "excess_mana": 1327503521, + "mana_used": 79040235, + "proving_cost_per_mana_numerator": 1312310154, + "fee_asset_price_numerator": 1909017143 + }, + "oracle_input": { + "proving_cost_modifier": -63494449, + "fee_asset_price_modifier": 58140301 + }, + "outputs": { + "fee_asset_price_at_execution": 10186811173, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30858006, + "proving_cost": 5490377577, + "congestion_cost": 20574731732, + "congestion_multiplier": 4726472349 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 314344680, + "proving_cost": 55929439645, + "congestion_cost": 209590907089, + "congestion_multiplier": 4726472349 + } + } + }, + { + "l1_block_number": 20974355, + "l1_fees": { + "blob_fee": 12, + "base_fee": 9031807679 + }, + "parent_header": { + "excess_mana": 1327503521, + "mana_used": 79040235, + "proving_cost_per_mana_numerator": 1312310154, + "fee_asset_price_numerator": 1909017143 + }, + "header": { + "excess_mana": 1306543756, + "mana_used": 107770546, + "proving_cost_per_mana_numerator": 1372426141, + "fee_asset_price_numerator": 2236036991 + }, + "oracle_input": { + "proving_cost_modifier": 60115987, + "fee_asset_price_modifier": 327019848 + }, + "outputs": { + "fee_asset_price_at_execution": 10192735538, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29917862, + "proving_cost": 5486892598, + "congestion_cost": 19926581814, + "congestion_multiplier": 4611975064 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 304944855, + "proving_cost": 55926445176, + "congestion_cost": 203106378606, + "congestion_multiplier": 4611975064 + } + } + }, + { + "l1_block_number": 20974358, + "l1_fees": { + "blob_fee": 12, + "base_fee": 9209742295 + }, + "parent_header": { + "excess_mana": 1306543756, + "mana_used": 107770546, + "proving_cost_per_mana_numerator": 1372426141, + "fee_asset_price_numerator": 2236036991 + }, + "header": { + "excess_mana": 1314314302, + "mana_used": 108806778, + "proving_cost_per_mana_numerator": 1324351893, + "fee_asset_price_numerator": 1806378454 + }, + "oracle_input": { + "proving_cost_modifier": -48074248, + "fee_asset_price_modifier": -429658537 + }, + "outputs": { + "fee_asset_price_at_execution": 10226122367, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30507271, + "proving_cost": 5490192090, + "congestion_cost": 20173166539, + "congestion_multiplier": 4654096197 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 311971086, + "proving_cost": 56143376130, + "congestion_cost": 206293269557, + "congestion_multiplier": 4654096197 + } + } + }, + { + "l1_block_number": 20974361, + "l1_fees": { + "blob_fee": 9, + "base_fee": 8782605352 + }, + "parent_header": { + "excess_mana": 1314314302, + "mana_used": 108806778, + "proving_cost_per_mana_numerator": 1324351893, + "fee_asset_price_numerator": 1806378454 + }, + "header": { + "excess_mana": 1323121080, + "mana_used": 90226091, + "proving_cost_per_mana_numerator": 1264633275, + "fee_asset_price_numerator": 2350054816 + }, + "oracle_input": { + "proving_cost_modifier": -59718618, + "fee_asset_price_modifier": 543676362 + }, + "outputs": { + "fee_asset_price_at_execution": 10182279215, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29092380, + "proving_cost": 5487553355, + "congestion_cost": 20424275275, + "congestion_multiplier": 4702299596 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 296226736, + "proving_cost": 55875800467, + "congestion_cost": 207965673614, + "congestion_multiplier": 4702299596 + } + } + }, + { + "l1_block_number": 20974364, + "l1_fees": { + "blob_fee": 7, + "base_fee": 9499075723 + }, + "parent_header": { + "excess_mana": 1323121080, + "mana_used": 90226091, + "proving_cost_per_mana_numerator": 1264633275, + "fee_asset_price_numerator": 2350054816 + }, + "header": { + "excess_mana": 1313347171, + "mana_used": 111455713, + "proving_cost_per_mana_numerator": 1260495242, + "fee_asset_price_numerator": 2066832958 + }, + "oracle_input": { + "proving_cost_modifier": -4138033, + "fee_asset_price_modifier": -283221858 + }, + "outputs": { + "fee_asset_price_at_execution": 10237788619, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31465688, + "proving_cost": 5484277243, + "congestion_cost": 20126024081, + "congestion_multiplier": 4648832865 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 322139062, + "proving_cost": 56146871141, + "congestion_cost": 206045980282, + "congestion_multiplier": 4648832865 + } + } + }, + { + "l1_block_number": 20974367, + "l1_fees": { + "blob_fee": 8, + "base_fee": 9417033890 + }, + "parent_header": { + "excess_mana": 1313347171, + "mana_used": 111455713, + "proving_cost_per_mana_numerator": 1260495242, + "fee_asset_price_numerator": 2066832958 + }, + "header": { + "excess_mana": 1324802884, + "mana_used": 102257732, + "proving_cost_per_mana_numerator": 1259391999, + "fee_asset_price_numerator": 1704421437 + }, + "oracle_input": { + "proving_cost_modifier": -1103243, + "fee_asset_price_modifier": -362411521 + }, + "outputs": { + "fee_asset_price_at_execution": 10208833986, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31193924, + "proving_cost": 5484050306, + "congestion_cost": 20470167981, + "congestion_multiplier": 4711561470 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 318453591, + "proving_cost": 55985759144, + "congestion_cost": 208976546583, + "congestion_multiplier": 4711561470 + } + } + }, + { + "l1_block_number": 20974370, + "l1_fees": { + "blob_fee": 6, + "base_fee": 9309211929 + }, + "parent_header": { + "excess_mana": 1324802884, + "mana_used": 102257732, + "proving_cost_per_mana_numerator": 1259391999, + "fee_asset_price_numerator": 1704421437 + }, + "header": { + "excess_mana": 1327060616, + "mana_used": 98249684, + "proving_cost_per_mana_numerator": 1204937291, + "fee_asset_price_numerator": 1449652955 + }, + "oracle_input": { + "proving_cost_modifier": -54454708, + "fee_asset_price_modifier": -254768482 + }, + "outputs": { + "fee_asset_price_at_execution": 10171902957, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30836764, + "proving_cost": 5483989804, + "congestion_cost": 20537345011, + "congestion_multiplier": 4724023731 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 313668570, + "proving_cost": 55782612103, + "congestion_cost": 208903880446, + "congestion_multiplier": 4724023731 + } + } + }, + { + "l1_block_number": 20974373, + "l1_fees": { + "blob_fee": 6, + "base_fee": 9007719109 + }, + "parent_header": { + "excess_mana": 1327060616, + "mana_used": 98249684, + "proving_cost_per_mana_numerator": 1204937291, + "fee_asset_price_numerator": 1449652955 + }, + "header": { + "excess_mana": 1325310300, + "mana_used": 103778888, + "proving_cost_per_mana_numerator": 1187210311, + "fee_asset_price_numerator": 547655613 + }, + "oracle_input": { + "proving_cost_modifier": -17726980, + "fee_asset_price_modifier": -901997342 + }, + "outputs": { + "fee_asset_price_at_execution": 10146021138, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29838069, + "proving_cost": 5481004326, + "congestion_cost": 20469249499, + "congestion_multiplier": 4714359445 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 302737678, + "proving_cost": 55610385749, + "congestion_cost": 207681438095, + "congestion_multiplier": 4714359445 + } + } + }, + { + "l1_block_number": 20974376, + "l1_fees": { + "blob_fee": 6, + "base_fee": 8992739005 + }, + "parent_header": { + "excess_mana": 1325310300, + "mana_used": 103778888, + "proving_cost_per_mana_numerator": 1187210311, + "fee_asset_price_numerator": 547655613 + }, + "header": { + "excess_mana": 1329089188, + "mana_used": 102202562, + "proving_cost_per_mana_numerator": 1334620866, + "fee_asset_price_numerator": 390261417 + }, + "oracle_input": { + "proving_cost_modifier": 147410555, + "fee_asset_price_modifier": -157394196 + }, + "outputs": { + "fee_asset_price_at_execution": 10054915798, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29788447, + "proving_cost": 5480032796, + "congestion_cost": 20580555301, + "congestion_multiplier": 4735249184 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 299520326, + "proving_cost": 55101268334, + "congestion_cost": 206935750627, + "congestion_multiplier": 4735249184 + } + } + }, + { + "l1_block_number": 20974379, + "l1_fees": { + "blob_fee": 6, + "base_fee": 9042037019 + }, + "parent_header": { + "excess_mana": 1329089188, + "mana_used": 102202562, + "proving_cost_per_mana_numerator": 1334620866, + "fee_asset_price_numerator": 390261417 + }, + "header": { + "excess_mana": 1331291750, + "mana_used": 102177014, + "proving_cost_per_mana_numerator": 1416682604, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 82061738, + "fee_asset_price_modifier": -424317117 + }, + "outputs": { + "fee_asset_price_at_execution": 10039102392, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29951747, + "proving_cost": 5488116900, + "congestion_cost": 20678783723, + "congestion_multiplier": 4747467646 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 300688654, + "proving_cost": 55095767498, + "congestion_cost": 207596427137, + "congestion_multiplier": 4747467646 + } + } + }, + { + "l1_block_number": 20974382, + "l1_fees": { + "blob_fee": 7, + "base_fee": 8510788576 + }, + "parent_header": { + "excess_mana": 1331291750, + "mana_used": 102177014, + "proving_cost_per_mana_numerator": 1416682604, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1333468764, + "mana_used": 97887752, + "proving_cost_per_mana_numerator": 1423671361, + "fee_asset_price_numerator": 360076914 + }, + "oracle_input": { + "proving_cost_modifier": 6988757, + "fee_asset_price_modifier": 360076914 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 28191987, + "proving_cost": 5492622392, + "congestion_cost": 20755917728, + "congestion_multiplier": 4759575364 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 281919870, + "proving_cost": 54926223920, + "congestion_cost": 207559177280, + "congestion_multiplier": 4759575364 + } + } + }, + { + "l1_block_number": 20974385, + "l1_fees": { + "blob_fee": 5, + "base_fee": 9374725308 + }, + "parent_header": { + "excess_mana": 1333468764, + "mana_used": 97887752, + "proving_cost_per_mana_numerator": 1423671361, + "fee_asset_price_numerator": 360076914 + }, + "header": { + "excess_mana": 1331356516, + "mana_used": 97037409, + "proving_cost_per_mana_numerator": 1534145393, + "fee_asset_price_numerator": 952978592 + }, + "oracle_input": { + "proving_cost_modifier": 110474032, + "fee_asset_price_modifier": 592901678 + }, + "outputs": { + "fee_asset_price_at_execution": 10036072596, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31053777, + "proving_cost": 5493006272, + "congestion_cost": 20703223638, + "congestion_multiplier": 4747827405 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 311657960, + "proving_cost": 55128209716, + "congestion_cost": 207779055402, + "congestion_multiplier": 4747827405 + } + } + }, + { + "l1_block_number": 20974388, + "l1_fees": { + "blob_fee": 5, + "base_fee": 8322579740 + }, + "parent_header": { + "excess_mana": 1331356516, + "mana_used": 97037409, + "proving_cost_per_mana_numerator": 1534145393, + "fee_asset_price_numerator": 952978592 + }, + "header": { + "excess_mana": 1328393925, + "mana_used": 94346326, + "proving_cost_per_mana_numerator": 1589826455, + "fee_asset_price_numerator": 1952978592 + }, + "oracle_input": { + "proving_cost_modifier": 55681062, + "fee_asset_price_modifier": 1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10095753389, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 27568545, + "proving_cost": 5499077970, + "congestion_cost": 20622122312, + "congestion_multiplier": 4731398825 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 278325231, + "proving_cost": 55517335052, + "congestion_cost": 208195861219, + "congestion_multiplier": 4731398825 + } + } + }, + { + "l1_block_number": 20974391, + "l1_fees": { + "blob_fee": 4, + "base_fee": 8799523084 + }, + "parent_header": { + "excess_mana": 1328393925, + "mana_used": 94346326, + "proving_cost_per_mana_numerator": 1589826455, + "fee_asset_price_numerator": 1952978592 + }, + "header": { + "excess_mana": 1322740251, + "mana_used": 111007432, + "proving_cost_per_mana_numerator": 1527438719, + "fee_asset_price_numerator": 2099675722 + }, + "oracle_input": { + "proving_cost_modifier": -62387736, + "fee_asset_price_modifier": 146697130 + }, + "outputs": { + "fee_asset_price_at_execution": 10197217397, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29148420, + "proving_cost": 5502140768, + "congestion_cost": 20466903129, + "congestion_multiplier": 4700204859 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 297232775, + "proving_cost": 56106525560, + "congestion_cost": 208705460649, + "congestion_multiplier": 4700204859 + } + } + }, + { + "l1_block_number": 20974394, + "l1_fees": { + "blob_fee": 4, + "base_fee": 8519958823 + }, + "parent_header": { + "excess_mana": 1322740251, + "mana_used": 111007432, + "proving_cost_per_mana_numerator": 1527438719, + "fee_asset_price_numerator": 2099675722 + }, + "header": { + "excess_mana": 1333747683, + "mana_used": 91076828, + "proving_cost_per_mana_numerator": 1499445967, + "fee_asset_price_numerator": 1358497570 + }, + "oracle_input": { + "proving_cost_modifier": -27992752, + "fee_asset_price_modifier": -741178152 + }, + "outputs": { + "fee_asset_price_at_execution": 10212187400, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 28222363, + "proving_cost": 5498709178, + "congestion_cost": 20787501587, + "congestion_multiplier": 4761128835 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 288212059, + "proving_cost": 56153848583, + "congestion_cost": 212285861784, + "congestion_multiplier": 4761128835 + } + } + }, + { + "l1_block_number": 20974397, + "l1_fees": { + "blob_fee": 4, + "base_fee": 9023488741 + }, + "parent_header": { + "excess_mana": 1333747683, + "mana_used": 91076828, + "proving_cost_per_mana_numerator": 1499445967, + "fee_asset_price_numerator": 1358497570 + }, + "header": { + "excess_mana": 1324824511, + "mana_used": 102348677, + "proving_cost_per_mana_numerator": 1684170181, + "fee_asset_price_numerator": 1669934689 + }, + "oracle_input": { + "proving_cost_modifier": 184724214, + "fee_asset_price_modifier": 311437119 + }, + "outputs": { + "fee_asset_price_at_execution": 10136776707, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29890306, + "proving_cost": 5497170153, + "congestion_cost": 20514683583, + "congestion_multiplier": 4711680691 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 302991357, + "proving_cost": 55723586361, + "congestion_cost": 207952766695, + "congestion_multiplier": 4711680691 + } + } + }, + { + "l1_block_number": 20974400, + "l1_fees": { + "blob_fee": 4, + "base_fee": 8545578463 + }, + "parent_header": { + "excess_mana": 1324824511, + "mana_used": 102348677, + "proving_cost_per_mana_numerator": 1684170181, + "fee_asset_price_numerator": 1669934689 + }, + "header": { + "excess_mana": 1327173188, + "mana_used": 92938693, + "proving_cost_per_mana_numerator": 1871615142, + "fee_asset_price_numerator": 2669934689 + }, + "oracle_input": { + "proving_cost_modifier": 187444961, + "fee_asset_price_modifier": 1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10168395603, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 28307228, + "proving_cost": 5507334142, + "congestion_cost": 20618304320, + "congestion_multiplier": 4724645970 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 287839092, + "proving_cost": 56000752273, + "congestion_cost": 209655074988, + "congestion_multiplier": 4724645970 + } + } + }, + { + "l1_block_number": 20974403, + "l1_fees": { + "blob_fee": 3, + "base_fee": 8672936965 + }, + "parent_header": { + "excess_mana": 1327173188, + "mana_used": 92938693, + "proving_cost_per_mana_numerator": 1871615142, + "fee_asset_price_numerator": 2669934689 + }, + "header": { + "excess_mana": 1320111881, + "mana_used": 100219596, + "proving_cost_per_mana_numerator": 1771461342, + "fee_asset_price_numerator": 2497321334 + }, + "oracle_input": { + "proving_cost_modifier": -100153800, + "fee_asset_price_modifier": -172613355 + }, + "outputs": { + "fee_asset_price_at_execution": 10270589678, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 28729103, + "proving_cost": 5517667044, + "congestion_cost": 20442757299, + "congestion_multiplier": 4685773024 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 295064828, + "proving_cost": 56669694188, + "congestion_cost": 209959172104, + "congestion_multiplier": 4685773024 + } + } + }, + { + "l1_block_number": 20974406, + "l1_fees": { + "blob_fee": 4, + "base_fee": 9479498490 + }, + "parent_header": { + "excess_mana": 1320111881, + "mana_used": 100219596, + "proving_cost_per_mana_numerator": 1771461342, + "fee_asset_price_numerator": 2497321334 + }, + "header": { + "excess_mana": 1320331477, + "mana_used": 87249250, + "proving_cost_per_mana_numerator": 1566676181, + "fee_asset_price_numerator": 3051306617 + }, + "oracle_input": { + "proving_cost_modifier": -204785161, + "fee_asset_price_modifier": 553985283 + }, + "outputs": { + "fee_asset_price_at_execution": 10252876561, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31400838, + "proving_cost": 5512143657, + "congestion_cost": 20438921506, + "congestion_multiplier": 4686977082 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 321948915, + "proving_cost": 56515328501, + "congestion_cost": 209557739240, + "congestion_multiplier": 4686977082 + } + } + }, + { + "l1_block_number": 20974409, + "l1_fees": { + "blob_fee": 3, + "base_fee": 9875043082 + }, + "parent_header": { + "excess_mana": 1320331477, + "mana_used": 87249250, + "proving_cost_per_mana_numerator": 1566676181, + "fee_asset_price_numerator": 3051306617 + }, + "header": { + "excess_mana": 1307580727, + "mana_used": 115675532, + "proving_cost_per_mana_numerator": 1629461953, + "fee_asset_price_numerator": 2394692137 + }, + "oracle_input": { + "proving_cost_modifier": 62785772, + "fee_asset_price_modifier": -656614480 + }, + "outputs": { + "fee_asset_price_at_execution": 10309833609, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32711080, + "proving_cost": 5500867155, + "congestion_cost": 20018128567, + "congestion_multiplier": 4617573967 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 337245791, + "proving_cost": 56713025073, + "congestion_cost": 206383574689, + "congestion_multiplier": 4617573967 + } + } + }, + { + "l1_block_number": 20974412, + "l1_fees": { + "blob_fee": 3, + "base_fee": 10014800521 + }, + "parent_header": { + "excess_mana": 1307580727, + "mana_used": 115675532, + "proving_cost_per_mana_numerator": 1629461953, + "fee_asset_price_numerator": 2394692137 + }, + "header": { + "excess_mana": 1323256259, + "mana_used": 105099465, + "proving_cost_per_mana_numerator": 1668234004, + "fee_asset_price_numerator": 2403049174 + }, + "oracle_input": { + "proving_cost_modifier": 38772051, + "fee_asset_price_modifier": 8357037 + }, + "outputs": { + "fee_asset_price_at_execution": 10242359514, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33174026, + "proving_cost": 5504322001, + "congestion_cost": 20505587938, + "congestion_multiplier": 4703043368 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 339780300, + "proving_cost": 56377244815, + "congestion_cost": 210025603706, + "congestion_multiplier": 4703043368 + } + } + }, + { + "l1_block_number": 20974415, + "l1_fees": { + "blob_fee": 2, + "base_fee": 9730168250 + }, + "parent_header": { + "excess_mana": 1323256259, + "mana_used": 105099465, + "proving_cost_per_mana_numerator": 1668234004, + "fee_asset_price_numerator": 2403049174 + }, + "header": { + "excess_mana": 1328355724, + "mana_used": 103057264, + "proving_cost_per_mana_numerator": 1662305093, + "fee_asset_price_numerator": 2860952379 + }, + "oracle_input": { + "proving_cost_modifier": -5928911, + "fee_asset_price_modifier": 457903205 + }, + "outputs": { + "fee_asset_price_at_execution": 10243215507, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32231182, + "proving_cost": 5506456554, + "congestion_cost": 20665881666, + "congestion_multiplier": 4731187359 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 330150943, + "proving_cost": 56403821162, + "congestion_cost": 211685079546, + "congestion_multiplier": 4731187359 + } + } + }, + { + "l1_block_number": 20974418, + "l1_fees": { + "blob_fee": 2, + "base_fee": 9791395571 + }, + "parent_header": { + "excess_mana": 1328355724, + "mana_used": 103057264, + "proving_cost_per_mana_numerator": 1662305093, + "fee_asset_price_numerator": 2860952379 + }, + "header": { + "excess_mana": 1331412988, + "mana_used": 91900546, + "proving_cost_per_mana_numerator": 1810563151, + "fee_asset_price_numerator": 1860952379 + }, + "oracle_input": { + "proving_cost_modifier": 148258058, + "fee_asset_price_modifier": -1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10290227071, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32433997, + "proving_cost": 5506130090, + "congestion_cost": 20759319767, + "congestion_multiplier": 4748141114 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 333753193, + "proving_cost": 56659328908, + "congestion_cost": 213618114241, + "congestion_multiplier": 4748141114 + } + } + }, + { + "l1_block_number": 20974421, + "l1_fees": { + "blob_fee": 2, + "base_fee": 9523218022 + }, + "parent_header": { + "excess_mana": 1331412988, + "mana_used": 91900546, + "proving_cost_per_mana_numerator": 1810563151, + "fee_asset_price_numerator": 1860952379 + }, + "header": { + "excess_mana": 1323313534, + "mana_used": 102883709, + "proving_cost_per_mana_numerator": 1818236942, + "fee_asset_price_numerator": 2187559535 + }, + "oracle_input": { + "proving_cost_modifier": 7673791, + "fee_asset_price_modifier": 326607156 + }, + "outputs": { + "fee_asset_price_at_execution": 10187837601, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31545659, + "proving_cost": 5514299426, + "congestion_cost": 20538252740, + "congestion_multiplier": 4703358537 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 321382050, + "proving_cost": 56178787035, + "congestion_cost": 209240383523, + "congestion_multiplier": 4703358537 + } + } + }, + { + "l1_block_number": 20974424, + "l1_fees": { + "blob_fee": 2, + "base_fee": 9104142284 + }, + "parent_header": { + "excess_mana": 1323313534, + "mana_used": 102883709, + "proving_cost_per_mana_numerator": 1818236942, + "fee_asset_price_numerator": 2187559535 + }, + "header": { + "excess_mana": 1326197243, + "mana_used": 96751216, + "proving_cost_per_mana_numerator": 1763396743, + "fee_asset_price_numerator": 1387005711 + }, + "oracle_input": { + "proving_cost_modifier": -54840199, + "fee_asset_price_modifier": -800553824 + }, + "outputs": { + "fee_asset_price_at_execution": 10221166205, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30157471, + "proving_cost": 5514722598, + "congestion_cost": 20622818401, + "congestion_multiplier": 4719254185 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 308244523, + "proving_cost": 56366896248, + "congestion_cost": 210789254492, + "congestion_multiplier": 4719254185 + } + } + }, + { + "l1_block_number": 20974427, + "l1_fees": { + "blob_fee": 2, + "base_fee": 9433024582 + }, + "parent_header": { + "excess_mana": 1326197243, + "mana_used": 96751216, + "proving_cost_per_mana_numerator": 1763396743, + "fee_asset_price_numerator": 1387005711 + }, + "header": { + "excess_mana": 1322948459, + "mana_used": 97573641, + "proving_cost_per_mana_numerator": 1659879098, + "fee_asset_price_numerator": 1287275603 + }, + "oracle_input": { + "proving_cost_modifier": -103517645, + "fee_asset_price_modifier": -99730108 + }, + "outputs": { + "fee_asset_price_at_execution": 10139666926, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31246893, + "proving_cost": 5511699143, + "congestion_cost": 20516383221, + "congestion_multiplier": 4701349984 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 316833087, + "proving_cost": 55886793506, + "congestion_cost": 208029292387, + "congestion_multiplier": 4701349984 + } + } + }, + { + "l1_block_number": 20974430, + "l1_fees": { + "blob_fee": 2, + "base_fee": 9577344523 + }, + "parent_header": { + "excess_mana": 1322948459, + "mana_used": 97573641, + "proving_cost_per_mana_numerator": 1659879098, + "fee_asset_price_numerator": 1287275603 + }, + "header": { + "excess_mana": 1320522100, + "mana_used": 108291556, + "proving_cost_per_mana_numerator": 1760133785, + "fee_asset_price_numerator": 2109308002 + }, + "oracle_input": { + "proving_cost_modifier": 100254687, + "fee_asset_price_modifier": 822032399 + }, + "outputs": { + "fee_asset_price_at_execution": 10129559666, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31724953, + "proving_cost": 5505996513, + "congestion_cost": 20423241531, + "congestion_multiplier": 4688022530 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 321359804, + "proving_cost": 55773320199, + "congestion_cost": 206878443661, + "congestion_multiplier": 4688022530 + } + } + }, + { + "l1_block_number": 20974433, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10362139543 + }, + "parent_header": { + "excess_mana": 1320522100, + "mana_used": 108291556, + "proving_cost_per_mana_numerator": 1760133785, + "fee_asset_price_numerator": 2109308002 + }, + "header": { + "excess_mana": 1328813656, + "mana_used": 116536020, + "proving_cost_per_mana_numerator": 1680519423, + "fee_asset_price_numerator": 2585288012 + }, + "oracle_input": { + "proving_cost_modifier": -79614362, + "fee_asset_price_modifier": 475980010 + }, + "outputs": { + "fee_asset_price_at_execution": 10213171114, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34324587, + "proving_cost": 5511519301, + "congestion_cost": 20706644413, + "congestion_multiplier": 4733722916 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 350562880, + "proving_cost": 56290089719, + "congestion_cost": 211480502586, + "congestion_multiplier": 4733722916 + } + } + }, + { + "l1_block_number": 20974436, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10406464639 + }, + "parent_header": { + "excess_mana": 1328813656, + "mana_used": 116536020, + "proving_cost_per_mana_numerator": 1680519423, + "fee_asset_price_numerator": 2585288012 + }, + "header": { + "excess_mana": 1345349676, + "mana_used": 96428044, + "proving_cost_per_mana_numerator": 1476676325, + "fee_asset_price_numerator": 2439022097 + }, + "oracle_input": { + "proving_cost_modifier": -203843098, + "fee_asset_price_modifier": -146265915 + }, + "outputs": { + "fee_asset_price_at_execution": 10261899644, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34471414, + "proving_cost": 5507133086, + "congestion_cost": 21203279479, + "congestion_multiplier": 4826198618 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 353742191, + "proving_cost": 56513647054, + "congestion_cost": 217585926137, + "congestion_multiplier": 4826198618 + } + } + }, + { + "l1_block_number": 20974439, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10104922672 + }, + "parent_header": { + "excess_mana": 1345349676, + "mana_used": 96428044, + "proving_cost_per_mana_numerator": 1476676325, + "fee_asset_price_numerator": 2439022097 + }, + "header": { + "excess_mana": 1341777720, + "mana_used": 95890772, + "proving_cost_per_mana_numerator": 1609085406, + "fee_asset_price_numerator": 3126603769 + }, + "oracle_input": { + "proving_cost_modifier": 132409081, + "fee_asset_price_modifier": 687581672 + }, + "outputs": { + "fee_asset_price_at_execution": 10246900954, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33472556, + "proving_cost": 5495918609, + "congestion_cost": 21045255974, + "congestion_multiplier": 4806071111 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 342989966, + "proving_cost": 56316133637, + "congestion_cost": 215648653517, + "congestion_multiplier": 4806071111 + } + } + }, + { + "l1_block_number": 20974442, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9965861569 + }, + "parent_header": { + "excess_mana": 1341777720, + "mana_used": 95890772, + "proving_cost_per_mana_numerator": 1609085406, + "fee_asset_price_numerator": 3126603769 + }, + "header": { + "excess_mana": 1337668492, + "mana_used": 94902476, + "proving_cost_per_mana_numerator": 1510544942, + "fee_asset_price_numerator": 3479262472 + }, + "oracle_input": { + "proving_cost_modifier": -98540464, + "fee_asset_price_modifier": 352658703 + }, + "outputs": { + "fee_asset_price_at_execution": 10317599544, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33011916, + "proving_cost": 5503200525, + "congestion_cost": 20943602139, + "congestion_multiplier": 4783019955 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 340603729, + "proving_cost": 56779819227, + "congestion_cost": 216087699879, + "congestion_multiplier": 4783019955 + } + } + }, + { + "l1_block_number": 20974445, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9453701170 + }, + "parent_header": { + "excess_mana": 1337668492, + "mana_used": 94902476, + "proving_cost_per_mana_numerator": 1510544942, + "fee_asset_price_numerator": 3479262472 + }, + "header": { + "excess_mana": 1332570968, + "mana_used": 107758024, + "proving_cost_per_mana_numerator": 1408425412, + "fee_asset_price_numerator": 3570246302 + }, + "oracle_input": { + "proving_cost_modifier": -102119530, + "fee_asset_price_modifier": 90983830 + }, + "outputs": { + "fee_asset_price_at_execution": 10354049691, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31315385, + "proving_cost": 5497780316, + "congestion_cost": 20759423456, + "congestion_multiplier": 4754578430 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 324241052, + "proving_cost": 56924290582, + "congestion_cost": 214944102019, + "congestion_multiplier": 4754578430 + } + } + }, + { + "l1_block_number": 20974448, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10049137759 + }, + "parent_header": { + "excess_mana": 1332570968, + "mana_used": 107758024, + "proving_cost_per_mana_numerator": 1408425412, + "fee_asset_price_numerator": 3570246302 + }, + "header": { + "excess_mana": 1340328992, + "mana_used": 91950513, + "proving_cost_per_mana_numerator": 1408723465, + "fee_asset_price_numerator": 3283241701 + }, + "oracle_input": { + "proving_cost_modifier": 298053, + "fee_asset_price_modifier": -287004601 + }, + "outputs": { + "fee_asset_price_at_execution": 10363474489, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33287768, + "proving_cost": 5492168875, + "congestion_cost": 20985306748, + "congestion_multiplier": 4797931665 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 344976934, + "proving_cost": 56917952025, + "congestion_cost": 217480691126, + "congestion_multiplier": 4797931665 + } + } + }, + { + "l1_block_number": 20974451, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9689451624 + }, + "parent_header": { + "excess_mana": 1340328992, + "mana_used": 91950513, + "proving_cost_per_mana_numerator": 1408723465, + "fee_asset_price_numerator": 3283241701 + }, + "header": { + "excess_mana": 1332279505, + "mana_used": 83167517, + "proving_cost_per_mana_numerator": 1481314433, + "fee_asset_price_numerator": 2985347824 + }, + "oracle_input": { + "proving_cost_modifier": 72590968, + "fee_asset_price_modifier": -297893877 + }, + "outputs": { + "fee_asset_price_at_execution": 10333773482, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32096308, + "proving_cost": 5492185244, + "congestion_cost": 20732392993, + "congestion_multiplier": 4752957339 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 331675976, + "proving_cost": 56754998232, + "congestion_cost": 214243852929, + "congestion_multiplier": 4752957339 + } + } + }, + { + "l1_block_number": 20974454, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9132012958 + }, + "parent_header": { + "excess_mana": 1332279505, + "mana_used": 83167517, + "proving_cost_per_mana_numerator": 1481314433, + "fee_asset_price_numerator": 2985347824 + }, + "header": { + "excess_mana": 1315447022, + "mana_used": 104540142, + "proving_cost_per_mana_numerator": 1485447414, + "fee_asset_price_numerator": 3115043922 + }, + "oracle_input": { + "proving_cost_modifier": 4132981, + "fee_asset_price_modifier": 129696098 + }, + "outputs": { + "fee_asset_price_at_execution": 10303035610, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30249792, + "proving_cost": 5496173522, + "congestion_cost": 20228191947, + "congestion_multiplier": 4660268278 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 311664684, + "proving_cost": 56627271515, + "congestion_cost": 208411781955, + "congestion_multiplier": 4660268278 + } + } + }, + { + "l1_block_number": 20974457, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9109047599 + }, + "parent_header": { + "excess_mana": 1315447022, + "mana_used": 104540142, + "proving_cost_per_mana_numerator": 1485447414, + "fee_asset_price_numerator": 3115043922 + }, + "header": { + "excess_mana": 1319987164, + "mana_used": 98613846, + "proving_cost_per_mana_numerator": 1619719960, + "fee_asset_price_numerator": 4071641001 + }, + "oracle_input": { + "proving_cost_modifier": 134272546, + "fee_asset_price_modifier": 956597079 + }, + "outputs": { + "fee_asset_price_at_execution": 10316406914, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30173720, + "proving_cost": 5496400683, + "congestion_cost": 20365920369, + "congestion_multiplier": 4685089331 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 311284373, + "proving_cost": 56703106008, + "congestion_cost": 210103121704, + "congestion_multiplier": 4685089331 + } + } + }, + { + "l1_block_number": 20974460, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9238199253 + }, + "parent_header": { + "excess_mana": 1319987164, + "mana_used": 98613846, + "proving_cost_per_mana_numerator": 1619719960, + "fee_asset_price_numerator": 4071641001 + }, + "header": { + "excess_mana": 1318601010, + "mana_used": 93569588, + "proving_cost_per_mana_numerator": 1534217900, + "fee_asset_price_numerator": 4385474010 + }, + "oracle_input": { + "proving_cost_modifier": -85502060, + "fee_asset_price_modifier": 313833009 + }, + "outputs": { + "fee_asset_price_at_execution": 10415566886, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30601535, + "proving_cost": 5503785797, + "congestion_cost": 20352693978, + "congestion_multiplier": 4677497211 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 318732334, + "proving_cost": 57325049094, + "congestion_cost": 211984845438, + "congestion_multiplier": 4677497211 + } + } + }, + { + "l1_block_number": 20974463, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9135208521 + }, + "parent_header": { + "excess_mana": 1318601010, + "mana_used": 93569588, + "proving_cost_per_mana_numerator": 1534217900, + "fee_asset_price_numerator": 4385474010 + }, + "header": { + "excess_mana": 1312170598, + "mana_used": 101029045, + "proving_cost_per_mana_numerator": 1496951851, + "fee_asset_price_numerator": 4427090165 + }, + "oracle_input": { + "proving_cost_modifier": -37266049, + "fee_asset_price_modifier": 41616155 + }, + "outputs": { + "fee_asset_price_at_execution": 10448305718, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30260378, + "proving_cost": 5499081958, + "congestion_cost": 20140285141, + "congestion_multiplier": 4642437729 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 316169680, + "proving_cost": 57456089465, + "congestion_cost": 210431856400, + "congestion_multiplier": 4642437729 + } + } + }, + { + "l1_block_number": 20974466, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9109919091 + }, + "parent_header": { + "excess_mana": 1312170598, + "mana_used": 101029045, + "proving_cost_per_mana_numerator": 1496951851, + "fee_asset_price_numerator": 4427090165 + }, + "header": { + "excess_mana": 1313199643, + "mana_used": 103381370, + "proving_cost_per_mana_numerator": 1456521830, + "fee_asset_price_numerator": 4554855911 + }, + "oracle_input": { + "proving_cost_modifier": -40430021, + "fee_asset_price_modifier": 127765746 + }, + "outputs": { + "fee_asset_price_at_execution": 10452654806, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30176606, + "proving_cost": 5497033049, + "congestion_cost": 20163429451, + "congestion_multiplier": 4648030509 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 315425645, + "proving_cost": 57458588918, + "congestion_cost": 210761367756, + "congestion_multiplier": 4648030509 + } + } + }, + { + "l1_block_number": 20974469, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9426312134 + }, + "parent_header": { + "excess_mana": 1313199643, + "mana_used": 103381370, + "proving_cost_per_mana_numerator": 1456521830, + "fee_asset_price_numerator": 4554855911 + }, + "header": { + "excess_mana": 1316581013, + "mana_used": 93119606, + "proving_cost_per_mana_numerator": 1383332186, + "fee_asset_price_numerator": 4852570946 + }, + "oracle_input": { + "proving_cost_modifier": -73189644, + "fee_asset_price_modifier": 297715035 + }, + "outputs": { + "fee_asset_price_at_execution": 10466018254, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31224658, + "proving_cost": 5494811046, + "congestion_cost": 20260963906, + "congestion_multiplier": 4666455483 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 326797840, + "proving_cost": 57508792709, + "congestion_cost": 212051618083, + "congestion_multiplier": 4666455483 + } + } + }, + { + "l1_block_number": 20974472, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8424055996 + }, + "parent_header": { + "excess_mana": 1316581013, + "mana_used": 93119606, + "proving_cost_per_mana_numerator": 1383332186, + "fee_asset_price_numerator": 4852570946 + }, + "header": { + "excess_mana": 1309700619, + "mana_used": 109263041, + "proving_cost_per_mana_numerator": 1365258008, + "fee_asset_price_numerator": 4182988274 + }, + "oracle_input": { + "proving_cost_modifier": -18074178, + "fee_asset_price_modifier": -669582672 + }, + "outputs": { + "fee_asset_price_at_execution": 10497223592, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 27904685, + "proving_cost": 5490790885, + "congestion_cost": 20027572650, + "congestion_multiplier": 4629041029 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 292921717, + "proving_cost": 57638059616, + "congestion_cost": 210233908112, + "congestion_multiplier": 4629041029 + } + } + }, + { + "l1_block_number": 20974475, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9204460195 + }, + "parent_header": { + "excess_mana": 1309700619, + "mana_used": 109263041, + "proving_cost_per_mana_numerator": 1365258008, + "fee_asset_price_numerator": 4182988274 + }, + "header": { + "excess_mana": 1318963660, + "mana_used": 86270240, + "proving_cost_per_mana_numerator": 1280812819, + "fee_asset_price_numerator": 4367269688 + }, + "oracle_input": { + "proving_cost_modifier": -84445189, + "fee_asset_price_modifier": 184281414 + }, + "outputs": { + "fee_asset_price_at_execution": 10427170794, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30489774, + "proving_cost": 5489798560, + "congestion_cost": 20311803193, + "congestion_multiplier": 4679482296 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 317922080, + "proving_cost": 57243067209, + "congestion_cost": 211794641027, + "congestion_multiplier": 4679482296 + } + } + }, + { + "l1_block_number": 20974478, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8598622425 + }, + "parent_header": { + "excess_mana": 1318963660, + "mana_used": 86270240, + "proving_cost_per_mana_numerator": 1280812819, + "fee_asset_price_numerator": 4367269688 + }, + "header": { + "excess_mana": 1305233900, + "mana_used": 122448599, + "proving_cost_per_mana_numerator": 1339381969, + "fee_asset_price_numerator": 5366579735 + }, + "oracle_input": { + "proving_cost_modifier": 58569150, + "fee_asset_price_modifier": 999310047 + }, + "outputs": { + "fee_asset_price_at_execution": 10446403848, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 28482936, + "proving_cost": 5485164646, + "congestion_cost": 19876216978, + "congestion_multiplier": 4604912480 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 297544252, + "proving_cost": 57300245064, + "congestion_cost": 207634989522, + "congestion_multiplier": 4604912480 + } + } + }, + { + "l1_block_number": 20974481, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9667058305 + }, + "parent_header": { + "excess_mana": 1305233900, + "mana_used": 122448599, + "proving_cost_per_mana_numerator": 1339381969, + "fee_asset_price_numerator": 5366579735 + }, + "header": { + "excess_mana": 1327682499, + "mana_used": 93784845, + "proving_cost_per_mana_numerator": 1302285571, + "fee_asset_price_numerator": 5548916077 + }, + "oracle_input": { + "proving_cost_modifier": -37096398, + "fee_asset_price_modifier": 182336342 + }, + "outputs": { + "fee_asset_price_at_execution": 10551319153, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32022130, + "proving_cost": 5488378201, + "congestion_cost": 20577083540, + "congestion_multiplier": 4727462196 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 337875713, + "proving_cost": 57909630031, + "congestion_cost": 217115375668, + "congestion_multiplier": 4727462196 + } + } + }, + { + "l1_block_number": 20974484, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10311092960 + }, + "parent_header": { + "excess_mana": 1327682499, + "mana_used": 93784845, + "proving_cost_per_mana_numerator": 1302285571, + "fee_asset_price_numerator": 5548916077 + }, + "header": { + "excess_mana": 1321467344, + "mana_used": 65246777, + "proving_cost_per_mana_numerator": 1238088312, + "fee_asset_price_numerator": 4997963835 + }, + "oracle_input": { + "proving_cost_modifier": -64197259, + "fee_asset_price_modifier": -550952242 + }, + "outputs": { + "fee_asset_price_at_execution": 10570575593, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34155495, + "proving_cost": 5486342588, + "congestion_cost": 20388358990, + "congestion_multiplier": 4693210048 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 361043241, + "proving_cost": 57993799055, + "congestion_cost": 215516689921, + "congestion_multiplier": 4693210048 + } + } + }, + { + "l1_block_number": 20974487, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9964934537 + }, + "parent_header": { + "excess_mana": 1321467344, + "mana_used": 65246777, + "proving_cost_per_mana_numerator": 1238088312, + "fee_asset_price_numerator": 4997963835 + }, + "header": { + "excess_mana": 1286714121, + "mana_used": 129539692, + "proving_cost_per_mana_numerator": 1255659249, + "fee_asset_price_numerator": 4985871086 + }, + "oracle_input": { + "proving_cost_modifier": 17570937, + "fee_asset_price_modifier": -12092749 + }, + "outputs": { + "fee_asset_price_at_execution": 10512496909, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33008845, + "proving_cost": 5482821637, + "congestion_cost": 19339637059, + "congestion_multiplier": 4506205842 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 347005381, + "proving_cost": 57638145511, + "congestion_cost": 203307874803, + "congestion_multiplier": 4506205842 + } + } + }, + { + "l1_block_number": 20974490, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10147307115 + }, + "parent_header": { + "excess_mana": 1286714121, + "mana_used": 129539692, + "proving_cost_per_mana_numerator": 1255659249, + "fee_asset_price_numerator": 4985871086 + }, + "header": { + "excess_mana": 1316253813, + "mana_used": 107842618, + "proving_cost_per_mana_numerator": 1343886692, + "fee_asset_price_numerator": 4131913707 + }, + "oracle_input": { + "proving_cost_modifier": 88227443, + "fee_asset_price_modifier": -853957379 + }, + "outputs": { + "fee_asset_price_at_execution": 10511225736, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33612954, + "proving_cost": 5483785104, + "congestion_cost": 20219439797, + "congestion_multiplier": 4664669394 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 353313347, + "proving_cost": 57641303115, + "congestion_cost": 212531095961, + "congestion_multiplier": 4664669394 + } + } + }, + { + "l1_block_number": 20974493, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9938782318 + }, + "parent_header": { + "excess_mana": 1316253813, + "mana_used": 107842618, + "proving_cost_per_mana_numerator": 1343886692, + "fee_asset_price_numerator": 4131913707 + }, + "header": { + "excess_mana": 1324096431, + "mana_used": 112543554, + "proving_cost_per_mana_numerator": 1347111084, + "fee_asset_price_numerator": 3921942167 + }, + "oracle_input": { + "proving_cost_modifier": 3224392, + "fee_asset_price_modifier": -209971540 + }, + "outputs": { + "fee_asset_price_at_execution": 10421846522, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32922216, + "proving_cost": 5488625443, + "congestion_cost": 20472069640, + "congestion_multiplier": 4707668738 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 343110282, + "proving_cost": 57201611983, + "congestion_cost": 213356767775, + "congestion_multiplier": 4707668738 + } + } + }, + { + "l1_block_number": 20974496, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9644897398 + }, + "parent_header": { + "excess_mana": 1324096431, + "mana_used": 112543554, + "proving_cost_per_mana_numerator": 1347111084, + "fee_asset_price_numerator": 3921942167 + }, + "header": { + "excess_mana": 1336639985, + "mana_used": 73408546, + "proving_cost_per_mana_numerator": 1278285869, + "fee_asset_price_numerator": 3955137169 + }, + "oracle_input": { + "proving_cost_modifier": -68825215, + "fee_asset_price_modifier": 33195002 + }, + "outputs": { + "fee_asset_price_at_execution": 10399986568, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31948722, + "proving_cost": 5488802420, + "congestion_cost": 20853355272, + "congestion_multiplier": 4777267755 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 332266279, + "proving_cost": 57083471442, + "congestion_cost": 216874614726, + "congestion_multiplier": 4777267755 + } + } + }, + { + "l1_block_number": 20974499, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9683030291 + }, + "parent_header": { + "excess_mana": 1336639985, + "mana_used": 73408546, + "proving_cost_per_mana_numerator": 1278285869, + "fee_asset_price_numerator": 3955137169 + }, + "header": { + "excess_mana": 1310048531, + "mana_used": 113343265, + "proving_cost_per_mana_numerator": 1214917640, + "fee_asset_price_numerator": 3560832675 + }, + "oracle_input": { + "proving_cost_modifier": -63368229, + "fee_asset_price_modifier": -394304494 + }, + "outputs": { + "fee_asset_price_at_execution": 10403439417, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32075037, + "proving_cost": 5485026040, + "congestion_cost": 20032184067, + "congestion_multiplier": 4630925696 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 333690704, + "proving_cost": 57063136107, + "congestion_cost": 208403613331, + "congestion_multiplier": 4630925696 + } + } + }, + { + "l1_block_number": 20974502, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11058719709 + }, + "parent_header": { + "excess_mana": 1310048531, + "mana_used": 113343265, + "proving_cost_per_mana_numerator": 1214917640, + "fee_asset_price_numerator": 3560832675 + }, + "header": { + "excess_mana": 1323391796, + "mana_used": 94371501, + "proving_cost_per_mana_numerator": 1081226248, + "fee_asset_price_numerator": 3698989537 + }, + "oracle_input": { + "proving_cost_modifier": -133691392, + "fee_asset_price_modifier": 138156862 + }, + "outputs": { + "fee_asset_price_at_execution": 10362498956, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 36632009, + "proving_cost": 5481551377, + "congestion_cost": 20438188177, + "congestion_multiplier": 4703789227 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 379599155, + "proving_cost": 56802570421, + "congestion_cost": 211790703646, + "congestion_multiplier": 4703789227 + } + } + }, + { + "l1_block_number": 20974505, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12997295205 + }, + "parent_header": { + "excess_mana": 1323391796, + "mana_used": 94371501, + "proving_cost_per_mana_numerator": 1081226248, + "fee_asset_price_numerator": 3698989537 + }, + "header": { + "excess_mana": 1317763297, + "mana_used": 93168662, + "proving_cost_per_mana_numerator": 1085933046, + "fee_asset_price_numerator": 3297057904 + }, + "oracle_input": { + "proving_cost_modifier": 4706798, + "fee_asset_price_modifier": -401931633 + }, + "outputs": { + "fee_asset_price_at_execution": 10376825353, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 43053540, + "proving_cost": 5474227911, + "congestion_cost": 20264505403, + "congestion_multiplier": 4672914928 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 446759065, + "proving_cost": 56805106974, + "congestion_cost": 210281233431, + "congestion_multiplier": 4672914928 + } + } + }, + { + "l1_block_number": 20974508, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12529147099 + }, + "parent_header": { + "excess_mana": 1317763297, + "mana_used": 93168662, + "proving_cost_per_mana_numerator": 1085933046, + "fee_asset_price_numerator": 3297057904 + }, + "header": { + "excess_mana": 1310931959, + "mana_used": 93314520, + "proving_cost_per_mana_numerator": 1078558840, + "fee_asset_price_numerator": 2473855109 + }, + "oracle_input": { + "proving_cost_modifier": -7374206, + "fee_asset_price_modifier": -823202795 + }, + "outputs": { + "fee_asset_price_at_execution": 10335201316, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 41502799, + "proving_cost": 5474485578, + "congestion_cost": 20054560275, + "congestion_multiplier": 4635714745 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 428939782, + "proving_cost": 56579910550, + "congestion_cost": 207267917745, + "congestion_multiplier": 4635714745 + } + } + }, + { + "l1_block_number": 20974511, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10526750513 + }, + "parent_header": { + "excess_mana": 1310931959, + "mana_used": 93314520, + "proving_cost_per_mana_numerator": 1078558840, + "fee_asset_price_numerator": 2473855109 + }, + "header": { + "excess_mana": 1304246479, + "mana_used": 103896298, + "proving_cost_per_mana_numerator": 1029046373, + "fee_asset_price_numerator": 1930554124 + }, + "oracle_input": { + "proving_cost_modifier": -49512467, + "fee_asset_price_modifier": -543300985 + }, + "outputs": { + "fee_asset_price_at_execution": 10250470880, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34869861, + "proving_cost": 5474081893, + "congestion_cost": 19829998367, + "congestion_multiplier": 4599595577 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 357432494, + "proving_cost": 56111917038, + "congestion_cost": 203266820811, + "congestion_multiplier": 4599595577 + } + } + }, + { + "l1_block_number": 20974514, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11093378624 + }, + "parent_header": { + "excess_mana": 1304246479, + "mana_used": 103896298, + "proving_cost_per_mana_numerator": 1029046373, + "fee_asset_price_numerator": 1930554124 + }, + "header": { + "excess_mana": 1308142777, + "mana_used": 117487149, + "proving_cost_per_mana_numerator": 984241441, + "fee_asset_price_numerator": 2186396974 + }, + "oracle_input": { + "proving_cost_modifier": -44804932, + "fee_asset_price_modifier": 255842850 + }, + "outputs": { + "fee_asset_price_at_execution": 10194930982, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 36746816, + "proving_cost": 5471372211, + "congestion_cost": 19942758954, + "congestion_multiplier": 4620611475 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 374631252, + "proving_cost": 55780262067, + "congestion_cost": 203315051126, + "congestion_multiplier": 4620611475 + } + } + }, + { + "l1_block_number": 20974517, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10637397356 + }, + "parent_header": { + "excess_mana": 1308142777, + "mana_used": 117487149, + "proving_cost_per_mana_numerator": 984241441, + "fee_asset_price_numerator": 2186396974 + }, + "header": { + "excess_mana": 1325629926, + "mana_used": 96366063, + "proving_cost_per_mana_numerator": 962580842, + "fee_asset_price_numerator": 2295853999 + }, + "oracle_input": { + "proving_cost_modifier": -21660599, + "fee_asset_price_modifier": 109457025 + }, + "outputs": { + "fee_asset_price_at_execution": 10221047378, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35236378, + "proving_cost": 5468921316, + "congestion_cost": 20454125725, + "congestion_multiplier": 4716122768 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 360152688, + "proving_cost": 55898103877, + "congestion_cost": 209062588110, + "congestion_multiplier": 4716122768 + } + } + }, + { + "l1_block_number": 20974520, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10064163696 + }, + "parent_header": { + "excess_mana": 1325629926, + "mana_used": 96366063, + "proving_cost_per_mana_numerator": 962580842, + "fee_asset_price_numerator": 2295853999 + }, + "header": { + "excess_mana": 1321995989, + "mana_used": 104057436, + "proving_cost_per_mana_numerator": 1102561637, + "fee_asset_price_numerator": 2044244503 + }, + "oracle_input": { + "proving_cost_modifier": 139980795, + "fee_asset_price_modifier": -251609496 + }, + "outputs": { + "fee_asset_price_at_execution": 10232241157, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33337542, + "proving_cost": 5467736843, + "congestion_cost": 20332596762, + "congestion_multiplier": 4696113766 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 341117769, + "proving_cost": 55947201960, + "congestion_cost": 208048033416, + "congestion_multiplier": 4696113766 + } + } + }, + { + "l1_block_number": 20974523, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11907531280 + }, + "parent_header": { + "excess_mana": 1321995989, + "mana_used": 104057436, + "proving_cost_per_mana_numerator": 1102561637, + "fee_asset_price_numerator": 2044244503 + }, + "header": { + "excess_mana": 1326053425, + "mana_used": 102990842, + "proving_cost_per_mana_numerator": 1166748460, + "fee_asset_price_numerator": 1690058727 + }, + "oracle_input": { + "proving_cost_modifier": 64186823, + "fee_asset_price_modifier": -354185776 + }, + "outputs": { + "fee_asset_price_at_execution": 10206528229, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 39443697, + "proving_cost": 5475395984, + "congestion_cost": 20506711626, + "congestion_multiplier": 4718460157 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 402583206, + "proving_cost": 55884783675, + "congestion_cost": 209302331094, + "congestion_multiplier": 4718460157 + } + } + }, + { + "l1_block_number": 20974526, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11019213472 + }, + "parent_header": { + "excess_mana": 1326053425, + "mana_used": 102990842, + "proving_cost_per_mana_numerator": 1166748460, + "fee_asset_price_numerator": 1690058727 + }, + "header": { + "excess_mana": 1329044267, + "mana_used": 107221657, + "proving_cost_per_mana_numerator": 1228517743, + "fee_asset_price_numerator": 1122668389 + }, + "oracle_input": { + "proving_cost_modifier": 61769283, + "fee_asset_price_modifier": -567390338 + }, + "outputs": { + "fee_asset_price_at_execution": 10170442101, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 36501144, + "proving_cost": 5478911595, + "congestion_cost": 20600068328, + "congestion_multiplier": 4735000317 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 371232771, + "proving_cost": 55722953153, + "congestion_cost": 209511802206, + "congestion_multiplier": 4735000317 + } + } + }, + { + "l1_block_number": 20974529, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11135880229 + }, + "parent_header": { + "excess_mana": 1329044267, + "mana_used": 107221657, + "proving_cost_per_mana_numerator": 1228517743, + "fee_asset_price_numerator": 1122668389 + }, + "header": { + "excess_mana": 1336265924, + "mana_used": 91764333, + "proving_cost_per_mana_numerator": 1208026504, + "fee_asset_price_numerator": 1888536575 + }, + "oracle_input": { + "proving_cost_modifier": -20491239, + "fee_asset_price_modifier": 765868186 + }, + "outputs": { + "fee_asset_price_at_execution": 10112899396, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 36887603, + "proving_cost": 5482296924, + "congestion_cost": 20835900880, + "congestion_multiplier": 4775177434 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 373040618, + "proving_cost": 55441917251, + "congestion_cost": 210711369424, + "congestion_multiplier": 4775177434 + } + } + }, + { + "l1_block_number": 20974532, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10401645769 + }, + "parent_header": { + "excess_mana": 1336265924, + "mana_used": 91764333, + "proving_cost_per_mana_numerator": 1208026504, + "fee_asset_price_numerator": 1888536575 + }, + "header": { + "excess_mana": 1328030257, + "mana_used": 87902892, + "proving_cost_per_mana_numerator": 1200128277, + "fee_asset_price_numerator": 1941013105 + }, + "oracle_input": { + "proving_cost_modifier": -7898227, + "fee_asset_price_modifier": 52476530 + }, + "outputs": { + "fee_asset_price_at_execution": 10190648221, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34455451, + "proving_cost": 5481173649, + "congestion_cost": 20569910404, + "congestion_multiplier": 4729386083 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 351123380, + "proving_cost": 55856712495, + "congestion_cost": 209620720864, + "congestion_multiplier": 4729386083 + } + } + }, + { + "l1_block_number": 20974535, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11090844407 + }, + "parent_header": { + "excess_mana": 1328030257, + "mana_used": 87902892, + "proving_cost_per_mana_numerator": 1200128277, + "fee_asset_price_numerator": 1941013105 + }, + "header": { + "excess_mana": 1315933149, + "mana_used": 92877236, + "proving_cost_per_mana_numerator": 1136168049, + "fee_asset_price_numerator": 1382043599 + }, + "oracle_input": { + "proving_cost_modifier": -63960228, + "fee_asset_price_modifier": -558969506 + }, + "outputs": { + "fee_asset_price_at_execution": 10195997323, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 36738422, + "proving_cost": 5480740751, + "congestion_cost": 20210082859, + "congestion_multiplier": 4662919646 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 374584852, + "proving_cost": 55881618025, + "congestion_cost": 206061950727, + "congestion_multiplier": 4662919646 + } + } + }, + { + "l1_block_number": 20974538, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10020764445 + }, + "parent_header": { + "excess_mana": 1315933149, + "mana_used": 92877236, + "proving_cost_per_mana_numerator": 1136168049, + "fee_asset_price_numerator": 1382043599 + }, + "header": { + "excess_mana": 1308810385, + "mana_used": 106131552, + "proving_cost_per_mana_numerator": 893392989, + "fee_asset_price_numerator": 1723038366 + }, + "oracle_input": { + "proving_cost_modifier": -242775060, + "fee_asset_price_modifier": 340994767 + }, + "outputs": { + "fee_asset_price_at_execution": 10139163797, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33193782, + "proving_cost": 5477236377, + "congestion_cost": 19971022492, + "congestion_multiplier": 4624222051 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 336557192, + "proving_cost": 55534596781, + "congestion_cost": 202489468239, + "congestion_multiplier": 4624222051 + } + } + }, + { + "l1_block_number": 20974541, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9721514258 + }, + "parent_header": { + "excess_mana": 1308810385, + "mana_used": 106131552, + "proving_cost_per_mana_numerator": 893392989, + "fee_asset_price_numerator": 1723038366 + }, + "header": { + "excess_mana": 1314941937, + "mana_used": 106820614, + "proving_cost_per_mana_numerator": 999930664, + "fee_asset_price_numerator": 1858647729 + }, + "oracle_input": { + "proving_cost_modifier": 106537675, + "fee_asset_price_modifier": 135609363 + }, + "outputs": { + "fee_asset_price_at_execution": 10173796829, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32202515, + "proving_cost": 5463955141, + "congestion_cost": 20102279668, + "congestion_multiplier": 4657515109 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 327621844, + "proving_cost": 55589169487, + "congestion_cost": 204516509141, + "congestion_multiplier": 4657515109 + } + } + }, + { + "l1_block_number": 20974544, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9605454919 + }, + "parent_header": { + "excess_mana": 1314941937, + "mana_used": 106820614, + "proving_cost_per_mana_numerator": 999930664, + "fee_asset_price_numerator": 1858647729 + }, + "header": { + "excess_mana": 1321762551, + "mana_used": 94649159, + "proving_cost_per_mana_numerator": 1216200771, + "fee_asset_price_numerator": 1932155741 + }, + "oracle_input": { + "proving_cost_modifier": 216270107, + "fee_asset_price_modifier": 73508012 + }, + "outputs": { + "fee_asset_price_at_execution": 10187602809, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31818069, + "proving_cost": 5469779414, + "congestion_cost": 20327474728, + "congestion_multiplier": 4694831327 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 324149849, + "proving_cost": 55723940122, + "congestion_cost": 207088238638, + "congestion_multiplier": 4694831327 + } + } + }, + { + "l1_block_number": 20974547, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8987171015 + }, + "parent_header": { + "excess_mana": 1321762551, + "mana_used": 94649159, + "proving_cost_per_mana_numerator": 1216200771, + "fee_asset_price_numerator": 1932155741 + }, + "header": { + "excess_mana": 1316411710, + "mana_used": 99651852, + "proving_cost_per_mana_numerator": 1030218038, + "fee_asset_price_numerator": 1640498241 + }, + "oracle_input": { + "proving_cost_modifier": -185982733, + "fee_asset_price_modifier": -291657500 + }, + "outputs": { + "fee_asset_price_at_execution": 10195094267, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29770003, + "proving_cost": 5481621713, + "congestion_cost": 20202178411, + "congestion_multiplier": 4665531222 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 303507986, + "proving_cost": 55885650100, + "congestion_cost": 205963113298, + "congestion_multiplier": 4665531222 + } + } + }, + { + "l1_block_number": 20974550, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9961876485 + }, + "parent_header": { + "excess_mana": 1316411710, + "mana_used": 99651852, + "proving_cost_per_mana_numerator": 1030218038, + "fee_asset_price_numerator": 1640498241 + }, + "header": { + "excess_mana": 1316063562, + "mana_used": 111037651, + "proving_cost_per_mana_numerator": 873740990, + "fee_asset_price_numerator": 1361795236 + }, + "oracle_input": { + "proving_cost_modifier": -156477048, + "fee_asset_price_modifier": -278703005 + }, + "outputs": { + "fee_asset_price_at_execution": 10165402829, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32998715, + "proving_cost": 5471436318, + "congestion_cost": 20166219837, + "congestion_multiplier": 4663631184 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 335445230, + "proving_cost": 55619354225, + "congestion_cost": 204997748181, + "congestion_multiplier": 4663631184 + } + } + }, + { + "l1_block_number": 20974553, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9733495056 + }, + "parent_header": { + "excess_mana": 1316063562, + "mana_used": 111037651, + "proving_cost_per_mana_numerator": 873740990, + "fee_asset_price_numerator": 1361795236 + }, + "header": { + "excess_mana": 1327101213, + "mana_used": 92008411, + "proving_cost_per_mana_numerator": 898901189, + "fee_asset_price_numerator": 1044864044 + }, + "oracle_input": { + "proving_cost_modifier": 25160199, + "fee_asset_price_modifier": -316931192 + }, + "outputs": { + "fee_asset_price_at_execution": 10137110990, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32242202, + "proving_cost": 5462881471, + "congestion_cost": 20465204013, + "congestion_multiplier": 4724248121 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 326842780, + "proving_cost": 55377835796, + "congestion_cost": 207458044512, + "congestion_multiplier": 4724248121 + } + } + }, + { + "l1_block_number": 20974556, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9375339716 + }, + "parent_header": { + "excess_mana": 1327101213, + "mana_used": 92008411, + "proving_cost_per_mana_numerator": 898901189, + "fee_asset_price_numerator": 1044864044 + }, + "header": { + "excess_mana": 1319109624, + "mana_used": 102382194, + "proving_cost_per_mana_numerator": 1025217469, + "fee_asset_price_numerator": 1697126570 + }, + "oracle_input": { + "proving_cost_modifier": 126316280, + "fee_asset_price_modifier": 652262526 + }, + "outputs": { + "fee_asset_price_at_execution": 10105034181, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31055812, + "proving_cost": 5464256115, + "congestion_cost": 20224294915, + "congestion_multiplier": 4680281517 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 313820041, + "proving_cost": 55216494815, + "congestion_cost": 204367191402, + "congestion_multiplier": 4680281517 + } + } + }, + { + "l1_block_number": 20974559, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9597087327 + }, + "parent_header": { + "excess_mana": 1319109624, + "mana_used": 102382194, + "proving_cost_per_mana_numerator": 1025217469, + "fee_asset_price_numerator": 1697126570 + }, + "header": { + "excess_mana": 1321491818, + "mana_used": 110585080, + "proving_cost_per_mana_numerator": 988477843, + "fee_asset_price_numerator": 843566589 + }, + "oracle_input": { + "proving_cost_modifier": -36739626, + "fee_asset_price_modifier": -853559981 + }, + "outputs": { + "fee_asset_price_at_execution": 10171160957, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31790351, + "proving_cost": 5471162722, + "congestion_cost": 20324301130, + "congestion_multiplier": 4693344439 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 323344776, + "proving_cost": 55648076667, + "congestion_cost": 206721738131, + "congestion_multiplier": 4693344439 + } + } + }, + { + "l1_block_number": 20974562, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10268313101 + }, + "parent_header": { + "excess_mana": 1321491818, + "mana_used": 110585080, + "proving_cost_per_mana_numerator": 988477843, + "fee_asset_price_numerator": 843566589 + }, + "header": { + "excess_mana": 1332076898, + "mana_used": 92593419, + "proving_cost_per_mana_numerator": 932263532, + "fee_asset_price_numerator": 456153193 + }, + "oracle_input": { + "proving_cost_modifier": -56214311, + "fee_asset_price_modifier": -387413396 + }, + "outputs": { + "fee_asset_price_at_execution": 10084713463, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34013787, + "proving_cost": 5469153006, + "congestion_cost": 20646950577, + "congestion_multiplier": 4751830783 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 343019295, + "proving_cost": 55154840950, + "congestion_cost": 208218580453, + "congestion_multiplier": 4751830783 + } + } + }, + { + "l1_block_number": 20974565, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9810780355 + }, + "parent_header": { + "excess_mana": 1332076898, + "mana_used": 92593419, + "proving_cost_per_mana_numerator": 932263532, + "fee_asset_price_numerator": 456153193 + }, + "header": { + "excess_mana": 1324670317, + "mana_used": 90724497, + "proving_cost_per_mana_numerator": 794288972, + "fee_asset_price_numerator": 128315644 + }, + "oracle_input": { + "proving_cost_modifier": -137974560, + "fee_asset_price_modifier": -327837549 + }, + "outputs": { + "fee_asset_price_at_execution": 10045719515, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32498209, + "proving_cost": 5466079423, + "congestion_cost": 20404290947, + "congestion_multiplier": 4710830748 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 326467892, + "proving_cost": 54910700730, + "congestion_cost": 204975783756, + "congestion_multiplier": 4710830748 + } + } + }, + { + "l1_block_number": 20974568, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10144246321 + }, + "parent_header": { + "excess_mana": 1324670317, + "mana_used": 90724497, + "proving_cost_per_mana_numerator": 794288972, + "fee_asset_price_numerator": 128315644 + }, + "header": { + "excess_mana": 1315394814, + "mana_used": 111555165, + "proving_cost_per_mana_numerator": 868429096, + "fee_asset_price_numerator": 675668512 + }, + "oracle_input": { + "proving_cost_modifier": 74140124, + "fee_asset_price_modifier": 547352868 + }, + "outputs": { + "fee_asset_price_at_execution": 10012839800, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33602815, + "proving_cost": 5458542825, + "congestion_cost": 20101163092, + "congestion_multiplier": 4659983622 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 336459603, + "proving_cost": 54655514848, + "congestion_cost": 201269725833, + "congestion_multiplier": 4659983622 + } + } + }, + { + "l1_block_number": 20974571, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9686834828 + }, + "parent_header": { + "excess_mana": 1315394814, + "mana_used": 111555165, + "proving_cost_per_mana_numerator": 868429096, + "fee_asset_price_numerator": 675668512 + }, + "header": { + "excess_mana": 1326949979, + "mana_used": 99938676, + "proving_cost_per_mana_numerator": 896089675, + "fee_asset_price_numerator": 448902582 + }, + "oracle_input": { + "proving_cost_modifier": 27660579, + "fee_asset_price_modifier": -226765930 + }, + "outputs": { + "fee_asset_price_at_execution": 10067795630, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32087640, + "proving_cost": 5462591296, + "congestion_cost": 20458954959, + "congestion_multiplier": 4723412268 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 323051801, + "proving_cost": 54996252778, + "congestion_cost": 205976577330, + "congestion_multiplier": 4723412268 + } + } + }, + { + "l1_block_number": 20974574, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9943977596 + }, + "parent_header": { + "excess_mana": 1326949979, + "mana_used": 99938676, + "proving_cost_per_mana_numerator": 896089675, + "fee_asset_price_numerator": 448902582 + }, + "header": { + "excess_mana": 1326888655, + "mana_used": 99622249, + "proving_cost_per_mana_numerator": 877465442, + "fee_asset_price_numerator": 22204524 + }, + "oracle_input": { + "proving_cost_modifier": -18624233, + "fee_asset_price_modifier": -426698058 + }, + "outputs": { + "fee_asset_price_at_execution": 10044991165, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32939425, + "proving_cost": 5464102489, + "congestion_cost": 20465890418, + "congestion_multiplier": 4723073380 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 330876233, + "proving_cost": 54886861226, + "congestion_cost": 205579688432, + "congestion_multiplier": 4723073380 + } + } + }, + { + "l1_block_number": 20974577, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8945291339 + }, + "parent_header": { + "excess_mana": 1326888655, + "mana_used": 99622249, + "proving_cost_per_mana_numerator": 877465442, + "fee_asset_price_numerator": 22204524 + }, + "header": { + "excess_mana": 1326510904, + "mana_used": 84100471, + "proving_cost_per_mana_numerator": 805729104, + "fee_asset_price_numerator": 259780126 + }, + "oracle_input": { + "proving_cost_modifier": -71736338, + "fee_asset_price_modifier": 237575602 + }, + "outputs": { + "fee_asset_price_at_execution": 10002220698, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29631277, + "proving_cost": 5463084937, + "congestion_cost": 20438322281, + "congestion_multiplier": 4720986391 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 296378572, + "proving_cost": 54642981231, + "congestion_cost": 204428610151, + "congestion_multiplier": 4720986391 + } + } + }, + { + "l1_block_number": 20974580, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10038998201 + }, + "parent_header": { + "excess_mana": 1326510904, + "mana_used": 84100471, + "proving_cost_per_mana_numerator": 805729104, + "fee_asset_price_numerator": 259780126 + }, + "header": { + "excess_mana": 1310611375, + "mana_used": 103492289, + "proving_cost_per_mana_numerator": 792740469, + "fee_asset_price_numerator": 340660283 + }, + "oracle_input": { + "proving_cost_modifier": -12988635, + "fee_asset_price_modifier": 80880157 + }, + "outputs": { + "fee_asset_price_at_execution": 10026011784, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33254181, + "proving_cost": 5459167325, + "congestion_cost": 19959329538, + "congestion_multiplier": 4633976292 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 333406810, + "proving_cost": 54733675931, + "congestion_cost": 200112473148, + "congestion_multiplier": 4633976292 + } + } + }, + { + "l1_block_number": 20974583, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10272200406 + }, + "parent_header": { + "excess_mana": 1310611375, + "mana_used": 103492289, + "proving_cost_per_mana_numerator": 792740469, + "fee_asset_price_numerator": 340660283 + }, + "header": { + "excess_mana": 1314103664, + "mana_used": 0, + "proving_cost_per_mana_numerator": 668559792, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -124180677, + "fee_asset_price_modifier": -608328780 + }, + "outputs": { + "fee_asset_price_at_execution": 10034124118, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34026663, + "proving_cost": 5458458300, + "congestion_cost": 20063769391, + "congestion_multiplier": 4652949353 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 341427759, + "proving_cost": 54770848075, + "congestion_cost": 201322352344, + "congestion_multiplier": 4652949353 + } + } + }, + { + "l1_block_number": 20974586, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10159830088 + }, + "parent_header": { + "excess_mana": 1314103664, + "mana_used": 0, + "proving_cost_per_mana_numerator": 668559792, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1214103664, + "mana_used": 174322033, + "proving_cost_per_mana_numerator": 520915187, + "fee_asset_price_numerator": 191162968 + }, + "oracle_input": { + "proving_cost_modifier": -147644605, + "fee_asset_price_modifier": 191162968 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33654437, + "proving_cost": 5451684156, + "congestion_cost": 17219546656, + "congestion_multiplier": 4139194849 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 336544370, + "proving_cost": 54516841560, + "congestion_cost": 172195466560, + "congestion_multiplier": 4139194849 + } + } + }, + { + "l1_block_number": 20974589, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11362253728 + }, + "parent_header": { + "excess_mana": 1214103664, + "mana_used": 174322033, + "proving_cost_per_mana_numerator": 520915187, + "fee_asset_price_numerator": 191162968 + }, + "header": { + "excess_mana": 1288425697, + "mana_used": 118595109, + "proving_cost_per_mana_numerator": 416693447, + "fee_asset_price_numerator": 185644548 + }, + "oracle_input": { + "proving_cost_modifier": -104221740, + "fee_asset_price_modifier": -5518420 + }, + "outputs": { + "fee_asset_price_at_execution": 10019134580, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 37637465, + "proving_cost": 5443640978, + "congestion_cost": 19268002426, + "congestion_multiplier": 4515238758 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 377094827, + "proving_cost": 54540571563, + "congestion_cost": 193048709393, + "congestion_multiplier": 4515238758 + } + } + }, + { + "l1_block_number": 20974592, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10488705208 + }, + "parent_header": { + "excess_mana": 1288425697, + "mana_used": 118595109, + "proving_cost_per_mana_numerator": 416693447, + "fee_asset_price_numerator": 185644548 + }, + "header": { + "excess_mana": 1307020806, + "mana_used": 107609608, + "proving_cost_per_mana_numerator": 453557170, + "fee_asset_price_numerator": 619717024 + }, + "oracle_input": { + "proving_cost_modifier": 36863723, + "fee_asset_price_modifier": 434072476 + }, + "outputs": { + "fee_asset_price_at_execution": 10018581697, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34743836, + "proving_cost": 5437970476, + "congestion_cost": 19781399242, + "congestion_multiplier": 4614549950 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 348083959, + "proving_cost": 54480751479, + "congestion_cost": 198181564386, + "congestion_multiplier": 4614549950 + } + } + }, + { + "l1_block_number": 20974595, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9462366449 + }, + "parent_header": { + "excess_mana": 1307020806, + "mana_used": 107609608, + "proving_cost_per_mana_numerator": 453557170, + "fee_asset_price_numerator": 619717024 + }, + "header": { + "excess_mana": 1314630414, + "mana_used": 92131303, + "proving_cost_per_mana_numerator": 531888880, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 78331710, + "fee_asset_price_modifier": -692817214 + }, + "outputs": { + "fee_asset_price_at_execution": 10062164124, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31344088, + "proving_cost": 5439975484, + "congestion_cost": 20002147688, + "congestion_multiplier": 4655817838 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 315389357, + "proving_cost": 54737926150, + "congestion_cost": 201264892869, + "congestion_multiplier": 4655817838 + } + } + }, + { + "l1_block_number": 20974598, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9421740766 + }, + "parent_header": { + "excess_mana": 1314630414, + "mana_used": 92131303, + "proving_cost_per_mana_numerator": 531888880, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1306761717, + "mana_used": 103809271, + "proving_cost_per_mana_numerator": 538177512, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 6288632, + "fee_asset_price_modifier": -126737791 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31209516, + "proving_cost": 5444238379, + "congestion_cost": 19783621866, + "congestion_multiplier": 4613151334 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 312095160, + "proving_cost": 54442383790, + "congestion_cost": 197836218660, + "congestion_multiplier": 4613151334 + } + } + }, + { + "l1_block_number": 20974601, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9237341401 + }, + "parent_header": { + "excess_mana": 1306761717, + "mana_used": 103809271, + "proving_cost_per_mana_numerator": 538177512, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1310570988, + "mana_used": 113120852, + "proving_cost_per_mana_numerator": 543916368, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 5738856, + "fee_asset_price_modifier": -73019921 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30598693, + "proving_cost": 5444580758, + "congestion_cost": 19895473457, + "congestion_multiplier": 4633757329 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 305986930, + "proving_cost": 54445807580, + "congestion_cost": 198954734570, + "congestion_multiplier": 4633757329 + } + } + }, + { + "l1_block_number": 20974604, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10238465003 + }, + "parent_header": { + "excess_mana": 1310570988, + "mana_used": 113120852, + "proving_cost_per_mana_numerator": 543916368, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1323691840, + "mana_used": 92397177, + "proving_cost_per_mana_numerator": 426314838, + "fee_asset_price_numerator": 243102440 + }, + "oracle_input": { + "proving_cost_modifier": -117601530, + "fee_asset_price_modifier": 243102440 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33914915, + "proving_cost": 5444893224, + "congestion_cost": 20301399153, + "congestion_multiplier": 4705440789 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 339149150, + "proving_cost": 54448932240, + "congestion_cost": 203013991530, + "congestion_multiplier": 4705440789 + } + } + }, + { + "l1_block_number": 20974607, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9761510720 + }, + "parent_header": { + "excess_mana": 1323691840, + "mana_used": 92397177, + "proving_cost_per_mana_numerator": 426314838, + "fee_asset_price_numerator": 243102440 + }, + "header": { + "excess_mana": 1316089017, + "mana_used": 101644078, + "proving_cost_per_mana_numerator": 570636341, + "fee_asset_price_numerator": 609906024 + }, + "oracle_input": { + "proving_cost_modifier": 144321503, + "fee_asset_price_modifier": 366803584 + }, + "outputs": { + "fee_asset_price_at_execution": 10024339817, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32335004, + "proving_cost": 5438493710, + "congestion_cost": 20043858555, + "congestion_multiplier": 4663770080 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 324137068, + "proving_cost": 54517309041, + "congestion_cost": 200926449399, + "congestion_multiplier": 4663770080 + } + } + }, + { + "l1_block_number": 20974610, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9386744044 + }, + "parent_header": { + "excess_mana": 1316089017, + "mana_used": 101644078, + "proving_cost_per_mana_numerator": 570636341, + "fee_asset_price_numerator": 609906024 + }, + "header": { + "excess_mana": 1317733095, + "mana_used": 92675049, + "proving_cost_per_mana_numerator": 666417343, + "fee_asset_price_numerator": 832510984 + }, + "oracle_input": { + "proving_cost_modifier": 95781002, + "fee_asset_price_modifier": 222604960 + }, + "outputs": { + "fee_asset_price_at_execution": 10061176973, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31093589, + "proving_cost": 5446348292, + "congestion_cost": 20117273616, + "congestion_multiplier": 4672749808 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 312838101, + "proving_cost": 54796674022, + "congestion_cost": 202403450064, + "congestion_multiplier": 4672749808 + } + } + }, + { + "l1_block_number": 20974613, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9635997754 + }, + "parent_header": { + "excess_mana": 1317733095, + "mana_used": 92675049, + "proving_cost_per_mana_numerator": 666417343, + "fee_asset_price_numerator": 832510984 + }, + "header": { + "excess_mana": 1310408144, + "mana_used": 98945719, + "proving_cost_per_mana_numerator": 637579467, + "fee_asset_price_numerator": 78183892 + }, + "oracle_input": { + "proving_cost_modifier": -28837876, + "fee_asset_price_modifier": -754327092 + }, + "outputs": { + "fee_asset_price_at_execution": 10083598599, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31919242, + "proving_cost": 5451567358, + "congestion_cost": 19920818941, + "congestion_multiplier": 4632874555 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 321860823, + "proving_cost": 54971416973, + "congestion_cost": 200873541964, + "congestion_multiplier": 4632874555 + } + } + }, + { + "l1_block_number": 20974616, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9497835793 + }, + "parent_header": { + "excess_mana": 1310408144, + "mana_used": 98945719, + "proving_cost_per_mana_numerator": 637579467, + "fee_asset_price_numerator": 78183892 + }, + "header": { + "excess_mana": 1309353863, + "mana_used": 104843069, + "proving_cost_per_mana_numerator": 727519356, + "fee_asset_price_numerator": 219999797 + }, + "oracle_input": { + "proving_cost_modifier": 89939889, + "fee_asset_price_modifier": 141815905 + }, + "outputs": { + "fee_asset_price_at_execution": 10007821446, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31461581, + "proving_cost": 5449995468, + "congestion_cost": 19882140315, + "congestion_multiplier": 4627163387 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 314861885, + "proving_cost": 54542581525, + "congestion_cost": 198976910236, + "congestion_multiplier": 4627163387 + } + } + }, + { + "l1_block_number": 20974619, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9784258718 + }, + "parent_header": { + "excess_mana": 1309353863, + "mana_used": 104843069, + "proving_cost_per_mana_numerator": 727519356, + "fee_asset_price_numerator": 219999797 + }, + "header": { + "excess_mana": 1314196932, + "mana_used": 108701348, + "proving_cost_per_mana_numerator": 695500631, + "fee_asset_price_numerator": 352336839 + }, + "oracle_input": { + "proving_cost_modifier": -32018725, + "fee_asset_price_modifier": 132337042 + }, + "outputs": { + "fee_asset_price_at_execution": 10022024197, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32410357, + "proving_cost": 5454899393, + "congestion_cost": 20047650914, + "congestion_multiplier": 4653457127 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 324817382, + "proving_cost": 54669133708, + "congestion_cost": 200918042553, + "congestion_multiplier": 4653457127 + } + } + }, + { + "l1_block_number": 20974622, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9822631866 + }, + "parent_header": { + "excess_mana": 1314196932, + "mana_used": 108701348, + "proving_cost_per_mana_numerator": 695500631, + "fee_asset_price_numerator": 352336839 + }, + "header": { + "excess_mana": 1322898280, + "mana_used": 91385697, + "proving_cost_per_mana_numerator": 809869333, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 114368702, + "fee_asset_price_modifier": -624014969 + }, + "outputs": { + "fee_asset_price_at_execution": 10035295827, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32537468, + "proving_cost": 5453153084, + "congestion_cost": 20302946558, + "congestion_multiplier": 4701073979 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 326523116, + "proving_cost": 54724004387, + "congestion_cost": 203746074869, + "congestion_multiplier": 4701073979 + } + } + }, + { + "l1_block_number": 20974625, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10157914688 + }, + "parent_header": { + "excess_mana": 1322898280, + "mana_used": 91385697, + "proving_cost_per_mana_numerator": 809869333, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1314283977, + "mana_used": 116675075, + "proving_cost_per_mana_numerator": 782149905, + "fee_asset_price_numerator": 622366323 + }, + "oracle_input": { + "proving_cost_modifier": -27719428, + "fee_asset_price_modifier": 622366323 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33648092, + "proving_cost": 5459393352, + "congestion_cost": 20071194812, + "congestion_multiplier": 4653931072 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 336480920, + "proving_cost": 54593933520, + "congestion_cost": 200711948120, + "congestion_multiplier": 4653931072 + } + } + }, + { + "l1_block_number": 20974628, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10107349159 + }, + "parent_header": { + "excess_mana": 1314283977, + "mana_used": 116675075, + "proving_cost_per_mana_numerator": 782149905, + "fee_asset_price_numerator": 622366323 + }, + "header": { + "excess_mana": 1330959052, + "mana_used": 26049996, + "proving_cost_per_mana_numerator": 742577896, + "fee_asset_price_numerator": 880139489 + }, + "oracle_input": { + "proving_cost_modifier": -39572009, + "fee_asset_price_modifier": 257773166 + }, + "outputs": { + "fee_asset_price_at_execution": 10062430704, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33480594, + "proving_cost": 5457880249, + "congestion_cost": 20568551121, + "congestion_multiplier": 4745620022 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 336896157, + "proving_cost": 54919541796, + "congestion_cost": 206969620336, + "congestion_multiplier": 4745620022 + } + } + }, + { + "l1_block_number": 20974631, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9986090744 + }, + "parent_header": { + "excess_mana": 1330959052, + "mana_used": 26049996, + "proving_cost_per_mana_numerator": 742577896, + "fee_asset_price_numerator": 880139489 + }, + "header": { + "excess_mana": 1257009048, + "mana_used": 151212674, + "proving_cost_per_mana_numerator": 809308729, + "fee_asset_price_numerator": 870419648 + }, + "oracle_input": { + "proving_cost_modifier": 66730833, + "fee_asset_price_modifier": -9719841 + }, + "outputs": { + "fee_asset_price_at_execution": 10088402410, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33078925, + "proving_cost": 5455720883, + "congestion_cost": 18400011532, + "congestion_multiplier": 4352283227 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 333713506, + "proving_cost": 55039507704, + "congestion_cost": 185626720683, + "congestion_multiplier": 4352283227 + } + } + }, + { + "l1_block_number": 20974634, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10010324507 + }, + "parent_header": { + "excess_mana": 1257009048, + "mana_used": 151212674, + "proving_cost_per_mana_numerator": 809308729, + "fee_asset_price_numerator": 870419648 + }, + "header": { + "excess_mana": 1308221722, + "mana_used": 101948161, + "proving_cost_per_mana_numerator": 809758637, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 449908, + "fee_asset_price_modifier": -1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10087421881, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33159199, + "proving_cost": 5459362746, + "congestion_cost": 19888632222, + "congestion_multiplier": 4621038281 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 334490829, + "proving_cost": 55070895220, + "congestion_cost": 200625023859, + "congestion_multiplier": 4621038281 + } + } + }, + { + "l1_block_number": 20974637, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10017086529 + }, + "parent_header": { + "excess_mana": 1308221722, + "mana_used": 101948161, + "proving_cost_per_mana_numerator": 809758637, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1310169883, + "mana_used": 111174043, + "proving_cost_per_mana_numerator": 741892216, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -67866421, + "fee_asset_price_modifier": -726341690 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33181599, + "proving_cost": 5459387308, + "congestion_cost": 19946721242, + "congestion_multiplier": 4631583250 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 331815990, + "proving_cost": 54593873080, + "congestion_cost": 199467212420, + "congestion_multiplier": 4631583250 + } + } + }, + { + "l1_block_number": 20974640, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10370308177 + }, + "parent_header": { + "excess_mana": 1310169883, + "mana_used": 111174043, + "proving_cost_per_mana_numerator": 741892216, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1321343926, + "mana_used": 94802248, + "proving_cost_per_mana_numerator": 773959935, + "fee_asset_price_numerator": 114448902 + }, + "oracle_input": { + "proving_cost_modifier": 32067719, + "fee_asset_price_modifier": 114448902 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34351645, + "proving_cost": 5455683475, + "congestion_cost": 20272132568, + "congestion_multiplier": 4692532402 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 343516450, + "proving_cost": 54556834750, + "congestion_cost": 202721325680, + "congestion_multiplier": 4692532402 + } + } + }, + { + "l1_block_number": 20974643, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10404764610 + }, + "parent_header": { + "excess_mana": 1321343926, + "mana_used": 94802248, + "proving_cost_per_mana_numerator": 773959935, + "fee_asset_price_numerator": 114448902 + }, + "header": { + "excess_mana": 1316146174, + "mana_used": 109144403, + "proving_cost_per_mana_numerator": 798378003, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 24418068, + "fee_asset_price_modifier": -501532851 + }, + "outputs": { + "fee_asset_price_at_execution": 10011451441, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34465782, + "proving_cost": 5457433268, + "congestion_cost": 20122768312, + "congestion_multiplier": 4664081974 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 345052502, + "proving_cost": 54636828155, + "congestion_cost": 201458117814, + "congestion_multiplier": 4664081974 + } + } + }, + { + "l1_block_number": 20974646, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10629066393 + }, + "parent_header": { + "excess_mana": 1316146174, + "mana_used": 109144403, + "proving_cost_per_mana_numerator": 798378003, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1325290577, + "mana_used": 34899899, + "proving_cost_per_mana_numerator": 839834293, + "fee_asset_price_numerator": 457917274 + }, + "oracle_input": { + "proving_cost_modifier": 41456290, + "fee_asset_price_modifier": 457917274 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35208782, + "proving_cost": 5458766031, + "congestion_cost": 20405999564, + "congestion_multiplier": 4714250658 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 352087820, + "proving_cost": 54587660310, + "congestion_cost": 204059995640, + "congestion_multiplier": 4714250658 + } + } + }, + { + "l1_block_number": 20974649, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10631215552 + }, + "parent_header": { + "excess_mana": 1325290577, + "mana_used": 34899899, + "proving_cost_per_mana_numerator": 839834293, + "fee_asset_price_numerator": 457917274 + }, + "header": { + "excess_mana": 1260190476, + "mana_used": 128319221, + "proving_cost_per_mana_numerator": 981905891, + "fee_asset_price_numerator": 1121443867 + }, + "oracle_input": { + "proving_cost_modifier": 142071598, + "fee_asset_price_modifier": 663526593 + }, + "outputs": { + "fee_asset_price_at_execution": 10045896731, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35215901, + "proving_cost": 5461029502, + "congestion_cost": 18514178449, + "congestion_multiplier": 4368513793 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 353775304, + "proving_cost": 54860938422, + "congestion_cost": 185991524757, + "congestion_multiplier": 4368513793 + } + } + }, + { + "l1_block_number": 20974652, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10463260499 + }, + "parent_header": { + "excess_mana": 1260190476, + "mana_used": 128319221, + "proving_cost_per_mana_numerator": 981905891, + "fee_asset_price_numerator": 1121443867 + }, + "header": { + "excess_mana": 1288509697, + "mana_used": 124344163, + "proving_cost_per_mana_numerator": 835441805, + "fee_asset_price_numerator": 944547786 + }, + "oracle_input": { + "proving_cost_modifier": -146464086, + "fee_asset_price_modifier": -176896081 + }, + "outputs": { + "fee_asset_price_at_execution": 10112775562, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34659550, + "proving_cost": 5468793588, + "congestion_cost": 19348394095, + "congestion_multiplier": 4515682538 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 350504250, + "proving_cost": 55304682150, + "congestion_cost": 195665966967, + "congestion_multiplier": 4515682538 + } + } + }, + { + "l1_block_number": 20974655, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10685244750 + }, + "parent_header": { + "excess_mana": 1288509697, + "mana_used": 124344163, + "proving_cost_per_mana_numerator": 835441805, + "fee_asset_price_numerator": 944547786 + }, + "header": { + "excess_mana": 1312853860, + "mana_used": 102282782, + "proving_cost_per_mana_numerator": 809561222, + "fee_asset_price_numerator": 1057140318 + }, + "oracle_input": { + "proving_cost_modifier": -25880583, + "fee_asset_price_modifier": 112592532 + }, + "outputs": { + "fee_asset_price_at_execution": 10094902271, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35394873, + "proving_cost": 5460789632, + "congestion_cost": 20039915628, + "congestion_multiplier": 4646150454 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 357307783, + "proving_cost": 55126137657, + "congestion_cost": 202300989783, + "congestion_multiplier": 4646150454 + } + } + }, + { + "l1_block_number": 20974658, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10095519528 + }, + "parent_header": { + "excess_mana": 1312853860, + "mana_used": 102282782, + "proving_cost_per_mana_numerator": 809561222, + "fee_asset_price_numerator": 1057140318 + }, + "header": { + "excess_mana": 1315136642, + "mana_used": 92935415, + "proving_cost_per_mana_numerator": 706535974, + "fee_asset_price_numerator": 1963428252 + }, + "oracle_input": { + "proving_cost_modifier": -103025248, + "fee_asset_price_modifier": 906287934 + }, + "outputs": { + "fee_asset_price_at_execution": 10106274778, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33441408, + "proving_cost": 5459376531, + "congestion_cost": 20095893169, + "congestion_multiplier": 4658576234 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 337968058, + "proving_cost": 55173959338, + "congestion_cost": 203094618275, + "congestion_multiplier": 4658576234 + } + } + }, + { + "l1_block_number": 20974661, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9964934916 + }, + "parent_header": { + "excess_mana": 1315136642, + "mana_used": 92935415, + "proving_cost_per_mana_numerator": 706535974, + "fee_asset_price_numerator": 1963428252 + }, + "header": { + "excess_mana": 1308072057, + "mana_used": 6890906, + "proving_cost_per_mana_numerator": 553003059, + "fee_asset_price_numerator": 1708530634 + }, + "oracle_input": { + "proving_cost_modifier": -153532915, + "fee_asset_price_modifier": -254897618 + }, + "outputs": { + "fee_asset_price_at_execution": 10198283027, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33008846, + "proving_cost": 5453754891, + "congestion_cost": 19863342129, + "congestion_multiplier": 4620229170 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 336633553, + "proving_cost": 55618935938, + "congestion_cost": 202571984893, + "congestion_multiplier": 4620229170 + } + } + }, + { + "l1_block_number": 20974664, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9868829086 + }, + "parent_header": { + "excess_mana": 1308072057, + "mana_used": 6890906, + "proving_cost_per_mana_numerator": 553003059, + "fee_asset_price_numerator": 1708530634 + }, + "header": { + "excess_mana": 1214962963, + "mana_used": 191542383, + "proving_cost_per_mana_numerator": 649849607, + "fee_asset_price_numerator": 2185828457 + }, + "oracle_input": { + "proving_cost_modifier": 96846548, + "fee_asset_price_modifier": 477297823 + }, + "outputs": { + "fee_asset_price_at_execution": 10172320949, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32690496, + "proving_cost": 5445388007, + "congestion_cost": 17219564100, + "congestion_multiplier": 4143358404 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 332538217, + "proving_cost": 55392234499, + "congestion_cost": 175162932627, + "congestion_multiplier": 4143358404 + } + } + }, + { + "l1_block_number": 20974667, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9796157813 + }, + "parent_header": { + "excess_mana": 1214962963, + "mana_used": 191542383, + "proving_cost_per_mana_numerator": 649849607, + "fee_asset_price_numerator": 2185828457 + }, + "header": { + "excess_mana": 1306505346, + "mana_used": 112909870, + "proving_cost_per_mana_numerator": 576325080, + "fee_asset_price_numerator": 2027932310 + }, + "oracle_input": { + "proving_cost_modifier": -73524527, + "fee_asset_price_modifier": -157896147 + }, + "outputs": { + "fee_asset_price_at_execution": 10220989270, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32449772, + "proving_cost": 5450664231, + "congestion_cost": 19803734643, + "congestion_multiplier": 4611767808 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 331668771, + "proving_cost": 55711180619, + "congestion_cost": 202413759292, + "congestion_multiplier": 4611767808 + } + } + }, + { + "l1_block_number": 20974670, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9423895660 + }, + "parent_header": { + "excess_mana": 1306505346, + "mana_used": 112909870, + "proving_cost_per_mana_numerator": 576325080, + "fee_asset_price_numerator": 2027932310 + }, + "header": { + "excess_mana": 1319415216, + "mana_used": 88953936, + "proving_cost_per_mana_numerator": 561262646, + "fee_asset_price_numerator": 2413894340 + }, + "oracle_input": { + "proving_cost_modifier": -15062434, + "fee_asset_price_modifier": 385962030 + }, + "outputs": { + "fee_asset_price_at_execution": 10204863456, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31216654, + "proving_cost": 5446658129, + "congestion_cost": 20169289629, + "congestion_multiplier": 4681955216 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 318561691, + "proving_cost": 55582402497, + "congestion_cost": 205824846668, + "congestion_multiplier": 4681955216 + } + } + }, + { + "l1_block_number": 20974673, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8779402628 + }, + "parent_header": { + "excess_mana": 1319415216, + "mana_used": 88953936, + "proving_cost_per_mana_numerator": 561262646, + "fee_asset_price_numerator": 2413894340 + }, + "header": { + "excess_mana": 1308369152, + "mana_used": 108956671, + "proving_cost_per_mana_numerator": 561045656, + "fee_asset_price_numerator": 1553870436 + }, + "oracle_input": { + "proving_cost_modifier": -216990, + "fee_asset_price_modifier": -860023904 + }, + "outputs": { + "fee_asset_price_at_execution": 10244326461, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29081771, + "proving_cost": 5445837792, + "congestion_cost": 19829257737, + "congestion_multiplier": 4621835446 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 297923156, + "proving_cost": 55788940194, + "congestion_cost": 203137389737, + "congestion_multiplier": 4621835446 + } + } + }, + { + "l1_block_number": 20974676, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9296854474 + }, + "parent_header": { + "excess_mana": 1308369152, + "mana_used": 108956671, + "proving_cost_per_mana_numerator": 561045656, + "fee_asset_price_numerator": 1553870436 + }, + "header": { + "excess_mana": 1317325823, + "mana_used": 94389617, + "proving_cost_per_mana_numerator": 550791710, + "fee_asset_price_numerator": 769518212 + }, + "oracle_input": { + "proving_cost_modifier": -10253946, + "fee_asset_price_modifier": -784352224 + }, + "outputs": { + "fee_asset_price_at_execution": 10156600577, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30795830, + "proving_cost": 5445825975, + "congestion_cost": 20102070317, + "congestion_multiplier": 4670523734 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 312780944, + "proving_cost": 55311079239, + "congestion_cost": 204168698980, + "congestion_multiplier": 4670523734 + } + } + }, + { + "l1_block_number": 20974679, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9564836737 + }, + "parent_header": { + "excess_mana": 1317325823, + "mana_used": 94389617, + "proving_cost_per_mana_numerator": 550791710, + "fee_asset_price_numerator": 769518212 + }, + "header": { + "excess_mana": 1311715440, + "mana_used": 102928262, + "proving_cost_per_mana_numerator": 576833814, + "fee_asset_price_numerator": 741678651 + }, + "oracle_input": { + "proving_cost_modifier": 26042104, + "fee_asset_price_modifier": -27839561 + }, + "outputs": { + "fee_asset_price_at_execution": 10077248661, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31683521, + "proving_cost": 5445267591, + "congestion_cost": 19935916526, + "congestion_multiplier": 4639966127 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 319282719, + "proving_cost": 54873315540, + "congestion_cost": 200899188117, + "congestion_multiplier": 4639966127 + } + } + }, + { + "l1_block_number": 20974682, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9381667937 + }, + "parent_header": { + "excess_mana": 1311715440, + "mana_used": 102928262, + "proving_cost_per_mana_numerator": 576833814, + "fee_asset_price_numerator": 741678651 + }, + "header": { + "excess_mana": 1314643702, + "mana_used": 108617085, + "proving_cost_per_mana_numerator": 526666518, + "fee_asset_price_numerator": 351476175 + }, + "oracle_input": { + "proving_cost_modifier": -50167296, + "fee_asset_price_modifier": -390202476 + }, + "outputs": { + "fee_asset_price_at_execution": 10074443589, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31076775, + "proving_cost": 5446685838, + "congestion_cost": 20026098775, + "congestion_multiplier": 4655890222 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 313081216, + "proving_cost": 54872329221, + "congestion_cost": 201751802416, + "congestion_multiplier": 4655890222 + } + } + }, + { + "l1_block_number": 20974685, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10397713754 + }, + "parent_header": { + "excess_mana": 1314643702, + "mana_used": 108617085, + "proving_cost_per_mana_numerator": 526666518, + "fee_asset_price_numerator": 351476175 + }, + "header": { + "excess_mana": 1323260787, + "mana_used": 31017300, + "proving_cost_per_mana_numerator": 449660495, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -77006023, + "fee_asset_price_modifier": -788587719 + }, + "outputs": { + "fee_asset_price_at_execution": 10035209457, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34442426, + "proving_cost": 5443954069, + "congestion_cost": 20286876302, + "congestion_multiplier": 4703068283 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 345636959, + "proving_cost": 54631219356, + "congestion_cost": 203583052918, + "congestion_multiplier": 4703068283 + } + } + }, + { + "l1_block_number": 20974688, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9445339829 + }, + "parent_header": { + "excess_mana": 1323260787, + "mana_used": 31017300, + "proving_cost_per_mana_numerator": 449660495, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1254278087, + "mana_used": 141703611, + "proving_cost_per_mana_numerator": 494464778, + "fee_asset_price_numerator": 227098236 + }, + "oracle_input": { + "proving_cost_modifier": 44804283, + "fee_asset_price_modifier": 227098236 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31287688, + "proving_cost": 5439763510, + "congestion_cost": 18264551295, + "congestion_multiplier": 4338398899 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 312876880, + "proving_cost": 54397635100, + "congestion_cost": 182645512950, + "congestion_multiplier": 4338398899 + } + } + }, + { + "l1_block_number": 20974691, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9351751903 + }, + "parent_header": { + "excess_mana": 1254278087, + "mana_used": 141703611, + "proving_cost_per_mana_numerator": 494464778, + "fee_asset_price_numerator": 227098236 + }, + "header": { + "excess_mana": 1295981698, + "mana_used": 112723984, + "proving_cost_per_mana_numerator": 379373842, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -115090936, + "fee_asset_price_modifier": -707254472 + }, + "outputs": { + "fee_asset_price_at_execution": 10022735629, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30977678, + "proving_cost": 5442201303, + "congestion_cost": 19458972680, + "congestion_multiplier": 4555332787 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 310481076, + "proving_cost": 54545744899, + "congestion_cost": 195032138783, + "congestion_multiplier": 4555332787 + } + } + }, + { + "l1_block_number": 20974694, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9403513294 + }, + "parent_header": { + "excess_mana": 1295981698, + "mana_used": 112723984, + "proving_cost_per_mana_numerator": 379373842, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1308705682, + "mana_used": 106107340, + "proving_cost_per_mana_numerator": 487357271, + "fee_asset_price_numerator": 873296007 + }, + "oracle_input": { + "proving_cost_modifier": 107983429, + "fee_asset_price_modifier": 873296007 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31149137, + "proving_cost": 5435941425, + "congestion_cost": 19810853368, + "congestion_multiplier": 4623655607 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 311491370, + "proving_cost": 54359414250, + "congestion_cost": 198108533680, + "congestion_multiplier": 4623655607 + } + } + }, + { + "l1_block_number": 20974697, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10065091506 + }, + "parent_header": { + "excess_mana": 1308705682, + "mana_used": 106107340, + "proving_cost_per_mana_numerator": 487357271, + "fee_asset_price_numerator": 873296007 + }, + "header": { + "excess_mana": 1314813022, + "mana_used": 102389524, + "proving_cost_per_mana_numerator": 476280958, + "fee_asset_price_numerator": 16767761 + }, + "oracle_input": { + "proving_cost_modifier": -11076313, + "fee_asset_price_modifier": -856528246 + }, + "outputs": { + "fee_asset_price_at_execution": 10087712036, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33340615, + "proving_cost": 5441814512, + "congestion_cost": 20021616616, + "congestion_multiplier": 4656812666 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 336330523, + "proving_cost": 54895457750, + "congestion_cost": 201972302917, + "congestion_multiplier": 4656812666 + } + } + }, + { + "l1_block_number": 20974700, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9772465608 + }, + "parent_header": { + "excess_mana": 1314813022, + "mana_used": 102389524, + "proving_cost_per_mana_numerator": 476280958, + "fee_asset_price_numerator": 16767761 + }, + "header": { + "excess_mana": 1317202546, + "mana_used": 106334484, + "proving_cost_per_mana_numerator": 284814652, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -191466306, + "fee_asset_price_modifier": -345823326 + }, + "outputs": { + "fee_asset_price_at_execution": 10001676916, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32371292, + "proving_cost": 5441211793, + "congestion_cost": 20087229617, + "congestion_multiplier": 4669850134 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 323767203, + "proving_cost": 54421242385, + "congestion_cost": 200905980766, + "congestion_multiplier": 4669850134 + } + } + }, + { + "l1_block_number": 20974703, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10113104790 + }, + "parent_header": { + "excess_mana": 1317202546, + "mana_used": 106334484, + "proving_cost_per_mana_numerator": 284814652, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1323537030, + "mana_used": 106033158, + "proving_cost_per_mana_numerator": 315246449, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": 30431797, + "fee_asset_price_modifier": -538742087 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33499659, + "proving_cost": 5430803673, + "congestion_cost": 20242995726, + "congestion_multiplier": 4704588581 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 334996590, + "proving_cost": 54308036730, + "congestion_cost": 202429957260, + "congestion_multiplier": 4704588581 + } + } + }, + { + "l1_block_number": 20974706, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9897877678 + }, + "parent_header": { + "excess_mana": 1323537030, + "mana_used": 106033158, + "proving_cost_per_mana_numerator": 315246449, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1329570188, + "mana_used": 100781150, + "proving_cost_per_mana_numerator": 210183547, + "fee_asset_price_numerator": 0 + }, + "oracle_input": { + "proving_cost_modifier": -105062902, + "fee_asset_price_modifier": -356469643 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32786719, + "proving_cost": 5432456615, + "congestion_cost": 20428613889, + "congestion_multiplier": 4737914790 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 327867190, + "proving_cost": 54324566150, + "congestion_cost": 204286138890, + "congestion_multiplier": 4737914790 + } + } + }, + { + "l1_block_number": 20974709, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9638505207 + }, + "parent_header": { + "excess_mana": 1329570188, + "mana_used": 100781150, + "proving_cost_per_mana_numerator": 210183547, + "fee_asset_price_numerator": 0 + }, + "header": { + "excess_mana": 1330351338, + "mana_used": 90026211, + "proving_cost_per_mana_numerator": 216028422, + "fee_asset_price_numerator": 889353403 + }, + "oracle_input": { + "proving_cost_modifier": 5844875, + "fee_asset_price_modifier": 889353403 + }, + "outputs": { + "fee_asset_price_at_execution": 10000000000, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31927548, + "proving_cost": 5426752116, + "congestion_cost": 20427727405, + "congestion_multiplier": 4742246965 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 319275480, + "proving_cost": 54267521160, + "congestion_cost": 204277274050, + "congestion_multiplier": 4742246965 + } + } + }, + { + "l1_block_number": 20974712, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9788093852 + }, + "parent_header": { + "excess_mana": 1330351338, + "mana_used": 90026211, + "proving_cost_per_mana_numerator": 216028422, + "fee_asset_price_numerator": 889353403 + }, + "header": { + "excess_mana": 1320377549, + "mana_used": 96281835, + "proving_cost_per_mana_numerator": 90907125, + "fee_asset_price_numerator": 874788918 + }, + "oracle_input": { + "proving_cost_modifier": -125121297, + "fee_asset_price_modifier": -14564485 + }, + "outputs": { + "fee_asset_price_at_execution": 10089331990, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32423060, + "proving_cost": 5427069312, + "congestion_cost": 20130402622, + "congestion_multiplier": 4687229737 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 327127016, + "proving_cost": 54755504021, + "congestion_cost": 203102315145, + "congestion_multiplier": 4687229737 + } + } + }, + { + "l1_block_number": 20974715, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9591156391 + }, + "parent_header": { + "excess_mana": 1320377549, + "mana_used": 96281835, + "proving_cost_per_mana_numerator": 90907125, + "fee_asset_price_numerator": 874788918 + }, + "header": { + "excess_mana": 1316659384, + "mana_used": 98802156, + "proving_cost_per_mana_numerator": 226700020, + "fee_asset_price_numerator": 1227720857 + }, + "oracle_input": { + "proving_cost_modifier": 135792895, + "fee_asset_price_modifier": 352931939 + }, + "outputs": { + "fee_asset_price_at_execution": 10087862637, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31770705, + "proving_cost": 5420283139, + "congestion_cost": 19992045676, + "congestion_multiplier": 4666883389 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 320498507, + "proving_cost": 54679071759, + "congestion_cost": 201677010612, + "congestion_multiplier": 4666883389 + } + } + }, + { + "l1_block_number": 20974718, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10060943500 + }, + "parent_header": { + "excess_mana": 1316659384, + "mana_used": 98802156, + "proving_cost_per_mana_numerator": 226700020, + "fee_asset_price_numerator": 1227720857 + }, + "header": { + "excess_mana": 1315461540, + "mana_used": 103467904, + "proving_cost_per_mana_numerator": 177575230, + "fee_asset_price_numerator": 1609108682 + }, + "oracle_input": { + "proving_cost_modifier": -49124790, + "fee_asset_price_modifier": 381387825 + }, + "outputs": { + "fee_asset_price_at_execution": 10123528828, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33326875, + "proving_cost": 5427648498, + "congestion_cost": 19989067215, + "congestion_multiplier": 4660347438 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 337385579, + "proving_cost": 54946956037, + "congestion_cost": 202359898195, + "congestion_multiplier": 4660347438 + } + } + }, + { + "l1_block_number": 20974721, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9931038619 + }, + "parent_header": { + "excess_mana": 1315461540, + "mana_used": 103467904, + "proving_cost_per_mana_numerator": 177575230, + "fee_asset_price_numerator": 1609108682 + }, + "header": { + "excess_mana": 1318929444, + "mana_used": 93820858, + "proving_cost_per_mana_numerator": 132035391, + "fee_asset_price_numerator": 1963088223 + }, + "oracle_input": { + "proving_cost_modifier": -45539839, + "fee_asset_price_modifier": 353979541 + }, + "outputs": { + "fee_asset_price_at_execution": 10162212455, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32896565, + "proving_cost": 5424982832, + "congestion_cost": 20081148201, + "congestion_multiplier": 4679294968 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 334301882, + "proving_cost": 55129828103, + "congestion_cost": 204068894358, + "congestion_multiplier": 4679294968 + } + } + }, + { + "l1_block_number": 20974724, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9547223674 + }, + "parent_header": { + "excess_mana": 1318929444, + "mana_used": 93820858, + "proving_cost_per_mana_numerator": 132035391, + "fee_asset_price_numerator": 1963088223 + }, + "header": { + "excess_mana": 1312750302, + "mana_used": 102433545, + "proving_cost_per_mana_numerator": 272099285, + "fee_asset_price_numerator": 2000138379 + }, + "oracle_input": { + "proving_cost_modifier": 140063894, + "fee_asset_price_modifier": 37050156 + }, + "outputs": { + "fee_asset_price_at_execution": 10198248350, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31625178, + "proving_cost": 5422512866, + "congestion_cost": 19883537732, + "congestion_multiplier": 4645587547 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 322521419, + "proving_cost": 55300132888, + "congestion_cost": 202777255867, + "congestion_multiplier": 4645587547 + } + } + }, + { + "l1_block_number": 20974727, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9057659802 + }, + "parent_header": { + "excess_mana": 1312750302, + "mana_used": 102433545, + "proving_cost_per_mana_numerator": 272099285, + "fee_asset_price_numerator": 2000138379 + }, + "header": { + "excess_mana": 1315183847, + "mana_used": 91742261, + "proving_cost_per_mana_numerator": 216089885, + "fee_asset_price_numerator": 2258197541 + }, + "oracle_input": { + "proving_cost_modifier": -56009400, + "fee_asset_price_modifier": 258059162 + }, + "outputs": { + "fee_asset_price_at_execution": 10202027517, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30003498, + "proving_cost": 5430113170, + "congestion_cost": 19977657964, + "congestion_multiplier": 4658833534 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 306096512, + "proving_cost": 55398163980, + "congestion_cost": 203812616273, + "congestion_multiplier": 4658833534 + } + } + }, + { + "l1_block_number": 20974730, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9445297033 + }, + "parent_header": { + "excess_mana": 1315183847, + "mana_used": 91742261, + "proving_cost_per_mana_numerator": 216089885, + "fee_asset_price_numerator": 2258197541 + }, + "header": { + "excess_mana": 1306926108, + "mana_used": 120537598, + "proving_cost_per_mana_numerator": 134913303, + "fee_asset_price_numerator": 1887680484 + }, + "oracle_input": { + "proving_cost_modifier": -81176582, + "fee_asset_price_modifier": -370517057 + }, + "outputs": { + "fee_asset_price_at_execution": 10228388783, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31287546, + "proving_cost": 5427072648, + "congestion_cost": 19726724985, + "congestion_multiplier": 4614038701 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 320021184, + "proving_cost": 55510208997, + "congestion_cost": 201772612561, + "congestion_multiplier": 4614038701 + } + } + }, + { + "l1_block_number": 20974733, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9930049927 + }, + "parent_header": { + "excess_mana": 1306926108, + "mana_used": 120537598, + "proving_cost_per_mana_numerator": 134913303, + "fee_asset_price_numerator": 1887680484 + }, + "header": { + "excess_mana": 1327463706, + "mana_used": 92120356, + "proving_cost_per_mana_numerator": 293230435, + "fee_asset_price_numerator": 1227976553 + }, + "oracle_input": { + "proving_cost_modifier": 158317132, + "fee_asset_price_modifier": -659703931 + }, + "outputs": { + "fee_asset_price_at_execution": 10190560981, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32893290, + "proving_cost": 5422668923, + "congestion_cost": 20328800583, + "congestion_multiplier": 4726252179 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 335201077, + "proving_cost": 55260038339, + "congestion_cost": 207161882011, + "congestion_multiplier": 4726252179 + } + } + }, + { + "l1_block_number": 20974736, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10365019463 + }, + "parent_header": { + "excess_mana": 1327463706, + "mana_used": 92120356, + "proving_cost_per_mana_numerator": 293230435, + "fee_asset_price_numerator": 1227976553 + }, + "header": { + "excess_mana": 1319584062, + "mana_used": 86406893, + "proving_cost_per_mana_numerator": 237640787, + "fee_asset_price_numerator": 1832755996 + }, + "oracle_input": { + "proving_cost_modifier": -55589648, + "fee_asset_price_modifier": 604779443 + }, + "outputs": { + "fee_asset_price_at_execution": 10123554714, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34334126, + "proving_cost": 5431260737, + "congestion_cost": 20129131249, + "congestion_multiplier": 4682880227 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 347583403, + "proving_cost": 54983665237, + "congestion_cost": 203778361544, + "congestion_multiplier": 4682880227 + } + } + }, + { + "l1_block_number": 20974739, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10874452459 + }, + "parent_header": { + "excess_mana": 1319584062, + "mana_used": 86406893, + "proving_cost_per_mana_numerator": 237640787, + "fee_asset_price_numerator": 1832755996 + }, + "header": { + "excess_mana": 1305990955, + "mana_used": 112381644, + "proving_cost_per_mana_numerator": 221200969, + "fee_asset_price_numerator": 1631151271 + }, + "oracle_input": { + "proving_cost_modifier": -16439818, + "fee_asset_price_modifier": -201604725 + }, + "outputs": { + "fee_asset_price_at_execution": 10184965404, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 36021623, + "proving_cost": 5428242357, + "congestion_cost": 19720491044, + "congestion_multiplier": 4608993108 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 366878984, + "proving_cost": 55286460610, + "congestion_cost": 200852519033, + "congestion_multiplier": 4608993108 + } + } + }, + { + "l1_block_number": 20974742, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10537462271 + }, + "parent_header": { + "excess_mana": 1305990955, + "mana_used": 112381644, + "proving_cost_per_mana_numerator": 221200969, + "fee_asset_price_numerator": 1631151271 + }, + "header": { + "excess_mana": 1318372599, + "mana_used": 104606734, + "proving_cost_per_mana_numerator": 153703284, + "fee_asset_price_numerator": 1141096092 + }, + "oracle_input": { + "proving_cost_modifier": -67497685, + "fee_asset_price_modifier": -490055179 + }, + "outputs": { + "fee_asset_price_at_execution": 10164452717, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34905343, + "proving_cost": 5427350037, + "congestion_cost": 20080601914, + "congestion_multiplier": 4676247359 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 354793708, + "proving_cost": 55166042829, + "congestion_cost": 204108328683, + "congestion_multiplier": 4676247359 + } + } + }, + { + "l1_block_number": 20974745, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10500204149 + }, + "parent_header": { + "excess_mana": 1318372599, + "mana_used": 104606734, + "proving_cost_per_mana_numerator": 153703284, + "fee_asset_price_numerator": 1141096092 + }, + "header": { + "excess_mana": 1322979333, + "mana_used": 98393903, + "proving_cost_per_mana_numerator": 125449892, + "fee_asset_price_numerator": 692530653 + }, + "oracle_input": { + "proving_cost_modifier": -28253392, + "fee_asset_price_modifier": -448565439 + }, + "outputs": { + "fee_asset_price_at_execution": 10114763142, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34781926, + "proving_cost": 5423687938, + "congestion_cost": 20204634344, + "congestion_multiplier": 4701519812 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 351810943, + "proving_cost": 54859318848, + "congestion_cost": 204365090760, + "congestion_multiplier": 4701519812 + } + } + }, + { + "l1_block_number": 20974748, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10424404293 + }, + "parent_header": { + "excess_mana": 1322979333, + "mana_used": 98393903, + "proving_cost_per_mana_numerator": 125449892, + "fee_asset_price_numerator": 692530653 + }, + "header": { + "excess_mana": 1321373236, + "mana_used": 101125648, + "proving_cost_per_mana_numerator": 116545291, + "fee_asset_price_numerator": 1221606111 + }, + "oracle_input": { + "proving_cost_modifier": -8904601, + "fee_asset_price_modifier": 529075458 + }, + "outputs": { + "fee_asset_price_at_execution": 10069493419, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34530839, + "proving_cost": 5422155778, + "congestion_cost": 20149870247, + "congestion_multiplier": 4692693325 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 347708056, + "proving_cost": 54598361923, + "congestion_cost": 202898985845, + "congestion_multiplier": 4692693325 + } + } + }, + { + "l1_block_number": 20974751, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9876371928 + }, + "parent_header": { + "excess_mana": 1321373236, + "mana_used": 101125648, + "proving_cost_per_mana_numerator": 116545291, + "fee_asset_price_numerator": 1221606111 + }, + "header": { + "excess_mana": 1322498884, + "mana_used": 106231316, + "proving_cost_per_mana_numerator": 116068701, + "fee_asset_price_numerator": 783842434 + }, + "oracle_input": { + "proving_cost_modifier": -476590, + "fee_asset_price_modifier": -437763677 + }, + "outputs": { + "fee_asset_price_at_execution": 10122909819, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32715482, + "proving_cost": 5421672978, + "congestion_cost": 20175115907, + "congestion_multiplier": 4698877712 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 331175873, + "proving_cost": 54883106624, + "congestion_cost": 204230878914, + "congestion_multiplier": 4698877712 + } + } + }, + { + "l1_block_number": 20974754, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9360570144 + }, + "parent_header": { + "excess_mana": 1322498884, + "mana_used": 106231316, + "proving_cost_per_mana_numerator": 116068701, + "fee_asset_price_numerator": 783842434 + }, + "header": { + "excess_mana": 1328730200, + "mana_used": 94599253, + "proving_cost_per_mana_numerator": 195742672, + "fee_asset_price_numerator": 1332901608 + }, + "oracle_input": { + "proving_cost_modifier": 79673971, + "fee_asset_price_modifier": 549059174 + }, + "outputs": { + "fee_asset_price_at_execution": 10078692252, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31006888, + "proving_cost": 5421647139, + "congestion_cost": 20356179104, + "congestion_multiplier": 4733260721 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 312508881, + "proving_cost": 54643113012, + "congestion_cost": 205163664615, + "congestion_multiplier": 4733260721 + } + } + }, + { + "l1_block_number": 20974757, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9824724225 + }, + "parent_header": { + "excess_mana": 1328730200, + "mana_used": 94599253, + "proving_cost_per_mana_numerator": 195742672, + "fee_asset_price_numerator": 1332901608 + }, + "header": { + "excess_mana": 1323329453, + "mana_used": 104810216, + "proving_cost_per_mana_numerator": 91244335, + "fee_asset_price_numerator": 1328557093 + }, + "oracle_input": { + "proving_cost_modifier": -104498337, + "fee_asset_price_modifier": -4344515 + }, + "outputs": { + "fee_asset_price_at_execution": 10134182434, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32544398, + "proving_cost": 5425968502, + "congestion_cost": 20215308524, + "congestion_multiplier": 4703446139 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 329810866, + "proving_cost": 54987754680, + "congestion_cost": 204865624541, + "congestion_multiplier": 4703446139 + } + } + }, + { + "l1_block_number": 20974760, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9304831062 + }, + "parent_header": { + "excess_mana": 1323329453, + "mana_used": 104810216, + "proving_cost_per_mana_numerator": 91244335, + "fee_asset_price_numerator": 1328557093 + }, + "header": { + "excess_mana": 1328139669, + "mana_used": 22463541, + "proving_cost_per_mana_numerator": 70172623, + "fee_asset_price_numerator": 846061293 + }, + "oracle_input": { + "proving_cost_modifier": -21071712, + "fee_asset_price_modifier": -482495800 + }, + "outputs": { + "fee_asset_price_at_execution": 10133742162, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30822252, + "proving_cost": 5420301417, + "congestion_cost": 20332645168, + "congestion_multiplier": 4729991540 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 312344754, + "proving_cost": 54927937000, + "congestion_cost": 206045783603, + "congestion_multiplier": 4729991540 + } + } + }, + { + "l1_block_number": 20974763, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9375115776 + }, + "parent_header": { + "excess_mana": 1328139669, + "mana_used": 22463541, + "proving_cost_per_mana_numerator": 70172623, + "fee_asset_price_numerator": 846061293 + }, + "header": { + "excess_mana": 1250603210, + "mana_used": 150785033, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1599723314 + }, + "oracle_input": { + "proving_cost_modifier": -176951960, + "fee_asset_price_modifier": 753662021 + }, + "outputs": { + "fee_asset_price_at_execution": 10084965050, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31055071, + "proving_cost": 5419159387, + "congestion_cost": 18093543131, + "congestion_multiplier": 4319785537 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 313189305, + "proving_cost": 54652033018, + "congestion_cost": 182472750106, + "congestion_multiplier": 4319785537 + } + } + }, + { + "l1_block_number": 20974766, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9355897486 + }, + "parent_header": { + "excess_mana": 1250603210, + "mana_used": 150785033, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 1599723314 + }, + "header": { + "excess_mana": 1301388243, + "mana_used": 115685651, + "proving_cost_per_mana_numerator": 73707425, + "fee_asset_price_numerator": 2586358676 + }, + "oracle_input": { + "proving_cost_modifier": 73707425, + "fee_asset_price_modifier": 986635362 + }, + "outputs": { + "fee_asset_price_at_execution": 10161258739, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30991410, + "proving_cost": 5415357955, + "congestion_cost": 19521021036, + "congestion_multiplier": 4584239594 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 314911735, + "proving_cost": 55026853345, + "congestion_cost": 198358145596, + "congestion_multiplier": 4584239594 + } + } + }, + { + "l1_block_number": 20974769, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9794644343 + }, + "parent_header": { + "excess_mana": 1301388243, + "mana_used": 115685651, + "proving_cost_per_mana_numerator": 73707425, + "fee_asset_price_numerator": 2586358676 + }, + "header": { + "excess_mana": 1317073894, + "mana_used": 107028096, + "proving_cost_per_mana_numerator": 10009116, + "fee_asset_price_numerator": 3372692979 + }, + "oracle_input": { + "proving_cost_modifier": -63698309, + "fee_asset_price_modifier": 786334303 + }, + "outputs": { + "fee_asset_price_at_execution": 10262009515, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32444759, + "proving_cost": 5419350947, + "congestion_cost": 20003441320, + "congestion_multiplier": 4669147268 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 332948425, + "proving_cost": 55613430983, + "congestion_cost": 205275505158, + "congestion_multiplier": 4669147268 + } + } + }, + { + "l1_block_number": 20974772, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10009442615 + }, + "parent_header": { + "excess_mana": 1317073894, + "mana_used": 107028096, + "proving_cost_per_mana_numerator": 10009116, + "fee_asset_price_numerator": 3372692979 + }, + "header": { + "excess_mana": 1324101990, + "mana_used": 104043606, + "proving_cost_per_mana_numerator": 166033820, + "fee_asset_price_numerator": 3617525919 + }, + "oracle_input": { + "proving_cost_modifier": 156024704, + "fee_asset_price_modifier": 244832940 + }, + "outputs": { + "fee_asset_price_at_execution": 10343021310, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33156278, + "proving_cost": 5415900011, + "congestion_cost": 20203462498, + "congestion_multiplier": 4707699357 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 342936089, + "proving_cost": 56016769226, + "congestion_cost": 208964843152, + "congestion_multiplier": 4707699357 + } + } + }, + { + "l1_block_number": 20974775, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9694844373 + }, + "parent_header": { + "excess_mana": 1324101990, + "mana_used": 104043606, + "proving_cost_per_mana_numerator": 166033820, + "fee_asset_price_numerator": 3617525919 + }, + "header": { + "excess_mana": 1328145596, + "mana_used": 99506947, + "proving_cost_per_mana_numerator": 47176936, + "fee_asset_price_numerator": 3843644767 + }, + "oracle_input": { + "proving_cost_modifier": -118856884, + "fee_asset_price_modifier": 226118848 + }, + "outputs": { + "fee_asset_price_at_execution": 10368375458, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32114171, + "proving_cost": 5424356749, + "congestion_cost": 20352769347, + "congestion_multiplier": 4730024341 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 332971782, + "proving_cost": 56241767391, + "congestion_cost": 211025154199, + "congestion_multiplier": 4730024341 + } + } + }, + { + "l1_block_number": 20974778, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9325354066 + }, + "parent_header": { + "excess_mana": 1328145596, + "mana_used": 99506947, + "proving_cost_per_mana_numerator": 47176936, + "fee_asset_price_numerator": 3843644767 + }, + "header": { + "excess_mana": 1327652543, + "mana_used": 95115604, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 4394437425 + }, + "oracle_input": { + "proving_cost_modifier": -70276183, + "fee_asset_price_modifier": 550792658 + }, + "outputs": { + "fee_asset_price_at_execution": 10391846836, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30890235, + "proving_cost": 5417913357, + "congestion_cost": 20309306606, + "congestion_multiplier": 4727296509 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 321006590, + "proving_cost": 56302125776, + "congestion_cost": 211051203594, + "congestion_multiplier": 4727296509 + } + } + }, + { + "l1_block_number": 20974781, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8890810110 + }, + "parent_header": { + "excess_mana": 1327652543, + "mana_used": 95115604, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 4394437425 + }, + "header": { + "excess_mana": 1322768147, + "mana_used": 105577993, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3884670042 + }, + "oracle_input": { + "proving_cost_modifier": -89581950, + "fee_asset_price_modifier": -509767383 + }, + "outputs": { + "fee_asset_price_at_execution": 10449242285, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29450808, + "proving_cost": 5415357955, + "congestion_cost": 20147743129, + "congestion_multiplier": 4700358269 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 307738628, + "proving_cost": 56586387331, + "congestion_cost": 210528649450, + "congestion_multiplier": 4700358269 + } + } + }, + { + "l1_block_number": 20974784, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9245683543 + }, + "parent_header": { + "excess_mana": 1322768147, + "mana_used": 105577993, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 3884670042 + }, + "header": { + "excess_mana": 1328346140, + "mana_used": 94255340, + "proving_cost_per_mana_numerator": 151704970, + "fee_asset_price_numerator": 4074038287 + }, + "oracle_input": { + "proving_cost_modifier": 151704970, + "fee_asset_price_modifier": 189368245 + }, + "outputs": { + "fee_asset_price_at_execution": 10396110994, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30626326, + "proving_cost": 5415357955, + "congestion_cost": 20319698786, + "congestion_multiplier": 4731134307 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 318394684, + "proving_cost": 56298662372, + "congestion_cost": 211245843943, + "congestion_multiplier": 4731134307 + } + } + }, + { + "l1_block_number": 20974787, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9301265399 + }, + "parent_header": { + "excess_mana": 1328346140, + "mana_used": 94255340, + "proving_cost_per_mana_numerator": 151704970, + "fee_asset_price_numerator": 4074038287 + }, + "header": { + "excess_mana": 1322601480, + "mana_used": 92317269, + "proving_cost_per_mana_numerator": 150396703, + "fee_asset_price_numerator": 4412849079 + }, + "oracle_input": { + "proving_cost_modifier": -1308267, + "fee_asset_price_modifier": 338810792 + }, + "outputs": { + "fee_asset_price_at_execution": 10415816579, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30810441, + "proving_cost": 5423579556, + "congestion_cost": 20178198272, + "congestion_multiplier": 4699441786 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 320915902, + "proving_cost": 56491009856, + "congestion_cost": 210172412095, + "congestion_multiplier": 4699441786 + } + } + }, + { + "l1_block_number": 20974790, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10338672585 + }, + "parent_header": { + "excess_mana": 1322601480, + "mana_used": 92317269, + "proving_cost_per_mana_numerator": 150396703, + "fee_asset_price_numerator": 4412849079 + }, + "header": { + "excess_mana": 1314918749, + "mana_used": 101125366, + "proving_cost_per_mana_numerator": 195716802, + "fee_asset_price_numerator": 3855190737 + }, + "oracle_input": { + "proving_cost_modifier": 45320099, + "fee_asset_price_modifier": -557658342 + }, + "outputs": { + "fee_asset_price_at_execution": 10451166341, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34246852, + "proving_cost": 5423508602, + "congestion_cost": 19961133408, + "congestion_multiplier": 4657388752 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 357919546, + "proving_cost": 56681990551, + "congestion_cost": 208617125601, + "congestion_multiplier": 4657388752 + } + } + }, + { + "l1_block_number": 20974793, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10696471973 + }, + "parent_header": { + "excess_mana": 1314918749, + "mana_used": 101125366, + "proving_cost_per_mana_numerator": 195716802, + "fee_asset_price_numerator": 3855190737 + }, + "header": { + "excess_mana": 1316044115, + "mana_used": 78651739, + "proving_cost_per_mana_numerator": 281864500, + "fee_asset_price_numerator": 4486558706 + }, + "oracle_input": { + "proving_cost_modifier": 86147698, + "fee_asset_price_modifier": 631367969 + }, + "outputs": { + "fee_asset_price_at_execution": 10393046745, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35432063, + "proving_cost": 5425967098, + "congestion_cost": 20007972759, + "congestion_multiplier": 4663525073 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 368247087, + "proving_cost": 56392329686, + "congestion_cost": 207943796156, + "congestion_multiplier": 4663525073 + } + } + }, + { + "l1_block_number": 20974796, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10676042346 + }, + "parent_header": { + "excess_mana": 1316044115, + "mana_used": 78651739, + "proving_cost_per_mana_numerator": 281864500, + "fee_asset_price_numerator": 4486558706 + }, + "header": { + "excess_mana": 1294695854, + "mana_used": 104253914, + "proving_cost_per_mana_numerator": 205325868, + "fee_asset_price_numerator": 4626061500 + }, + "oracle_input": { + "proving_cost_modifier": -76538632, + "fee_asset_price_modifier": 139502794 + }, + "outputs": { + "fee_asset_price_at_execution": 10458872696, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35364390, + "proving_cost": 5430643458, + "congestion_cost": 19396045360, + "congestion_multiplier": 4548484726 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 369871652, + "proving_cost": 56798408584, + "congestion_cost": 202860769226, + "congestion_multiplier": 4548484726 + } + } + }, + { + "l1_block_number": 20974799, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11427276933 + }, + "parent_header": { + "excess_mana": 1294695854, + "mana_used": 104253914, + "proving_cost_per_mana_numerator": 205325868, + "fee_asset_price_numerator": 4626061500 + }, + "header": { + "excess_mana": 1298949768, + "mana_used": 121554216, + "proving_cost_per_mana_numerator": 194135492, + "fee_asset_price_numerator": 4492379499 + }, + "oracle_input": { + "proving_cost_modifier": -11190376, + "fee_asset_price_modifier": -133682001 + }, + "outputs": { + "fee_asset_price_at_execution": 10473473298, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 37852854, + "proving_cost": 5426488508, + "congestion_cost": 19514142896, + "congestion_multiplier": 4571179325 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 396450855, + "proving_cost": 56834182490, + "congestion_cost": 204380854554, + "congestion_multiplier": 4571179325 + } + } + }, + { + "l1_block_number": 20974802, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11491823317 + }, + "parent_header": { + "excess_mana": 1298949768, + "mana_used": 121554216, + "proving_cost_per_mana_numerator": 194135492, + "fee_asset_price_numerator": 4492379499 + }, + "header": { + "excess_mana": 1320503984, + "mana_used": 69392636, + "proving_cost_per_mana_numerator": 202298936, + "fee_asset_price_numerator": 4437308775 + }, + "oracle_input": { + "proving_cost_modifier": 8163444, + "fee_asset_price_modifier": -55070724 + }, + "outputs": { + "fee_asset_price_at_execution": 10459481503, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 38066664, + "proving_cost": 5425881298, + "congestion_cost": 20150620261, + "congestion_multiplier": 4687923165 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 398157567, + "proving_cost": 56751905073, + "congestion_cost": 210765039893, + "congestion_multiplier": 4687923165 + } + } + }, + { + "l1_block_number": 20974805, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10811344431 + }, + "parent_header": { + "excess_mana": 1320503984, + "mana_used": 69392636, + "proving_cost_per_mana_numerator": 202298936, + "fee_asset_price_numerator": 4437308775 + }, + "header": { + "excess_mana": 1289896620, + "mana_used": 123033670, + "proving_cost_per_mana_numerator": 292978465, + "fee_asset_price_numerator": 4662820355 + }, + "oracle_input": { + "proving_cost_modifier": 90679529, + "fee_asset_price_modifier": 225511580 + }, + "outputs": { + "fee_asset_price_at_execution": 10453722977, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35812578, + "proving_cost": 5426324255, + "congestion_cost": 19243195915, + "congestion_multiplier": 4523016084 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 374374769, + "proving_cost": 56725290545, + "congestion_cost": 201163039287, + "congestion_multiplier": 4523016084 + } + } + }, + { + "l1_block_number": 20974808, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11312462913 + }, + "parent_header": { + "excess_mana": 1289896620, + "mana_used": 123033670, + "proving_cost_per_mana_numerator": 292978465, + "fee_asset_price_numerator": 4662820355 + }, + "header": { + "excess_mana": 1312930290, + "mana_used": 104485851, + "proving_cost_per_mana_numerator": 338949112, + "fee_asset_price_numerator": 5084899225 + }, + "oracle_input": { + "proving_cost_modifier": 45970647, + "fee_asset_price_modifier": 422078870 + }, + "outputs": { + "fee_asset_price_at_execution": 10477323934, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 37472533, + "proving_cost": 5431247052, + "congestion_cost": 19942046606, + "congestion_multiplier": 4646565946 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 392611866, + "proving_cost": 56904934729, + "congestion_cost": 208939282197, + "congestion_multiplier": 4646565946 + } + } + }, + { + "l1_block_number": 20974811, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10662810216 + }, + "parent_header": { + "excess_mana": 1312930290, + "mana_used": 104485851, + "proving_cost_per_mana_numerator": 338949112, + "fee_asset_price_numerator": 5084899225 + }, + "header": { + "excess_mana": 1317416141, + "mana_used": 95457884, + "proving_cost_per_mana_numerator": 410205539, + "fee_asset_price_numerator": 4421489069 + }, + "oracle_input": { + "proving_cost_modifier": 71256427, + "fee_asset_price_modifier": -663410156 + }, + "outputs": { + "fee_asset_price_at_execution": 10521639963, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35320558, + "proving_cost": 5433744405, + "congestion_cost": 20077032115, + "congestion_multiplier": 4671017304 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 371630194, + "proving_cost": 57171902280, + "congestion_cost": 211243303439, + "congestion_multiplier": 4671017304 + } + } + }, + { + "l1_block_number": 20974814, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10452820038 + }, + "parent_header": { + "excess_mana": 1317416141, + "mana_used": 95457884, + "proving_cost_per_mana_numerator": 410205539, + "fee_asset_price_numerator": 4421489069 + }, + "header": { + "excess_mana": 1312874025, + "mana_used": 101125688, + "proving_cost_per_mana_numerator": 392508919, + "fee_asset_price_numerator": 5338461220 + }, + "oracle_input": { + "proving_cost_modifier": -17696620, + "fee_asset_price_modifier": 916972151 + }, + "outputs": { + "fee_asset_price_at_execution": 10452069359, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34624966, + "proving_cost": 5437617677, + "congestion_cost": 19953219853, + "congestion_multiplier": 4646260072 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 361902546, + "proving_cost": 56834357107, + "congestion_cost": 208552437838, + "congestion_multiplier": 4646260072 + } + } + }, + { + "l1_block_number": 20974817, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10494444894 + }, + "parent_header": { + "excess_mana": 1312874025, + "mana_used": 101125688, + "proving_cost_per_mana_numerator": 392508919, + "fee_asset_price_numerator": 5338461220 + }, + "header": { + "excess_mana": 1313999713, + "mana_used": 113120937, + "proving_cost_per_mana_numerator": 440009576, + "fee_asset_price_numerator": 5678935638 + }, + "oracle_input": { + "proving_cost_modifier": 47500657, + "fee_asset_price_modifier": 340474418 + }, + "outputs": { + "fee_asset_price_at_execution": 10548352696, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34762848, + "proving_cost": 5436655487, + "congestion_cost": 19983717955, + "congestion_multiplier": 4652383483 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 366690781, + "proving_cost": 57347759563, + "congestion_cost": 210795305166, + "congestion_multiplier": 4652383483 + } + } + }, + { + "l1_block_number": 20974820, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11441672423 + }, + "parent_header": { + "excess_mana": 1313999713, + "mana_used": 113120937, + "proving_cost_per_mana_numerator": 440009576, + "fee_asset_price_numerator": 5678935638 + }, + "header": { + "excess_mana": 1327120650, + "mana_used": 93614567, + "proving_cost_per_mana_numerator": 652994890, + "fee_asset_price_numerator": 5682136233 + }, + "oracle_input": { + "proving_cost_modifier": 212985314, + "fee_asset_price_modifier": 3200595 + }, + "outputs": { + "fee_asset_price_at_execution": 10584328347, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 37900539, + "proving_cost": 5439238548, + "congestion_cost": 20398813395, + "congestion_multiplier": 4724355557 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 401151749, + "proving_cost": 57570686749, + "congestion_cost": 215907738861, + "congestion_multiplier": 4724355557 + } + } + }, + { + "l1_block_number": 20974823, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10436948017 + }, + "parent_header": { + "excess_mana": 1327120650, + "mana_used": 93614567, + "proving_cost_per_mana_numerator": 652994890, + "fee_asset_price_numerator": 5682136233 + }, + "header": { + "excess_mana": 1320735217, + "mana_used": 92881828, + "proving_cost_per_mana_numerator": 643450673, + "fee_asset_price_numerator": 5750089006 + }, + "oracle_input": { + "proving_cost_modifier": -9544217, + "fee_asset_price_modifier": 67952773 + }, + "outputs": { + "fee_asset_price_at_execution": 10584667114, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34572390, + "proving_cost": 5450835673, + "congestion_cost": 20236721458, + "congestion_multiplier": 4689191620 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 365937239, + "proving_cost": 57695281091, + "congestion_cost": 214198960111, + "congestion_multiplier": 4689191620 + } + } + }, + { + "l1_block_number": 20974826, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12544299201 + }, + "parent_header": { + "excess_mana": 1320735217, + "mana_used": 92881828, + "proving_cost_per_mana_numerator": 643450673, + "fee_asset_price_numerator": 5750089006 + }, + "header": { + "excess_mana": 1313617045, + "mana_used": 89289918, + "proving_cost_per_mana_numerator": 462121778, + "fee_asset_price_numerator": 5871915980 + }, + "oracle_input": { + "proving_cost_modifier": -181328895, + "fee_asset_price_modifier": 121826974 + }, + "outputs": { + "fee_asset_price_at_execution": 10591862133, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 41552991, + "proving_cost": 5450315458, + "congestion_cost": 20046972764, + "congestion_multiplier": 4650300977 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 440123551, + "proving_cost": 57728989912, + "congestion_cost": 212334771700, + "congestion_multiplier": 4650300977 + } + } + }, + { + "l1_block_number": 20974829, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12400332753 + }, + "parent_header": { + "excess_mana": 1313617045, + "mana_used": 89289918, + "proving_cost_per_mana_numerator": 462121778, + "fee_asset_price_numerator": 5871915980 + }, + "header": { + "excess_mana": 1302906963, + "mana_used": 111424450, + "proving_cost_per_mana_numerator": 557448177, + "fee_asset_price_numerator": 5446763525 + }, + "oracle_input": { + "proving_cost_modifier": 95326399, + "fee_asset_price_modifier": -425152455 + }, + "outputs": { + "fee_asset_price_at_execution": 10604773742, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 41076102, + "proving_cost": 5440441416, + "congestion_cost": 19691762869, + "congestion_multiplier": 4592392582 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 435602767, + "proving_cost": 57694650273, + "congestion_cost": 208826689806, + "congestion_multiplier": 4592392582 + } + } + }, + { + "l1_block_number": 20974832, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12549492621 + }, + "parent_header": { + "excess_mana": 1302906963, + "mana_used": 111424450, + "proving_cost_per_mana_numerator": 557448177, + "fee_asset_price_numerator": 5446763525 + }, + "header": { + "excess_mana": 1314331413, + "mana_used": 90490628, + "proving_cost_per_mana_numerator": 449359153, + "fee_asset_price_numerator": 5218321344 + }, + "oracle_input": { + "proving_cost_modifier": -108089024, + "fee_asset_price_modifier": -228442181 + }, + "outputs": { + "fee_asset_price_at_execution": 10559782993, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 41570194, + "proving_cost": 5445630066, + "congestion_cost": 20051268877, + "congestion_multiplier": 4654189373 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 438972227, + "proving_cost": 57504671757, + "congestion_cost": 211737048075, + "congestion_multiplier": 4654189373 + } + } + }, + { + "l1_block_number": 20974835, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12247487967 + }, + "parent_header": { + "excess_mana": 1314331413, + "mana_used": 90490628, + "proving_cost_per_mana_numerator": 449359153, + "fee_asset_price_numerator": 5218321344 + }, + "header": { + "excess_mana": 1304822041, + "mana_used": 113679240, + "proving_cost_per_mana_numerator": 514902665, + "fee_asset_price_numerator": 5674843125 + }, + "oracle_input": { + "proving_cost_modifier": 65543512, + "fee_asset_price_modifier": 456521781 + }, + "outputs": { + "fee_asset_price_at_execution": 10535687527, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 40569803, + "proving_cost": 5439747118, + "congestion_cost": 19743905009, + "congestion_multiplier": 4602694022 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 427430767, + "proving_cost": 57311475861, + "congestion_cost": 208015613737, + "congestion_multiplier": 4602694022 + } + } + }, + { + "l1_block_number": 20974838, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12279164524 + }, + "parent_header": { + "excess_mana": 1304822041, + "mana_used": 113679240, + "proving_cost_per_mana_numerator": 514902665, + "fee_asset_price_numerator": 5674843125 + }, + "header": { + "excess_mana": 1318501281, + "mana_used": 94816566, + "proving_cost_per_mana_numerator": 713358368, + "fee_asset_price_numerator": 6674843125 + }, + "oracle_input": { + "proving_cost_modifier": 198455703, + "fee_asset_price_modifier": 1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10583895191, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 40674732, + "proving_cost": 5443313688, + "congestion_cost": 20164359222, + "congestion_multiplier": 4676951459 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 430497100, + "proving_cost": 57611461565, + "congestion_cost": 213417464599, + "congestion_multiplier": 4676951459 + } + } + }, + { + "l1_block_number": 20974841, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10902675660 + }, + "parent_header": { + "excess_mana": 1318501281, + "mana_used": 94816566, + "proving_cost_per_mana_numerator": 713358368, + "fee_asset_price_numerator": 6674843125 + }, + "header": { + "excess_mana": 1313317847, + "mana_used": 107663248, + "proving_cost_per_mana_numerator": 748402866, + "fee_asset_price_numerator": 7610408635 + }, + "oracle_input": { + "proving_cost_modifier": 35044498, + "fee_asset_price_modifier": 935565510 + }, + "outputs": { + "fee_asset_price_at_execution": 10690265106, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 36115113, + "proving_cost": 5454126980, + "congestion_cost": 20032100119, + "congestion_multiplier": 4648673370 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 386080132, + "proving_cost": 58306063337, + "congestion_cost": 214148460902, + "congestion_multiplier": 4648673370 + } + } + }, + { + "l1_block_number": 20974844, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11748014686 + }, + "parent_header": { + "excess_mana": 1313317847, + "mana_used": 107663248, + "proving_cost_per_mana_numerator": 748402866, + "fee_asset_price_numerator": 7610408635 + }, + "header": { + "excess_mana": 1320981095, + "mana_used": 113716102, + "proving_cost_per_mana_numerator": 644992713, + "fee_asset_price_numerator": 8106950703 + }, + "oracle_input": { + "proving_cost_modifier": -103410153, + "fee_asset_price_modifier": 496542068 + }, + "outputs": { + "fee_asset_price_at_execution": 10790748852, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 38915298, + "proving_cost": 5456038687, + "congestion_cost": 20279351804, + "congestion_multiplier": 4690540787 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 419925207, + "proving_cost": 58874743198, + "congestion_cost": 218829392198, + "congestion_multiplier": 4690540787 + } + } + }, + { + "l1_block_number": 20974847, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11555866445 + }, + "parent_header": { + "excess_mana": 1320981095, + "mana_used": 113716102, + "proving_cost_per_mana_numerator": 644992713, + "fee_asset_price_numerator": 8106950703 + }, + "header": { + "excess_mana": 1334697197, + "mana_used": 77154125, + "proving_cost_per_mana_numerator": 630470577, + "fee_asset_price_numerator": 8256440326 + }, + "oracle_input": { + "proving_cost_modifier": -14522136, + "fee_asset_price_modifier": 149489623 + }, + "outputs": { + "fee_asset_price_at_execution": 10844462705, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 38278807, + "proving_cost": 5450399505, + "congestion_cost": 20672673591, + "congestion_multiplier": 4766421061 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 415113094, + "proving_cost": 59106654159, + "congestion_cost": 224184037770, + "congestion_multiplier": 4766421061 + } + } + }, + { + "l1_block_number": 20974850, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11216225347 + }, + "parent_header": { + "excess_mana": 1334697197, + "mana_used": 77154125, + "proving_cost_per_mana_numerator": 630470577, + "fee_asset_price_numerator": 8256440326 + }, + "header": { + "excess_mana": 1311851322, + "mana_used": 120250559, + "proving_cost_per_mana_numerator": 559447502, + "fee_asset_price_numerator": 8337804903 + }, + "oracle_input": { + "proving_cost_modifier": -71023075, + "fee_asset_price_modifier": 81364577 + }, + "outputs": { + "fee_asset_price_at_execution": 10860686175, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 37153746, + "proving_cost": 5449608048, + "congestion_cost": 19975674820, + "congestion_multiplier": 4640703856 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 403515175, + "proving_cost": 59186482786, + "congestion_cost": 216949535353, + "congestion_multiplier": 4640703856 + } + } + }, + { + "l1_block_number": 20974853, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11547959457 + }, + "parent_header": { + "excess_mana": 1311851322, + "mana_used": 120250559, + "proving_cost_per_mana_numerator": 559447502, + "fee_asset_price_numerator": 8337804903 + }, + "header": { + "excess_mana": 1332101881, + "mana_used": 95609882, + "proving_cost_per_mana_numerator": 658973526, + "fee_asset_price_numerator": 9010707806 + }, + "oracle_input": { + "proving_cost_modifier": 99526024, + "fee_asset_price_modifier": 672902903 + }, + "outputs": { + "fee_asset_price_at_execution": 10869526522, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 38252615, + "proving_cost": 5445738943, + "congestion_cost": 20575770061, + "congestion_multiplier": 4751969682 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 415787813, + "proving_cost": 59192603872, + "congestion_cost": 223648878388, + "congestion_multiplier": 4751969682 + } + } + }, + { + "l1_block_number": 20974856, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11536198807 + }, + "parent_header": { + "excess_mana": 1332101881, + "mana_used": 95609882, + "proving_cost_per_mana_numerator": 658973526, + "fee_asset_price_numerator": 9010707806 + }, + "header": { + "excess_mana": 1327711763, + "mana_used": 82020204, + "proving_cost_per_mana_numerator": 837434640, + "fee_asset_price_numerator": 8643670869 + }, + "oracle_input": { + "proving_cost_modifier": 178461114, + "fee_asset_price_modifier": -367036937 + }, + "outputs": { + "fee_asset_price_at_execution": 10942914520, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 38213658, + "proving_cost": 5451161568, + "congestion_cost": 20462327177, + "congestion_multiplier": 4727624062 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 418168792, + "proving_cost": 59651595073, + "congestion_cost": 223917497178, + "congestion_multiplier": 4727624062 + } + } + }, + { + "l1_block_number": 20974859, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12543844247 + }, + "parent_header": { + "excess_mana": 1327711763, + "mana_used": 82020204, + "proving_cost_per_mana_numerator": 837434640, + "fee_asset_price_numerator": 8643670869 + }, + "header": { + "excess_mana": 1309731967, + "mana_used": 122961211, + "proving_cost_per_mana_numerator": 914286965, + "fee_asset_price_numerator": 8589826773 + }, + "oracle_input": { + "proving_cost_modifier": 76852325, + "fee_asset_price_modifier": -53844096 + }, + "outputs": { + "fee_asset_price_at_execution": 10902823601, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 41551484, + "proving_cost": 5460898458, + "congestion_cost": 19969550821, + "congestion_multiplier": 4629210812 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 453028500, + "proving_cost": 59539212590, + "congestion_cost": 217724489992, + "congestion_multiplier": 4629210812 + } + } + }, + { + "l1_block_number": 20974862, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11467196389 + }, + "parent_header": { + "excess_mana": 1309731967, + "mana_used": 122961211, + "proving_cost_per_mana_numerator": 914286965, + "fee_asset_price_numerator": 8589826773 + }, + "header": { + "excess_mana": 1332693178, + "mana_used": 88377634, + "proving_cost_per_mana_numerator": 888132222, + "fee_asset_price_numerator": 7731360299 + }, + "oracle_input": { + "proving_cost_modifier": -26154743, + "fee_asset_price_modifier": -858466474 + }, + "outputs": { + "fee_asset_price_at_execution": 10896954654, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 37985088, + "proving_cost": 5465096898, + "congestion_cost": 20665494386, + "congestion_multiplier": 4755258315 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 413921781, + "proving_cost": 59552913077, + "congestion_cost": 225190955226, + "congestion_multiplier": 4755258315 + } + } + }, + { + "l1_block_number": 20974865, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11847593532 + }, + "parent_header": { + "excess_mana": 1332693178, + "mana_used": 88377634, + "proving_cost_per_mana_numerator": 888132222, + "fee_asset_price_numerator": 7731360299 + }, + "header": { + "excess_mana": 1321070812, + "mana_used": 105628168, + "proving_cost_per_mana_numerator": 1011353411, + "fee_asset_price_numerator": 8653928406 + }, + "oracle_input": { + "proving_cost_modifier": 123221189, + "fee_asset_price_modifier": 922568107 + }, + "outputs": { + "fee_asset_price_at_execution": 10803808339, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 39245153, + "proving_cost": 5463667703, + "congestion_cost": 20311433905, + "congestion_multiplier": 4691033174 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 423997111, + "proving_cost": 59028418691, + "congestion_cost": 219440838999, + "congestion_multiplier": 4691033174 + } + } + }, + { + "l1_block_number": 20974868, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11328194124 + }, + "parent_header": { + "excess_mana": 1321070812, + "mana_used": 105628168, + "proving_cost_per_mana_numerator": 1011353411, + "fee_asset_price_numerator": 8653928406 + }, + "header": { + "excess_mana": 1326698980, + "mana_used": 112426897, + "proving_cost_per_mana_numerator": 922374234, + "fee_asset_price_numerator": 8952196191 + }, + "oracle_input": { + "proving_cost_modifier": -88979177, + "fee_asset_price_modifier": 298267785 + }, + "outputs": { + "fee_asset_price_at_execution": 10903942019, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 37524643, + "proving_cost": 5470404249, + "congestion_cost": 20500650978, + "congestion_multiplier": 4722025353 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 409166531, + "proving_cost": 59648970751, + "congestion_cost": 223537909615, + "congestion_multiplier": 4722025353 + } + } + }, + { + "l1_block_number": 20974871, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10326551989 + }, + "parent_header": { + "excess_mana": 1326698980, + "mana_used": 112426897, + "proving_cost_per_mana_numerator": 922374234, + "fee_asset_price_numerator": 8952196191 + }, + "header": { + "excess_mana": 1339125877, + "mana_used": 93159165, + "proving_cost_per_mana_numerator": 1096301212, + "fee_asset_price_numerator": 8922067968 + }, + "oracle_input": { + "proving_cost_modifier": 173926978, + "fee_asset_price_modifier": -30128223 + }, + "outputs": { + "fee_asset_price_at_execution": 10936513517, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34206703, + "proving_cost": 5465538893, + "congestion_cost": 20850539989, + "congestion_multiplier": 4791182633 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 374102069, + "proving_cost": 59773939980, + "congestion_cost": 228032212426, + "congestion_multiplier": 4791182633 + } + } + }, + { + "l1_block_number": 20974874, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10644013577 + }, + "parent_header": { + "excess_mana": 1339125877, + "mana_used": 93159165, + "proving_cost_per_mana_numerator": 1096301212, + "fee_asset_price_numerator": 8922067968 + }, + "header": { + "excess_mana": 1332285042, + "mana_used": 95153977, + "proving_cost_per_mana_numerator": 1124499162, + "fee_asset_price_numerator": 9123995500 + }, + "oracle_input": { + "proving_cost_modifier": 28197950, + "fee_asset_price_modifier": 201927532 + }, + "outputs": { + "fee_asset_price_at_execution": 10933219036, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35258294, + "proving_cost": 5475053211, + "congestion_cost": 20680133670, + "congestion_multiplier": 4752988130 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 385486651, + "proving_cost": 59859955989, + "congestion_cost": 226100431107, + "congestion_multiplier": 4752988130 + } + } + }, + { + "l1_block_number": 20974877, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10075447620 + }, + "parent_header": { + "excess_mana": 1332285042, + "mana_used": 95153977, + "proving_cost_per_mana_numerator": 1124499162, + "fee_asset_price_numerator": 9123995500 + }, + "header": { + "excess_mana": 1327439019, + "mana_used": 100954563, + "proving_cost_per_mana_numerator": 1154447316, + "fee_asset_price_numerator": 9066858318 + }, + "oracle_input": { + "proving_cost_modifier": 29948154, + "fee_asset_price_modifier": -57137182 + }, + "outputs": { + "fee_asset_price_at_execution": 10955318520, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33374920, + "proving_cost": 5476597282, + "congestion_cost": 20530793757, + "congestion_multiplier": 4726115669 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 365632879, + "proving_cost": 59997867630, + "congestion_cost": 224921385076, + "congestion_multiplier": 4726115669 + } + } + }, + { + "l1_block_number": 20974880, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9763461789 + }, + "parent_header": { + "excess_mana": 1327439019, + "mana_used": 100954563, + "proving_cost_per_mana_numerator": 1154447316, + "fee_asset_price_numerator": 9066858318 + }, + "header": { + "excess_mana": 1328393582, + "mana_used": 86609776, + "proving_cost_per_mana_numerator": 1082851492, + "fee_asset_price_numerator": 8765287529 + }, + "oracle_input": { + "proving_cost_modifier": -71595824, + "fee_asset_price_modifier": -301570789 + }, + "outputs": { + "fee_asset_price_at_execution": 10949060748, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32341467, + "proving_cost": 5478237667, + "congestion_cost": 20562158041, + "congestion_multiplier": 4731396926 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 354108686, + "proving_cost": 59981557007, + "congestion_cost": 225136317500, + "congestion_multiplier": 4731396926 + } + } + }, + { + "l1_block_number": 20974883, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10100174423 + }, + "parent_header": { + "excess_mana": 1328393582, + "mana_used": 86609776, + "proving_cost_per_mana_numerator": 1082851492, + "fee_asset_price_numerator": 8765287529 + }, + "header": { + "excess_mana": 1315003358, + "mana_used": 101994370, + "proving_cost_per_mana_numerator": 1293341291, + "fee_asset_price_numerator": 8005697334 + }, + "oracle_input": { + "proving_cost_modifier": 210489799, + "fee_asset_price_modifier": -759590195 + }, + "outputs": { + "fee_asset_price_at_execution": 10916091317, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33456827, + "proving_cost": 5474316882, + "congestion_cost": 20146609081, + "congestion_multiplier": 4657849822 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 365217778, + "proving_cost": 59758142982, + "congestion_cost": 219922224456, + "congestion_multiplier": 4657849822 + } + } + }, + { + "l1_block_number": 20974886, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9861299092 + }, + "parent_header": { + "excess_mana": 1315003358, + "mana_used": 101994370, + "proving_cost_per_mana_numerator": 1293341291, + "fee_asset_price_numerator": 8005697334 + }, + "header": { + "excess_mana": 1316997728, + "mana_used": 100770495, + "proving_cost_per_mana_numerator": 1274750290, + "fee_asset_price_numerator": 7879332404 + }, + "oracle_input": { + "proving_cost_modifier": -18591001, + "fee_asset_price_modifier": -126364930 + }, + "outputs": { + "fee_asset_price_at_execution": 10833487879, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32665553, + "proving_cost": 5485851896, + "congestion_cost": 20245957137, + "congestion_multiplier": 4668731199 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 353881872, + "proving_cost": 59430910021, + "congestion_cost": 219334331242, + "congestion_multiplier": 4668731199 + } + } + }, + { + "l1_block_number": 20974889, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9769056260 + }, + "parent_header": { + "excess_mana": 1316997728, + "mana_used": 100770495, + "proving_cost_per_mana_numerator": 1274750290, + "fee_asset_price_numerator": 7879332404 + }, + "header": { + "excess_mana": 1317768223, + "mana_used": 93740114, + "proving_cost_per_mana_numerator": 1134591213, + "fee_asset_price_numerator": 8058266347 + }, + "oracle_input": { + "proving_cost_modifier": -140159077, + "fee_asset_price_modifier": 178933943 + }, + "outputs": { + "fee_asset_price_at_execution": 10819806795, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32359998, + "proving_cost": 5484832116, + "congestion_cost": 20264325870, + "congestion_multiplier": 4672941861 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 350128926, + "proving_cost": 59344823798, + "congestion_cost": 219256090744, + "congestion_multiplier": 4672941861 + } + } + }, + { + "l1_block_number": 20974892, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9623430979 + }, + "parent_header": { + "excess_mana": 1317768223, + "mana_used": 93740114, + "proving_cost_per_mana_numerator": 1134591213, + "fee_asset_price_numerator": 8058266347 + }, + "header": { + "excess_mana": 1311508337, + "mana_used": 108023757, + "proving_cost_per_mana_numerator": 1392064986, + "fee_asset_price_numerator": 7449911189 + }, + "oracle_input": { + "proving_cost_modifier": 257473773, + "fee_asset_price_modifier": -608355158 + }, + "outputs": { + "fee_asset_price_at_execution": 10839184433, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31877615, + "proving_cost": 5477150011, + "congestion_cost": 20046480829, + "congestion_multiplier": 4638841950 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 345527348, + "proving_cost": 59367839136, + "congestion_cost": 217287502938, + "congestion_multiplier": 4638841950 + } + } + }, + { + "l1_block_number": 20974895, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9512609521 + }, + "parent_header": { + "excess_mana": 1311508337, + "mana_used": 108023757, + "proving_cost_per_mana_numerator": 1392064986, + "fee_asset_price_numerator": 7449911189 + }, + "header": { + "excess_mana": 1319532094, + "mana_used": 94907192, + "proving_cost_per_mana_numerator": 1301384261, + "fee_asset_price_numerator": 7256716944 + }, + "oracle_input": { + "proving_cost_modifier": -90680725, + "fee_asset_price_modifier": -193194245 + }, + "outputs": { + "fee_asset_price_at_execution": 10773443867, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31510519, + "proving_cost": 5491270406, + "congestion_cost": 20338168203, + "congestion_multiplier": 4682595504 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 339476807, + "proving_cost": 59159893477, + "congestion_cost": 219112113492, + "congestion_multiplier": 4682595504 + } + } + }, + { + "l1_block_number": 20974898, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10044576348 + }, + "parent_header": { + "excess_mana": 1319532094, + "mana_used": 94907192, + "proving_cost_per_mana_numerator": 1301384261, + "fee_asset_price_numerator": 7256716944 + }, + "header": { + "excess_mana": 1314439286, + "mana_used": 107252047, + "proving_cost_per_mana_numerator": 1319569211, + "fee_asset_price_numerator": 6585416524 + }, + "oracle_input": { + "proving_cost_modifier": 18184950, + "fee_asset_price_modifier": -671300420 + }, + "outputs": { + "fee_asset_price_at_execution": 10752650286, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33272659, + "proving_cost": 5486293139, + "congestion_cost": 20172781146, + "congestion_multiplier": 4654776822 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 357769266, + "proving_cost": 58992191490, + "congestion_cost": 216910860958, + "congestion_multiplier": 4654776822 + } + } + }, + { + "l1_block_number": 20974901, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10070103513 + }, + "parent_header": { + "excess_mana": 1314439286, + "mana_used": 107252047, + "proving_cost_per_mana_numerator": 1319569211, + "fee_asset_price_numerator": 6585416524 + }, + "header": { + "excess_mana": 1321691333, + "mana_used": 121405371, + "proving_cost_per_mana_numerator": 1304115838, + "fee_asset_price_numerator": 6808203349 + }, + "oracle_input": { + "proving_cost_modifier": -15453373, + "fee_asset_price_modifier": 222786825 + }, + "outputs": { + "fee_asset_price_at_execution": 10680709439, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33357217, + "proving_cost": 5487290910, + "congestion_cost": 20395704072, + "congestion_multiplier": 4694440146 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 356278742, + "proving_cost": 58608159816, + "congestion_cost": 217840588996, + "congestion_multiplier": 4694440146 + } + } + }, + { + "l1_block_number": 20974904, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10137549634 + }, + "parent_header": { + "excess_mana": 1321691333, + "mana_used": 121405371, + "proving_cost_per_mana_numerator": 1304115838, + "fee_asset_price_numerator": 6808203349 + }, + "header": { + "excess_mana": 1343096704, + "mana_used": 90671800, + "proving_cost_per_mana_numerator": 1172290607, + "fee_asset_price_numerator": 6521145587 + }, + "oracle_input": { + "proving_cost_modifier": -131825231, + "fee_asset_price_modifier": -287057762 + }, + "outputs": { + "fee_asset_price_at_execution": 10704531178, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33580633, + "proving_cost": 5486443004, + "congestion_cost": 21050574921, + "congestion_multiplier": 4813493620 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 359464932, + "proving_cost": 58729800192, + "congestion_cost": 225336535556, + "congestion_multiplier": 4813493620 + } + } + }, + { + "l1_block_number": 20974907, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9517302233 + }, + "parent_header": { + "excess_mana": 1343096704, + "mana_used": 90671800, + "proving_cost_per_mana_numerator": 1172290607, + "fee_asset_price_numerator": 6521145587 + }, + "header": { + "excess_mana": 1333768504, + "mana_used": 111628561, + "proving_cost_per_mana_numerator": 1241261106, + "fee_asset_price_numerator": 7094785441 + }, + "oracle_input": { + "proving_cost_modifier": 68970499, + "fee_asset_price_modifier": 573639854 + }, + "outputs": { + "fee_asset_price_at_execution": 10673847052, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31526063, + "proving_cost": 5479215252, + "congestion_cost": 20727247225, + "congestion_multiplier": 4761244820 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 336504374, + "proving_cost": 58484305564, + "congestion_cost": 221239466688, + "congestion_multiplier": 4761244820 + } + } + }, + { + "l1_block_number": 20974910, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9424484397 + }, + "parent_header": { + "excess_mana": 1333768504, + "mana_used": 111628561, + "proving_cost_per_mana_numerator": 1241261106, + "fee_asset_price_numerator": 7094785441 + }, + "header": { + "excess_mana": 1345397065, + "mana_used": 76010152, + "proving_cost_per_mana_numerator": 1123733641, + "fee_asset_price_numerator": 7441702780 + }, + "oracle_input": { + "proving_cost_modifier": -117527465, + "fee_asset_price_modifier": 346917339 + }, + "outputs": { + "fee_asset_price_at_execution": 10735252448, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31218604, + "proving_cost": 5482995598, + "congestion_cost": 21099954340, + "congestion_multiplier": 4826466214 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 335139595, + "proving_cost": 58861341915, + "congestion_cost": 226513336481, + "congestion_multiplier": 4826466214 + } + } + }, + { + "l1_block_number": 20974913, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9284979161 + }, + "parent_header": { + "excess_mana": 1345397065, + "mana_used": 76010152, + "proving_cost_per_mana_numerator": 1123733641, + "fee_asset_price_numerator": 7441702780 + }, + "header": { + "excess_mana": 1321407217, + "mana_used": 102379463, + "proving_cost_per_mana_numerator": 1087220094, + "fee_asset_price_numerator": 7782300821 + }, + "oracle_input": { + "proving_cost_modifier": -36513547, + "fee_asset_price_modifier": 340598041 + }, + "outputs": { + "fee_asset_price_at_execution": 10772559575, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30756493, + "proving_cost": 5476555358, + "congestion_cost": 20337841232, + "congestion_multiplier": 4692879899 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 331326153, + "proving_cost": 58996518859, + "congestion_cost": 219090606298, + "congestion_multiplier": 4692879899 + } + } + }, + { + "l1_block_number": 20974916, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9349531035 + }, + "parent_header": { + "excess_mana": 1321407217, + "mana_used": 102379463, + "proving_cost_per_mana_numerator": 1087220094, + "fee_asset_price_numerator": 7782300821 + }, + "header": { + "excess_mana": 1323786680, + "mana_used": 97560775, + "proving_cost_per_mana_numerator": 975214132, + "fee_asset_price_numerator": 7994655497 + }, + "oracle_input": { + "proving_cost_modifier": -112005962, + "fee_asset_price_modifier": 212354676 + }, + "outputs": { + "fee_asset_price_at_execution": 10809313257, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30970321, + "proving_cost": 5474556038, + "congestion_cost": 20403276690, + "congestion_multiplier": 4705962947 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 334767901, + "proving_cost": 59176191157, + "congestion_cost": 220545409211, + "congestion_multiplier": 4705962947 + } + } + }, + { + "l1_block_number": 20974919, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9390478247 + }, + "parent_header": { + "excess_mana": 1323786680, + "mana_used": 97560775, + "proving_cost_per_mana_numerator": 975214132, + "fee_asset_price_numerator": 7994655497 + }, + "header": { + "excess_mana": 1321347455, + "mana_used": 99274649, + "proving_cost_per_mana_numerator": 937389994, + "fee_asset_price_numerator": 7861276742 + }, + "oracle_input": { + "proving_cost_modifier": -37824138, + "fee_asset_price_modifier": -133378755 + }, + "outputs": { + "fee_asset_price_at_execution": 10832291729, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31105959, + "proving_cost": 5468427642, + "congestion_cost": 20307312571, + "congestion_multiplier": 4692551777 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 336948822, + "proving_cost": 59235603517, + "congestion_cost": 219974734001, + "congestion_multiplier": 4692551777 + } + } + }, + { + "l1_block_number": 20974922, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9142314696 + }, + "parent_header": { + "excess_mana": 1321347455, + "mana_used": 99274649, + "proving_cost_per_mana_numerator": 937389994, + "fee_asset_price_numerator": 7861276742 + }, + "header": { + "excess_mana": 1320622104, + "mana_used": 100673187, + "proving_cost_per_mana_numerator": 971394804, + "fee_asset_price_numerator": 8578845048 + }, + "oracle_input": { + "proving_cost_modifier": 34004810, + "fee_asset_price_modifier": 717568306 + }, + "outputs": { + "fee_asset_price_at_execution": 10817853384, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30283917, + "proving_cost": 5466359647, + "congestion_cost": 20274760503, + "congestion_multiplier": 4688571083 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 327606973, + "proving_cost": 59134277205, + "congestion_cost": 219329386517, + "congestion_multiplier": 4688571083 + } + } + }, + { + "l1_block_number": 20974925, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9969641609 + }, + "parent_header": { + "excess_mana": 1320622104, + "mana_used": 100673187, + "proving_cost_per_mana_numerator": 971394804, + "fee_asset_price_numerator": 8578845048 + }, + "header": { + "excess_mana": 1321295291, + "mana_used": 102820127, + "proving_cost_per_mana_numerator": 1013995161, + "fee_asset_price_numerator": 9578845048 + }, + "oracle_input": { + "proving_cost_modifier": 42600357, + "fee_asset_price_modifier": 1000000000 + }, + "outputs": { + "fee_asset_price_at_execution": 10895758046, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33024437, + "proving_cost": 5468218788, + "congestion_cost": 20312049967, + "congestion_multiplier": 4692265391 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 359826275, + "proving_cost": 59580388856, + "congestion_cost": 221315181858, + "congestion_multiplier": 4692265391 + } + } + }, + { + "l1_block_number": 20974928, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9852702429 + }, + "parent_header": { + "excess_mana": 1321295291, + "mana_used": 102820127, + "proving_cost_per_mana_numerator": 1013995161, + "fee_asset_price_numerator": 9578845048 + }, + "header": { + "excess_mana": 1324115418, + "mana_used": 98269123, + "proving_cost_per_mana_numerator": 919091259, + "fee_asset_price_numerator": 9292279788 + }, + "oracle_input": { + "proving_cost_modifier": -94903902, + "fee_asset_price_modifier": -286565260 + }, + "outputs": { + "fee_asset_price_at_execution": 11005262235, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32637076, + "proving_cost": 5470548765, + "congestion_cost": 20404565630, + "congestion_multiplier": 4707773319 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 359179579, + "proving_cost": 60204823728, + "congestion_cost": 224557595549, + "congestion_multiplier": 4707773319 + } + } + }, + { + "l1_block_number": 20974931, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9051667803 + }, + "parent_header": { + "excess_mana": 1324115418, + "mana_used": 98269123, + "proving_cost_per_mana_numerator": 919091259, + "fee_asset_price_numerator": 9292279788 + }, + "header": { + "excess_mana": 1322384541, + "mana_used": 97911435, + "proving_cost_per_mana_numerator": 728383216, + "fee_asset_price_numerator": 9763078118 + }, + "oracle_input": { + "proving_cost_modifier": -190708043, + "fee_asset_price_modifier": 470798330 + }, + "outputs": { + "fee_asset_price_at_execution": 10973770121, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29983649, + "proving_cost": 5465359464, + "congestion_cost": 20323147897, + "congestion_multiplier": 4698249132 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 329033671, + "proving_cost": 59975598386, + "congestion_cost": 223021553156, + "congestion_multiplier": 4698249132 + } + } + }, + { + "l1_block_number": 20974934, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9177771259 + }, + "parent_header": { + "excess_mana": 1322384541, + "mana_used": 97911435, + "proving_cost_per_mana_numerator": 728383216, + "fee_asset_price_numerator": 9763078118 + }, + "header": { + "excess_mana": 1320295976, + "mana_used": 99481176, + "proving_cost_per_mana_numerator": 580576659, + "fee_asset_price_numerator": 9915158567 + }, + "oracle_input": { + "proving_cost_modifier": -147806557, + "fee_asset_price_modifier": 152080449 + }, + "outputs": { + "fee_asset_price_at_execution": 11025556256, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30401367, + "proving_cost": 5454946516, + "congestion_cost": 20223284071, + "congestion_multiplier": 4686782407 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 335191982, + "proving_cost": 60143819685, + "congestion_cost": 222972956205, + "congestion_multiplier": 4686782407 + } + } + }, + { + "l1_block_number": 20974937, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9151655035 + }, + "parent_header": { + "excess_mana": 1320295976, + "mana_used": 99481176, + "proving_cost_per_mana_numerator": 580576659, + "fee_asset_price_numerator": 9915158567 + }, + "header": { + "excess_mana": 1319777152, + "mana_used": 102737449, + "proving_cost_per_mana_numerator": 599954471, + "fee_asset_price_numerator": 9619014183 + }, + "oracle_input": { + "proving_cost_modifier": 19377812, + "fee_asset_price_modifier": -296144384 + }, + "outputs": { + "fee_asset_price_at_execution": 11042336728, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30314857, + "proving_cost": 5446889703, + "congestion_cost": 20177683551, + "congestion_multiplier": 4683938281 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 334746858, + "proving_cost": 60146390220, + "congestion_cost": 222808776161, + "congestion_multiplier": 4683938281 + } + } + }, + { + "l1_block_number": 20974940, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10111441008 + }, + "parent_header": { + "excess_mana": 1319777152, + "mana_used": 102737449, + "proving_cost_per_mana_numerator": 599954471, + "fee_asset_price_numerator": 9619014183 + }, + "header": { + "excess_mana": 1322514601, + "mana_used": 116287303, + "proving_cost_per_mana_numerator": 559406423, + "fee_asset_price_numerator": 9289033428 + }, + "oracle_input": { + "proving_cost_modifier": -40548048, + "fee_asset_price_modifier": -329980755 + }, + "outputs": { + "fee_asset_price_at_execution": 11009683842, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33494148, + "proving_cost": 5447945294, + "congestion_cost": 20275647821, + "congestion_multiplier": 4698964120 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 368759980, + "proving_cost": 59980155275, + "congestion_cost": 223228472200, + "congestion_multiplier": 4698964120 + } + } + }, + { + "l1_block_number": 20974943, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9743090500 + }, + "parent_header": { + "excess_mana": 1322514601, + "mana_used": 116287303, + "proving_cost_per_mana_numerator": 559406423, + "fee_asset_price_numerator": 9289033428 + }, + "header": { + "excess_mana": 1338801904, + "mana_used": 92831721, + "proving_cost_per_mana_numerator": 522669976, + "fee_asset_price_numerator": 9057063136 + }, + "oracle_input": { + "proving_cost_modifier": -36736447, + "fee_asset_price_modifier": -231970292 + }, + "outputs": { + "fee_asset_price_at_execution": 10973413879, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32273987, + "proving_cost": 5445736706, + "congestion_cost": 20758192326, + "congestion_multiplier": 4789366887 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 354155816, + "proving_cost": 59758322751, + "congestion_cost": 227788235773, + "congestion_multiplier": 4789366887 + } + } + }, + { + "l1_block_number": 20974946, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9439894878 + }, + "parent_header": { + "excess_mana": 1338801904, + "mana_used": 92831721, + "proving_cost_per_mana_numerator": 522669976, + "fee_asset_price_numerator": 9057063136 + }, + "header": { + "excess_mana": 1331633625, + "mana_used": 77640995, + "proving_cost_per_mana_numerator": 580693964, + "fee_asset_price_numerator": 9091408259 + }, + "oracle_input": { + "proving_cost_modifier": 58023988, + "fee_asset_price_modifier": 34345123 + }, + "outputs": { + "fee_asset_price_at_execution": 10947988320, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31269651, + "proving_cost": 5443736503, + "congestion_cost": 20527807305, + "congestion_multiplier": 4749366983 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 342339773, + "proving_cost": 59597963652, + "congestion_cost": 224738194610, + "congestion_multiplier": 4749366983 + } + } + }, + { + "l1_block_number": 20974949, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9405583805 + }, + "parent_header": { + "excess_mana": 1331633625, + "mana_used": 77640995, + "proving_cost_per_mana_numerator": 580693964, + "fee_asset_price_numerator": 9091408259 + }, + "header": { + "excess_mana": 1309274620, + "mana_used": 119848095, + "proving_cost_per_mana_numerator": 400210010, + "fee_asset_price_numerator": 8805169513 + }, + "oracle_input": { + "proving_cost_modifier": -180483954, + "fee_asset_price_modifier": -286238746 + }, + "outputs": { + "fee_asset_price_at_execution": 10951749066, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31155996, + "proving_cost": 5446896093, + "congestion_cost": 19867439967, + "congestion_multiplier": 4626734402 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 341212650, + "proving_cost": 59653039199, + "congestion_cost": 217583217102, + "congestion_multiplier": 4626734402 + } + } + }, + { + "l1_block_number": 20974952, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9725564097 + }, + "parent_header": { + "excess_mana": 1309274620, + "mana_used": 119848095, + "proving_cost_per_mana_numerator": 400210010, + "fee_asset_price_numerator": 8805169513 + }, + "header": { + "excess_mana": 1329122715, + "mana_used": 104571961, + "proving_cost_per_mana_numerator": 389834369, + "fee_asset_price_numerator": 8101281380 + }, + "oracle_input": { + "proving_cost_modifier": -10375641, + "fee_asset_price_modifier": -703888133 + }, + "outputs": { + "fee_asset_price_at_execution": 10920445739, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32215931, + "proving_cost": 5437074185, + "congestion_cost": 20430177368, + "congestion_multiplier": 4735434935 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 351812326, + "proving_cost": 59375273616, + "congestion_cost": 223106643385, + "congestion_multiplier": 4735434935 + } + } + }, + { + "l1_block_number": 20974955, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9211947631 + }, + "parent_header": { + "excess_mana": 1329122715, + "mana_used": 104571961, + "proving_cost_per_mana_numerator": 389834369, + "fee_asset_price_numerator": 8101281380 + }, + "header": { + "excess_mana": 1333694676, + "mana_used": 101810527, + "proving_cost_per_mana_numerator": 427108560, + "fee_asset_price_numerator": 8211979675 + }, + "oracle_input": { + "proving_cost_modifier": 37274191, + "fee_asset_price_modifier": 110698295 + }, + "outputs": { + "fee_asset_price_at_execution": 10843847915, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30514576, + "proving_cost": 5436510083, + "congestion_cost": 20560569849, + "congestion_multiplier": 4760833567 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 330895421, + "proving_cost": 58952688528, + "congestion_cost": 222955692488, + "congestion_multiplier": 4760833567 + } + } + }, + { + "l1_block_number": 20974958, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9168730681 + }, + "parent_header": { + "excess_mana": 1333694676, + "mana_used": 101810527, + "proving_cost_per_mana_numerator": 427108560, + "fee_asset_price_numerator": 8211979675 + }, + "header": { + "excess_mana": 1335505203, + "mana_used": 95686443, + "proving_cost_per_mana_numerator": 441651375, + "fee_asset_price_numerator": 7634681671 + }, + "oracle_input": { + "proving_cost_modifier": 14542815, + "fee_asset_price_modifier": -577298004 + }, + "outputs": { + "fee_asset_price_at_execution": 10855858516, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30371420, + "proving_cost": 5438536876, + "congestion_cost": 20622866034, + "congestion_multiplier": 4770929209 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 329707838, + "proving_cost": 59039986859, + "congestion_cost": 223878915859, + "congestion_multiplier": 4770929209 + } + } + }, + { + "l1_block_number": 20974961, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9071304225 + }, + "parent_header": { + "excess_mana": 1335505203, + "mana_used": 95686443, + "proving_cost_per_mana_numerator": 441651375, + "fee_asset_price_numerator": 7634681671 + }, + "header": { + "excess_mana": 1331191646, + "mana_used": 87209194, + "proving_cost_per_mana_numerator": 252255241, + "fee_asset_price_numerator": 7846156025 + }, + "oracle_input": { + "proving_cost_modifier": -189396134, + "fee_asset_price_modifier": 211474354 + }, + "outputs": { + "fee_asset_price_at_execution": 10793368413, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30048695, + "proving_cost": 5439327850, + "congestion_cost": 20493270678, + "congestion_multiplier": 4746911647 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 324326635, + "proving_cost": 58708669404, + "congestion_cost": 221191420414, + "congestion_multiplier": 4746911647 + } + } + }, + { + "l1_block_number": 20974964, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8301086454 + }, + "parent_header": { + "excess_mana": 1331191646, + "mana_used": 87209194, + "proving_cost_per_mana_numerator": 252255241, + "fee_asset_price_numerator": 7846156025 + }, + "header": { + "excess_mana": 1318400840, + "mana_used": 103763183, + "proving_cost_per_mana_numerator": 370929871, + "fee_asset_price_numerator": 7994895828 + }, + "oracle_input": { + "proving_cost_modifier": 118674630, + "fee_asset_price_modifier": 148739803 + }, + "outputs": { + "fee_asset_price_at_execution": 10816217770, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 27497348, + "proving_cost": 5429035723, + "congestion_cost": 20060408407, + "congestion_multiplier": 4676401874 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 297417304, + "proving_cost": 58721632661, + "congestion_cost": 216977745885, + "congestion_multiplier": 4676401874 + } + } + }, + { + "l1_block_number": 20974967, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8897960618 + }, + "parent_header": { + "excess_mana": 1318400840, + "mana_used": 103763183, + "proving_cost_per_mana_numerator": 370929871, + "fee_asset_price_numerator": 7994895828 + }, + "header": { + "excess_mana": 1322164023, + "mana_used": 96243533, + "proving_cost_per_mana_numerator": 435025193, + "fee_asset_price_numerator": 8064434274 + }, + "oracle_input": { + "proving_cost_modifier": 64095322, + "fee_asset_price_modifier": 69538446 + }, + "outputs": { + "fee_asset_price_at_execution": 10832317762, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29474494, + "proving_cost": 5435482436, + "congestion_cost": 20204148580, + "congestion_multiplier": 4697037111 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 319277084, + "proving_cost": 58878872936, + "congestion_cost": 218857757529, + "congestion_multiplier": 4697037111 + } + } + }, + { + "l1_block_number": 20974970, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8878052220 + }, + "parent_header": { + "excess_mana": 1322164023, + "mana_used": 96243533, + "proving_cost_per_mana_numerator": 435025193, + "fee_asset_price_numerator": 8064434274 + }, + "header": { + "excess_mana": 1318407556, + "mana_used": 108984685, + "proving_cost_per_mana_numerator": 460258625, + "fee_asset_price_numerator": 7922857959 + }, + "oracle_input": { + "proving_cost_modifier": 25233432, + "fee_asset_price_modifier": -141576315 + }, + "outputs": { + "fee_asset_price_at_execution": 10839853007, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29408547, + "proving_cost": 5438967442, + "congestion_cost": 20104148674, + "congestion_multiplier": 4676438620 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 318784326, + "proving_cost": 58957607581, + "congestion_cost": 217926016457, + "congestion_multiplier": 4676438620 + } + } + }, + { + "l1_block_number": 20974973, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8944979149 + }, + "parent_header": { + "excess_mana": 1318407556, + "mana_used": 108984685, + "proving_cost_per_mana_numerator": 460258625, + "fee_asset_price_numerator": 7922857959 + }, + "header": { + "excess_mana": 1327392241, + "mana_used": 79765363, + "proving_cost_per_mana_numerator": 534368547, + "fee_asset_price_numerator": 8870191059 + }, + "oracle_input": { + "proving_cost_modifier": 74109922, + "fee_asset_price_modifier": 947333100 + }, + "outputs": { + "fee_asset_price_at_execution": 10824517201, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29630243, + "proving_cost": 5440340054, + "congestion_cost": 20380327197, + "congestion_multiplier": 4725857014 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 320733075, + "proving_cost": 58889054493, + "congestion_cost": 220607202305, + "congestion_multiplier": 4725857014 + } + } + }, + { + "l1_block_number": 20974976, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8661304425 + }, + "parent_header": { + "excess_mana": 1327392241, + "mana_used": 79765363, + "proving_cost_per_mana_numerator": 534368547, + "fee_asset_price_numerator": 8870191059 + }, + "header": { + "excess_mana": 1307157604, + "mana_used": 111586525, + "proving_cost_per_mana_numerator": 631784323, + "fee_asset_price_numerator": 8097895451 + }, + "oracle_input": { + "proving_cost_modifier": 97415776, + "fee_asset_price_modifier": -772295608 + }, + "outputs": { + "fee_asset_price_at_execution": 10927548691, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 28690570, + "proving_cost": 5444373380, + "congestion_cost": 19786705617, + "congestion_multiplier": 4615288584 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 313517600, + "proving_cost": 59493655201, + "congestion_cost": 216220189064, + "congestion_multiplier": 4615288584 + } + } + }, + { + "l1_block_number": 20974979, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8725503529 + }, + "parent_header": { + "excess_mana": 1307157604, + "mana_used": 111586525, + "proving_cost_per_mana_numerator": 631784323, + "fee_asset_price_numerator": 8097895451 + }, + "header": { + "excess_mana": 1318744129, + "mana_used": 89963278, + "proving_cost_per_mana_numerator": 528282288, + "fee_asset_price_numerator": 7833069405 + }, + "oracle_input": { + "proving_cost_modifier": -103502035, + "fee_asset_price_modifier": -264826046 + }, + "outputs": { + "fee_asset_price_at_execution": 10843480756, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 28903230, + "proving_cost": 5449679642, + "congestion_cost": 20151764655, + "congestion_multiplier": 4678280520 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 313411618, + "proving_cost": 59093496324, + "congestion_cost": 218515272235, + "congestion_multiplier": 4678280520 + } + } + }, + { + "l1_block_number": 20974982, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8635480789 + }, + "parent_header": { + "excess_mana": 1318744129, + "mana_used": 89963278, + "proving_cost_per_mana_numerator": 528282288, + "fee_asset_price_numerator": 7833069405 + }, + "header": { + "excess_mana": 1308707407, + "mana_used": 105050231, + "proving_cost_per_mana_numerator": 534505171, + "fee_asset_price_numerator": 8001097969 + }, + "oracle_input": { + "proving_cost_modifier": 6222883, + "fee_asset_price_modifier": 168028564 + }, + "outputs": { + "fee_asset_price_at_execution": 10814802386, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 28605030, + "proving_cost": 5444042031, + "congestion_cost": 19831039272, + "congestion_multiplier": 4623664938 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 309357746, + "proving_cost": 58876238746, + "congestion_cost": 214468770835, + "congestion_multiplier": 4623664938 + } + } + }, + { + "l1_block_number": 20974985, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9253198960 + }, + "parent_header": { + "excess_mana": 1308707407, + "mana_used": 105050231, + "proving_cost_per_mana_numerator": 534505171, + "fee_asset_price_numerator": 8001097969 + }, + "header": { + "excess_mana": 1313757638, + "mana_used": 91611611, + "proving_cost_per_mana_numerator": 559614429, + "fee_asset_price_numerator": 8101746392 + }, + "oracle_input": { + "proving_cost_modifier": 25109258, + "fee_asset_price_modifier": 100648423 + }, + "outputs": { + "fee_asset_price_at_execution": 10832989618, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 30651221, + "proving_cost": 5444380818, + "congestion_cost": 19989703249, + "congestion_multiplier": 4651065986 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 332044358, + "proving_cost": 58978920877, + "congestion_cost": 216548247763, + "congestion_multiplier": 4651065986 + } + } + }, + { + "l1_block_number": 20974988, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8772488689 + }, + "parent_header": { + "excess_mana": 1313757638, + "mana_used": 91611611, + "proving_cost_per_mana_numerator": 559614429, + "fee_asset_price_numerator": 8101746392 + }, + "header": { + "excess_mana": 1305369249, + "mana_used": 113252671, + "proving_cost_per_mana_numerator": 417177712, + "fee_asset_price_numerator": 8070934001 + }, + "oracle_input": { + "proving_cost_modifier": -142436717, + "fee_asset_price_modifier": -30812391 + }, + "outputs": { + "fee_asset_price_at_execution": 10843898340, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29058868, + "proving_cost": 5445748033, + "congestion_cost": 19740192412, + "congestion_multiplier": 4605641764 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 315111410, + "proving_cost": 59053138055, + "congestion_cost": 214060639727, + "congestion_multiplier": 4605641764 + } + } + }, + { + "l1_block_number": 20974991, + "l1_fees": { + "blob_fee": 1, + "base_fee": 8898215086 + }, + "parent_header": { + "excess_mana": 1305369249, + "mana_used": 113252671, + "proving_cost_per_mana_numerator": 417177712, + "fee_asset_price_numerator": 8070934001 + }, + "header": { + "excess_mana": 1318621920, + "mana_used": 90250478, + "proving_cost_per_mana_numerator": 245435262, + "fee_asset_price_numerator": 7785208408 + }, + "oracle_input": { + "proving_cost_modifier": -171742450, + "fee_asset_price_modifier": -285725593 + }, + "outputs": { + "fee_asset_price_at_execution": 10840557591, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 29475337, + "proving_cost": 5437996810, + "congestion_cost": 20107239241, + "congestion_multiplier": 4677611646 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 319529088, + "proving_cost": 58950917598, + "congestion_cost": 217973684988, + "congestion_multiplier": 4677611646 + } + } + }, + { + "l1_block_number": 20974994, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9375929800 + }, + "parent_header": { + "excess_mana": 1318621920, + "mana_used": 90250478, + "proving_cost_per_mana_numerator": 245435262, + "fee_asset_price_numerator": 7785208408 + }, + "header": { + "excess_mana": 1308872398, + "mana_used": 95210532, + "proving_cost_per_mana_numerator": 318267081, + "fee_asset_price_numerator": 8018327579 + }, + "oracle_input": { + "proving_cost_modifier": 72831819, + "fee_asset_price_modifier": 233119171 + }, + "outputs": { + "fee_asset_price_at_execution": 10809627552, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 31057767, + "proving_cost": 5428665476, + "congestion_cost": 19789081232, + "congestion_multiplier": 4624557574 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 335722893, + "proving_cost": 58681851899, + "congestion_cost": 213912597714, + "congestion_multiplier": 4624557574 + } + } + }, + { + "l1_block_number": 20974997, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9712139037 + }, + "parent_header": { + "excess_mana": 1308872398, + "mana_used": 95210532, + "proving_cost_per_mana_numerator": 318267081, + "fee_asset_price_numerator": 8018327579 + }, + "header": { + "excess_mana": 1304082930, + "mana_used": 57474297, + "proving_cost_per_mana_numerator": 377674874, + "fee_asset_price_numerator": 8058999714 + }, + "oracle_input": { + "proving_cost_modifier": 59407793, + "fee_asset_price_modifier": 40672135 + }, + "outputs": { + "fee_asset_price_at_execution": 10834856261, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32171460, + "proving_cost": 5432620712, + "congestion_cost": 19666232392, + "congestion_multiplier": 4598715518 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 348573144, + "proving_cost": 58861664535, + "congestion_cost": 213080801162, + "congestion_multiplier": 4598715518 + } + } + }, + { + "l1_block_number": 20975000, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10320266532 + }, + "parent_header": { + "excess_mana": 1304082930, + "mana_used": 57474297, + "proving_cost_per_mana_numerator": 377674874, + "fee_asset_price_numerator": 8058999714 + }, + "header": { + "excess_mana": 1261557227, + "mana_used": 135729420, + "proving_cost_per_mana_numerator": 417528624, + "fee_asset_price_numerator": 7594293458 + }, + "oracle_input": { + "proving_cost_modifier": 39853750, + "fee_asset_price_modifier": -464706256 + }, + "outputs": { + "fee_asset_price_at_execution": 10839263925, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34185882, + "proving_cost": 5435849071, + "congestion_cost": 18464130689, + "congestion_multiplier": 4375505065 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 370549797, + "proving_cost": 58920602737, + "congestion_cost": 200137585683, + "congestion_multiplier": 4375505065 + } + } + }, + { + "l1_block_number": 20975003, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10168459328 + }, + "parent_header": { + "excess_mana": 1261557227, + "mana_used": 135729420, + "proving_cost_per_mana_numerator": 417528624, + "fee_asset_price_numerator": 7594293458 + }, + "header": { + "excess_mana": 1297286647, + "mana_used": 112984877, + "proving_cost_per_mana_numerator": 524867736, + "fee_asset_price_numerator": 7779610709 + }, + "oracle_input": { + "proving_cost_modifier": 107339112, + "fee_asset_price_modifier": 185317251 + }, + "outputs": { + "fee_asset_price_at_execution": 10789010044, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 33683021, + "proving_cost": 5438015893, + "congestion_cost": 19491795489, + "congestion_multiplier": 4562293137 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 363406451, + "proving_cost": 58670808089, + "congestion_cost": 210297177306, + "congestion_multiplier": 4562293137 + } + } + }, + { + "l1_block_number": 20975006, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10401786820 + }, + "parent_header": { + "excess_mana": 1297286647, + "mana_used": 112984877, + "proving_cost_per_mana_numerator": 524867736, + "fee_asset_price_numerator": 7779610709 + }, + "header": { + "excess_mana": 1310271524, + "mana_used": 110485095, + "proving_cost_per_mana_numerator": 519626542, + "fee_asset_price_numerator": 8264827175 + }, + "oracle_input": { + "proving_cost_modifier": -5241194, + "fee_asset_price_modifier": 485216466 + }, + "outputs": { + "fee_asset_price_at_execution": 10809022478, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 34455918, + "proving_cost": 5443856145, + "congestion_cost": 19897963890, + "congestion_multiplier": 4632134070 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 372434792, + "proving_cost": 58842763438, + "congestion_cost": 215077538953, + "congestion_multiplier": 4632134070 + } + } + }, + { + "l1_block_number": 20975009, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10702980460 + }, + "parent_header": { + "excess_mana": 1310271524, + "mana_used": 110485095, + "proving_cost_per_mana_numerator": 519626542, + "fee_asset_price_numerator": 8264827175 + }, + "header": { + "excess_mana": 1320756619, + "mana_used": 102141151, + "proving_cost_per_mana_numerator": 478575697, + "fee_asset_price_numerator": 7482690588 + }, + "oracle_input": { + "proving_cost_modifier": -41050845, + "fee_asset_price_modifier": -782136587 + }, + "outputs": { + "fee_asset_price_at_execution": 10861597083, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35453622, + "proving_cost": 5443570829, + "congestion_cost": 20213814437, + "congestion_multiplier": 4689309040 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 385082957, + "proving_cost": 59125873037, + "congestion_cost": 219554307925, + "congestion_multiplier": 4689309040 + } + } + }, + { + "l1_block_number": 20975012, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11536948339 + }, + "parent_header": { + "excess_mana": 1320756619, + "mana_used": 102141151, + "proving_cost_per_mana_numerator": 478575697, + "fee_asset_price_numerator": 7482690588 + }, + "header": { + "excess_mana": 1322897770, + "mana_used": 95947526, + "proving_cost_per_mana_numerator": 556287357, + "fee_asset_price_numerator": 7910988307 + }, + "oracle_input": { + "proving_cost_modifier": 77711660, + "fee_asset_price_modifier": 428297719 + }, + "outputs": { + "fee_asset_price_at_execution": 10776975916, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 38216141, + "proving_cost": 5441336656, + "congestion_cost": 20280214903, + "congestion_multiplier": 4701071174 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 411854431, + "proving_cost": 58641154092, + "congestion_cost": 218559387580, + "congestion_multiplier": 4701071174 + } + } + }, + { + "l1_block_number": 20975015, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11359031521 + }, + "parent_header": { + "excess_mana": 1322897770, + "mana_used": 95947526, + "proving_cost_per_mana_numerator": 556287357, + "fee_asset_price_numerator": 7910988307 + }, + "header": { + "excess_mana": 1318845296, + "mana_used": 92861285, + "proving_cost_per_mana_numerator": 577567345, + "fee_asset_price_numerator": 8043579839 + }, + "oracle_input": { + "proving_cost_modifier": 21279988, + "fee_asset_price_modifier": 132591532 + }, + "outputs": { + "fee_asset_price_at_execution": 10823232445, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 37626791, + "proving_cost": 5445566852, + "congestion_cost": 20171760841, + "congestion_multiplier": 4678834299 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 407243505, + "proving_cost": 58938635833, + "congestion_cost": 218323656407, + "congestion_multiplier": 4678834299 + } + } + }, + { + "l1_block_number": 20975018, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11201567819 + }, + "parent_header": { + "excess_mana": 1318845296, + "mana_used": 92861285, + "proving_cost_per_mana_numerator": 577567345, + "fee_asset_price_numerator": 8043579839 + }, + "header": { + "excess_mana": 1311706581, + "mana_used": 107725422, + "proving_cost_per_mana_numerator": 576270642, + "fee_asset_price_numerator": 8673737845 + }, + "oracle_input": { + "proving_cost_modifier": -1296703, + "fee_asset_price_modifier": 630158006 + }, + "outputs": { + "fee_asset_price_at_execution": 10837592653, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 37105193, + "proving_cost": 5446725792, + "congestion_cost": 19960695297, + "congestion_multiplier": 4639918034 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 402130967, + "proving_cost": 59029395426, + "congestion_cost": 216325884699, + "congestion_multiplier": 4639918034 + } + } + }, + { + "l1_block_number": 20975021, + "l1_fees": { + "blob_fee": 1, + "base_fee": 9913252976 + }, + "parent_header": { + "excess_mana": 1311706581, + "mana_used": 107725422, + "proving_cost_per_mana_numerator": 576270642, + "fee_asset_price_numerator": 8673737845 + }, + "header": { + "excess_mana": 1319432003, + "mana_used": 114906142, + "proving_cost_per_mana_numerator": 589826202, + "fee_asset_price_numerator": 9223117112 + }, + "oracle_input": { + "proving_cost_modifier": 13555560, + "fee_asset_price_modifier": 549379267 + }, + "outputs": { + "fee_asset_price_at_execution": 10906102243, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 32837650, + "proving_cost": 5446655164, + "congestion_cost": 20175751030, + "congestion_multiplier": 4682047174 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 358130768, + "proving_cost": 59401778100, + "congestion_cost": 220038803562, + "congestion_multiplier": 4682047174 + } + } + }, + { + "l1_block_number": 20975024, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10599983896 + }, + "parent_header": { + "excess_mana": 1319432003, + "mana_used": 114906142, + "proving_cost_per_mana_numerator": 589826202, + "fee_asset_price_numerator": 9223117112 + }, + "header": { + "excess_mana": 1334338145, + "mana_used": 94649328, + "proving_cost_per_mana_numerator": 551090117, + "fee_asset_price_numerator": 9243600887 + }, + "oracle_input": { + "proving_cost_modifier": -38736085, + "fee_asset_price_modifier": 20483775 + }, + "outputs": { + "fee_asset_price_at_execution": 10966182992, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35112446, + "proving_cost": 5447393539, + "congestion_cost": 20638450530, + "congestion_multiplier": 4764419152 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 385049508, + "proving_cost": 59737114378, + "congestion_cost": 226325025183, + "congestion_multiplier": 4764419152 + } + } + }, + { + "l1_block_number": 20975027, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11446110527 + }, + "parent_header": { + "excess_mana": 1334338145, + "mana_used": 94649328, + "proving_cost_per_mana_numerator": 551090117, + "fee_asset_price_numerator": 9243600887 + }, + "header": { + "excess_mana": 1328987473, + "mana_used": 92306873, + "proving_cost_per_mana_numerator": 580816426, + "fee_asset_price_numerator": 8644364312 + }, + "oracle_input": { + "proving_cost_modifier": 29726309, + "fee_asset_price_modifier": -599236575 + }, + "outputs": { + "fee_asset_price_at_execution": 10968429510, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 37915241, + "proving_cost": 5445283841, + "congestion_cost": 20478025152, + "congestion_multiplier": 4734685691 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 415870648, + "proving_cost": 59726211971, + "congestion_cost": 224611775383, + "congestion_multiplier": 4734685691 + } + } + }, + { + "l1_block_number": 20975030, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11076948971 + }, + "parent_header": { + "excess_mana": 1328987473, + "mana_used": 92306873, + "proving_cost_per_mana_numerator": 580816426, + "fee_asset_price_numerator": 8644364312 + }, + "header": { + "excess_mana": 1321294346, + "mana_used": 101265912, + "proving_cost_per_mana_numerator": 620609103, + "fee_asset_price_numerator": 8736960733 + }, + "oracle_input": { + "proving_cost_modifier": 39792677, + "fee_asset_price_modifier": 92596421 + }, + "outputs": { + "fee_asset_price_at_execution": 10902899206, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 36692393, + "proving_cost": 5446902763, + "congestion_cost": 20246860163, + "congestion_multiplier": 4692260203 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 400053462, + "proving_cost": 59387031809, + "congestion_cost": 220749475595, + "congestion_multiplier": 4692260203 + } + } + }, + { + "l1_block_number": 20975033, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11283306741 + }, + "parent_header": { + "excess_mana": 1321294346, + "mana_used": 101265912, + "proving_cost_per_mana_numerator": 620609103, + "fee_asset_price_numerator": 8736960733 + }, + "header": { + "excess_mana": 1322560258, + "mana_used": 100901498, + "proving_cost_per_mana_numerator": 595189786, + "fee_asset_price_numerator": 9164105855 + }, + "oracle_input": { + "proving_cost_modifier": -25419317, + "fee_asset_price_modifier": 427145122 + }, + "outputs": { + "fee_asset_price_at_execution": 10912999576, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 37375953, + "proving_cost": 5449070663, + "congestion_cost": 20295546381, + "congestion_multiplier": 4699215139 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 407883759, + "proving_cost": 59465705834, + "congestion_cost": 221485289050, + "congestion_multiplier": 4699215139 + } + } + }, + { + "l1_block_number": 20975036, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10860587186 + }, + "parent_header": { + "excess_mana": 1322560258, + "mana_used": 100901498, + "proving_cost_per_mana_numerator": 595189786, + "fee_asset_price_numerator": 9164105855 + }, + "header": { + "excess_mana": 1323461756, + "mana_used": 97604527, + "proving_cost_per_mana_numerator": 652162855, + "fee_asset_price_numerator": 8932035693 + }, + "oracle_input": { + "proving_cost_modifier": 56973069, + "fee_asset_price_modifier": -232070162 + }, + "outputs": { + "fee_asset_price_at_execution": 10959713619, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35975695, + "proving_cost": 5447685722, + "congestion_cost": 20312437487, + "congestion_multiplier": 4704174263 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 394283314, + "proving_cost": 59705075399, + "congestion_cost": 222618497761, + "congestion_multiplier": 4704174263 + } + } + }, + { + "l1_block_number": 20975039, + "l1_fees": { + "blob_fee": 1, + "base_fee": 10866970943 + }, + "parent_header": { + "excess_mana": 1323461756, + "mana_used": 97604527, + "proving_cost_per_mana_numerator": 652162855, + "fee_asset_price_numerator": 8932035693 + }, + "header": { + "excess_mana": 1321066283, + "mana_used": 90323102, + "proving_cost_per_mana_numerator": 633173688, + "fee_asset_price_numerator": 8577437773 + }, + "oracle_input": { + "proving_cost_modifier": -18989167, + "fee_asset_price_modifier": -354597920 + }, + "outputs": { + "fee_asset_price_at_execution": 10934308883, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 35996841, + "proving_cost": 5450790320, + "congestion_cost": 20251777044, + "congestion_multiplier": 4691008317 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 393600578, + "proving_cost": 59600625015, + "congestion_cost": 221439185628, + "congestion_multiplier": 4691008317 + } + } + }, + { + "l1_block_number": 20975042, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11041792448 + }, + "parent_header": { + "excess_mana": 1321066283, + "mana_used": 90323102, + "proving_cost_per_mana_numerator": 633173688, + "fee_asset_price_numerator": 8577437773 + }, + "header": { + "excess_mana": 1311389385, + "mana_used": 90949554, + "proving_cost_per_mana_numerator": 529914617, + "fee_asset_price_numerator": 8467260121 + }, + "oracle_input": { + "proving_cost_modifier": -103259071, + "fee_asset_price_modifier": -110177652 + }, + "outputs": { + "fee_asset_price_at_execution": 10895604714, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 36575937, + "proving_cost": 5449755359, + "congestion_cost": 19960350715, + "congestion_multiplier": 4638196390 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 398516951, + "proving_cost": 59378380179, + "congestion_cost": 217480091343, + "congestion_multiplier": 4638196390 + } + } + }, + { + "l1_block_number": 20975045, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11833006757 + }, + "parent_header": { + "excess_mana": 1311389385, + "mana_used": 90949554, + "proving_cost_per_mana_numerator": 529914617, + "fee_asset_price_numerator": 8467260121 + }, + "header": { + "excess_mana": 1302338939, + "mana_used": 112229615, + "proving_cost_per_mana_numerator": 474886245, + "fee_asset_price_numerator": 8426877839 + }, + "oracle_input": { + "proving_cost_modifier": -55028372, + "fee_asset_price_modifier": -40382282 + }, + "outputs": { + "fee_asset_price_at_execution": 10883606803, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 39196834, + "proving_cost": 5444130897, + "congestion_cost": 19681536035, + "congestion_multiplier": 4589341546 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 426602929, + "proving_cost": 59251780067, + "congestion_cost": 214206099484, + "congestion_multiplier": 4589341546 + } + } + }, + { + "l1_block_number": 20975048, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11691009725 + }, + "parent_header": { + "excess_mana": 1302338939, + "mana_used": 112229615, + "proving_cost_per_mana_numerator": 474886245, + "fee_asset_price_numerator": 8426877839 + }, + "header": { + "excess_mana": 1314568554, + "mana_used": 101270628, + "proving_cost_per_mana_numerator": 632296174, + "fee_asset_price_numerator": 8794436593 + }, + "oracle_input": { + "proving_cost_modifier": 157409929, + "fee_asset_price_modifier": 367558754 + }, + "outputs": { + "fee_asset_price_at_execution": 10879212642, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 38726469, + "proving_cost": 5441135904, + "congestion_cost": 20031532129, + "congestion_multiplier": 4655480880 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 421313491, + "proving_cost": 59195274513, + "congestion_cost": 217927297576, + "congestion_multiplier": 4655480880 + } + } + }, + { + "l1_block_number": 20975051, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11981504880 + }, + "parent_header": { + "excess_mana": 1314568554, + "mana_used": 101270628, + "proving_cost_per_mana_numerator": 632296174, + "fee_asset_price_numerator": 8794436593 + }, + "header": { + "excess_mana": 1315839182, + "mana_used": 95222710, + "proving_cost_per_mana_numerator": 423476750, + "fee_asset_price_numerator": 9220027633 + }, + "oracle_input": { + "proving_cost_modifier": -208819424, + "fee_asset_price_modifier": 425591040 + }, + "outputs": { + "fee_asset_price_at_execution": 10919273719, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 39688734, + "proving_cost": 5449707537, + "congestion_cost": 20104403476, + "congestion_multiplier": 4662407027 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 433372150, + "proving_cost": 59506848285, + "congestion_cost": 219525484511, + "congestion_multiplier": 4662407027 + } + } + }, + { + "l1_block_number": 20975054, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12160928021 + }, + "parent_header": { + "excess_mana": 1315839182, + "mana_used": 95222710, + "proving_cost_per_mana_numerator": 423476750, + "fee_asset_price_numerator": 9220027633 + }, + "header": { + "excess_mana": 1311061892, + "mana_used": 123820176, + "proving_cost_per_mana_numerator": 348788374, + "fee_asset_price_numerator": 8941079810 + }, + "oracle_input": { + "proving_cost_modifier": -74688376, + "fee_asset_price_modifier": -278947823 + }, + "outputs": { + "fee_asset_price_at_execution": 10965844199, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 40283074, + "proving_cost": 5438339362, + "congestion_cost": 19922569607, + "congestion_multiplier": 4636419527 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 441737913, + "proving_cost": 59635982144, + "congestion_cost": 218467794354, + "congestion_multiplier": 4636419527 + } + } + }, + { + "l1_block_number": 20975057, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12913546101 + }, + "parent_header": { + "excess_mana": 1311061892, + "mana_used": 123820176, + "proving_cost_per_mana_numerator": 348788374, + "fee_asset_price_numerator": 8941079810 + }, + "header": { + "excess_mana": 1334882068, + "mana_used": 93982896, + "proving_cost_per_mana_numerator": 195305836, + "fee_asset_price_numerator": 8870005590 + }, + "oracle_input": { + "proving_cost_modifier": -153482538, + "fee_asset_price_modifier": -71074220 + }, + "outputs": { + "fee_asset_price_at_execution": 10935297840, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 42776121, + "proving_cost": 5434279072, + "congestion_cost": 20634543335, + "congestion_multiplier": 4767452145 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 467769623, + "proving_cost": 59425460197, + "congestion_cost": 225644877160, + "congestion_multiplier": 4767452145 + } + } + }, + { + "l1_block_number": 20975060, + "l1_fees": { + "blob_fee": 1, + "base_fee": 14539177654 + }, + "parent_header": { + "excess_mana": 1334882068, + "mana_used": 93982896, + "proving_cost_per_mana_numerator": 195305836, + "fee_asset_price_numerator": 8870005590 + }, + "header": { + "excess_mana": 1328864964, + "mana_used": 90824690, + "proving_cost_per_mana_numerator": 122449014, + "fee_asset_price_numerator": 9650640266 + }, + "oracle_input": { + "proving_cost_modifier": -72856822, + "fee_asset_price_modifier": 780634676 + }, + "outputs": { + "fee_asset_price_at_execution": 10927528423, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 48161025, + "proving_cost": 5425944800, + "congestion_cost": 20440349967, + "congestion_multiplier": 4734007091 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 526280969, + "proving_cost": 59292166023, + "congestion_cost": 223362505240, + "congestion_multiplier": 4734007091 + } + } + }, + { + "l1_block_number": 20975063, + "l1_fees": { + "blob_fee": 1, + "base_fee": 16652594433 + }, + "parent_header": { + "excess_mana": 1328864964, + "mana_used": 90824690, + "proving_cost_per_mana_numerator": 122449014, + "fee_asset_price_numerator": 9650640266 + }, + "header": { + "excess_mana": 1319689654, + "mana_used": 105117350, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 9709646324 + }, + "oracle_input": { + "proving_cost_modifier": -141123043, + "fee_asset_price_modifier": 59006058 + }, + "outputs": { + "fee_asset_price_at_execution": 11013166324, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 55161719, + "proving_cost": 5421993068, + "congestion_cost": 20174873988, + "congestion_multiplier": 4683458798 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 607505186, + "proving_cost": 59713311465, + "congestion_cost": 222189242795, + "congestion_multiplier": 4683458798 + } + } + }, + { + "l1_block_number": 20975066, + "l1_fees": { + "blob_fee": 1, + "base_fee": 18249319128 + }, + "parent_header": { + "excess_mana": 1319689654, + "mana_used": 105117350, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 9709646324 + }, + "header": { + "excess_mana": 1324807004, + "mana_used": 101364337, + "proving_cost_per_mana_numerator": 128284611, + "fee_asset_price_numerator": 9289510144 + }, + "oracle_input": { + "proving_cost_modifier": 128284611, + "fee_asset_price_modifier": -420136180 + }, + "outputs": { + "fee_asset_price_at_execution": 11019666677, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 60450869, + "proving_cost": 5415357955, + "congestion_cost": 20323925414, + "congestion_multiplier": 4711584182 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 666148426, + "proving_cost": 59675439600, + "congestion_cost": 223962883630, + "congestion_multiplier": 4711584182 + } + } + }, + { + "l1_block_number": 20975069, + "l1_fees": { + "blob_fee": 1, + "base_fee": 18581711762 + }, + "parent_header": { + "excess_mana": 1324807004, + "mana_used": 101364337, + "proving_cost_per_mana_numerator": 128284611, + "fee_asset_price_numerator": 9289510144 + }, + "header": { + "excess_mana": 1326171341, + "mana_used": 98775140, + "proving_cost_per_mana_numerator": 10819532, + "fee_asset_price_numerator": 9750284946 + }, + "oracle_input": { + "proving_cost_modifier": -117465079, + "fee_asset_price_modifier": 460774802 + }, + "outputs": { + "fee_asset_price_at_execution": 10973466191, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 61551920, + "proving_cost": 5422309483, + "congestion_cost": 20395090193, + "congestion_multiplier": 4719111169 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 675437913, + "proving_cost": 59501529788, + "congestion_cost": 223804832695, + "congestion_multiplier": 4719111169 + } + } + }, + { + "l1_block_number": 20975072, + "l1_fees": { + "blob_fee": 1, + "base_fee": 18508034366 + }, + "parent_header": { + "excess_mana": 1326171341, + "mana_used": 98775140, + "proving_cost_per_mana_numerator": 10819532, + "fee_asset_price_numerator": 9750284946 + }, + "header": { + "excess_mana": 1324946481, + "mana_used": 102197042, + "proving_cost_per_mana_numerator": 26005399, + "fee_asset_price_numerator": 9952218389 + }, + "oracle_input": { + "proving_cost_modifier": 15185867, + "fee_asset_price_modifier": 201933443 + }, + "outputs": { + "fee_asset_price_at_execution": 11024145828, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 61307863, + "proving_cost": 5415943903, + "congestion_cost": 20333492677, + "congestion_multiplier": 4712353119 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 675866822, + "proving_cost": 59706155382, + "congestion_cost": 224159388463, + "congestion_multiplier": 4712353119 + } + } + }, + { + "l1_block_number": 20975075, + "l1_fees": { + "blob_fee": 1, + "base_fee": 16846912203 + }, + "parent_header": { + "excess_mana": 1324946481, + "mana_used": 102197042, + "proving_cost_per_mana_numerator": 26005399, + "fee_asset_price_numerator": 9952218389 + }, + "header": { + "excess_mana": 1327143523, + "mana_used": 88168307, + "proving_cost_per_mana_numerator": 114842777, + "fee_asset_price_numerator": 10106089984 + }, + "oracle_input": { + "proving_cost_modifier": 88837378, + "fee_asset_price_modifier": 153871595 + }, + "outputs": { + "fee_asset_price_at_execution": 11046429757, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 55805396, + "proving_cost": 5416766423, + "congestion_cost": 20382495173, + "congestion_multiplier": 4724481989 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 616450386, + "proving_cost": 59835929801, + "congestion_cost": 225153801200, + "congestion_multiplier": 4724481989 + } + } + }, + { + "l1_block_number": 20975078, + "l1_fees": { + "blob_fee": 1, + "base_fee": 20153470138 + }, + "parent_header": { + "excess_mana": 1327143523, + "mana_used": 88168307, + "proving_cost_per_mana_numerator": 114842777, + "fee_asset_price_numerator": 10106089984 + }, + "header": { + "excess_mana": 1315311830, + "mana_used": 116305637, + "proving_cost_per_mana_numerator": 126735087, + "fee_asset_price_numerator": 10553381925 + }, + "oracle_input": { + "proving_cost_modifier": 11892310, + "fee_asset_price_modifier": 447291941 + }, + "outputs": { + "fee_asset_price_at_execution": 11063440158, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 66758369, + "proving_cost": 5421580674, + "congestion_cost": 20084747964, + "congestion_multiplier": 4659531200 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 738577220, + "proving_cost": 59981333348, + "congestion_cost": 222206407188, + "congestion_multiplier": 4659531200 + } + } + }, + { + "l1_block_number": 20975081, + "l1_fees": { + "blob_fee": 1, + "base_fee": 20365754346 + }, + "parent_header": { + "excess_mana": 1315311830, + "mana_used": 116305637, + "proving_cost_per_mana_numerator": 126735087, + "fee_asset_price_numerator": 10553381925 + }, + "header": { + "excess_mana": 1331617467, + "mana_used": 83202142, + "proving_cost_per_mana_numerator": 5960869, + "fee_asset_price_numerator": 10576638721 + }, + "oracle_input": { + "proving_cost_modifier": -120774218, + "fee_asset_price_modifier": 23256796 + }, + "outputs": { + "fee_asset_price_at_execution": 11113036873, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 67461561, + "proving_cost": 5422225464, + "congestion_cost": 20582358386, + "congestion_multiplier": 4749277198 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 749702814, + "proving_cost": 60257391515, + "congestion_cost": 228732507676, + "congestion_multiplier": 4749277198 + } + } + }, + { + "l1_block_number": 20975084, + "l1_fees": { + "blob_fee": 1, + "base_fee": 19718960848 + }, + "parent_header": { + "excess_mana": 1331617467, + "mana_used": 83202142, + "proving_cost_per_mana_numerator": 5960869, + "fee_asset_price_numerator": 10576638721 + }, + "header": { + "excess_mana": 1314819609, + "mana_used": 104175730, + "proving_cost_per_mana_numerator": 14836989, + "fee_asset_price_numerator": 10419130569 + }, + "oracle_input": { + "proving_cost_modifier": 8876120, + "fee_asset_price_modifier": -157508152 + }, + "outputs": { + "fee_asset_price_at_execution": 11115621710, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 65319057, + "proving_cost": 5415680767, + "congestion_cost": 20043186286, + "congestion_multiplier": 4656848555 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 726061928, + "proving_cost": 60198658708, + "congestion_cost": 222792476618, + "congestion_multiplier": 4656848555 + } + } + }, + { + "l1_block_number": 20975087, + "l1_fees": { + "blob_fee": 1, + "base_fee": 18161430857 + }, + "parent_header": { + "excess_mana": 1314819609, + "mana_used": 104175730, + "proving_cost_per_mana_numerator": 14836989, + "fee_asset_price_numerator": 10419130569 + }, + "header": { + "excess_mana": 1318995339, + "mana_used": 81358527, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 10344089503 + }, + "oracle_input": { + "proving_cost_modifier": -21425270, + "fee_asset_price_modifier": -75041066 + }, + "outputs": { + "fee_asset_price_at_execution": 11098127481, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 60159739, + "proving_cost": 5416161490, + "congestion_cost": 20150976855, + "congestion_multiplier": 4679655742 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 667660452, + "proving_cost": 60109250673, + "congestion_cost": 223638110003, + "congestion_multiplier": 4679655742 + } + } + }, + { + "l1_block_number": 20975090, + "l1_fees": { + "blob_fee": 1, + "base_fee": 19301653207 + }, + "parent_header": { + "excess_mana": 1318995339, + "mana_used": 81358527, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 10344089503 + }, + "header": { + "excess_mana": 1300353866, + "mana_used": 120465579, + "proving_cost_per_mana_numerator": 92323832, + "fee_asset_price_numerator": 9546868216 + }, + "oracle_input": { + "proving_cost_modifier": 92323832, + "fee_asset_price_modifier": -797221287 + }, + "outputs": { + "fee_asset_price_at_execution": 11089802451, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 63936726, + "proving_cost": 5415357955, + "congestion_cost": 19608724511, + "congestion_multiplier": 4578695006 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 709045660, + "proving_cost": 60055249922, + "congestion_cost": 217456881143, + "congestion_multiplier": 4578695006 + } + } + }, + { + "l1_block_number": 20975093, + "l1_fees": { + "blob_fee": 1, + "base_fee": 19362551866 + }, + "parent_header": { + "excess_mana": 1300353866, + "mana_used": 120465579, + "proving_cost_per_mana_numerator": 92323832, + "fee_asset_price_numerator": 9546868216 + }, + "header": { + "excess_mana": 1320819445, + "mana_used": 103670134, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 10053927891 + }, + "oracle_input": { + "proving_cost_modifier": -165526439, + "fee_asset_price_modifier": 507059675 + }, + "outputs": { + "fee_asset_price_at_execution": 11001743664, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 64138453, + "proving_cost": 5420359929, + "congestion_cost": 20235900005, + "congestion_multiplier": 4689653747 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 705634818, + "proving_cost": 59633410505, + "congestion_cost": 222630184665, + "congestion_multiplier": 4689653747 + } + } + }, + { + "l1_block_number": 20975096, + "l1_fees": { + "blob_fee": 1, + "base_fee": 17613864145 + }, + "parent_header": { + "excess_mana": 1320819445, + "mana_used": 103670134, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 10053927891 + }, + "header": { + "excess_mana": 1324489579, + "mana_used": 106564847, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 9640848007 + }, + "oracle_input": { + "proving_cost_modifier": -24024628, + "fee_asset_price_modifier": -413079884 + }, + "outputs": { + "fee_asset_price_at_execution": 11057670741, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 58345924, + "proving_cost": 5415357955, + "congestion_cost": 20306536505, + "congestion_multiplier": 4709834685 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 645170016, + "proving_cost": 59881245211, + "congestion_cost": 224542994562, + "congestion_multiplier": 4709834685 + } + } + }, + { + "l1_block_number": 20975099, + "l1_fees": { + "blob_fee": 1, + "base_fee": 18068788476 + }, + "parent_header": { + "excess_mana": 1324489579, + "mana_used": 106564847, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 9640848007 + }, + "header": { + "excess_mana": 1331054426, + "mana_used": 87336617, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 10276407143 + }, + "oracle_input": { + "proving_cost_modifier": -75005104, + "fee_asset_price_modifier": 635559136 + }, + "outputs": { + "fee_asset_price_at_execution": 11012087939, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 59852861, + "proving_cost": 5415357955, + "congestion_cost": 20510958830, + "congestion_multiplier": 4746149604 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 659104968, + "proving_cost": 59634398021, + "congestion_cost": 225868482349, + "congestion_multiplier": 4746149604 + } + } + }, + { + "l1_block_number": 20975102, + "l1_fees": { + "blob_fee": 1, + "base_fee": 16794255548 + }, + "parent_header": { + "excess_mana": 1331054426, + "mana_used": 87336617, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 10276407143 + }, + "header": { + "excess_mana": 1318391043, + "mana_used": 113102161, + "proving_cost_per_mana_numerator": 113584083, + "fee_asset_price_numerator": 10577915632 + }, + "oracle_input": { + "proving_cost_modifier": 113584083, + "fee_asset_price_modifier": 301508489 + }, + "outputs": { + "fee_asset_price_at_execution": 11082299151, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 55630971, + "proving_cost": 5415357955, + "congestion_cost": 20113260678, + "congestion_multiplier": 4676348271 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 616519062, + "proving_cost": 60014616867, + "congestion_cost": 222901171735, + "congestion_multiplier": 4676348271 + } + } + }, + { + "l1_block_number": 20975105, + "l1_fees": { + "blob_fee": 1, + "base_fee": 17225028163 + }, + "parent_header": { + "excess_mana": 1318391043, + "mana_used": 113102161, + "proving_cost_per_mana_numerator": 113584083, + "fee_asset_price_numerator": 10577915632 + }, + "header": { + "excess_mana": 1331493204, + "mana_used": 101779107, + "proving_cost_per_mana_numerator": 74612133, + "fee_asset_price_numerator": 10778362448 + }, + "oracle_input": { + "proving_cost_modifier": -38971950, + "fee_asset_price_modifier": 200446816 + }, + "outputs": { + "fee_asset_price_at_execution": 11115763647, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 57057905, + "proving_cost": 5421512434, + "congestion_cost": 20536896241, + "congestion_multiplier": 4748586761 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 634242186, + "proving_cost": 60264250825, + "congestion_cost": 228283284657, + "congestion_multiplier": 4748586761 + } + } + }, + { + "l1_block_number": 20975108, + "l1_fees": { + "blob_fee": 1, + "base_fee": 16802177302 + }, + "parent_header": { + "excess_mana": 1331493204, + "mana_used": 101779107, + "proving_cost_per_mana_numerator": 74612133, + "fee_asset_price_numerator": 10778362448 + }, + "header": { + "excess_mana": 1333272311, + "mana_used": 92008465, + "proving_cost_per_mana_numerator": 202382631, + "fee_asset_price_numerator": 11242911350 + }, + "oracle_input": { + "proving_cost_modifier": 127770498, + "fee_asset_price_modifier": 464548902 + }, + "outputs": { + "fee_asset_price_at_execution": 11138067188, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 55657212, + "proving_cost": 5419399976, + "congestion_cost": 20577901158, + "congestion_multiplier": 4758481501 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 619913766, + "proving_cost": 60361641051, + "congestion_cost": 229198045685, + "congestion_multiplier": 4758481501 + } + } + }, + { + "l1_block_number": 20975111, + "l1_fees": { + "blob_fee": 1, + "base_fee": 15985470904 + }, + "parent_header": { + "excess_mana": 1333272311, + "mana_used": 92008465, + "proving_cost_per_mana_numerator": 202382631, + "fee_asset_price_numerator": 11242911350 + }, + "header": { + "excess_mana": 1325280776, + "mana_used": 99264175, + "proving_cost_per_mana_numerator": 152318466, + "fee_asset_price_numerator": 11312887858 + }, + "oracle_input": { + "proving_cost_modifier": -50064165, + "fee_asset_price_modifier": 69976508 + }, + "outputs": { + "fee_asset_price_at_execution": 11189929326, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 52951872, + "proving_cost": 5426328796, + "congestion_cost": 20351125622, + "congestion_multiplier": 4714196599 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 592527705, + "proving_cost": 60720235726, + "congestion_cost": 227727657414, + "congestion_multiplier": 4714196599 + } + } + }, + { + "l1_block_number": 20975114, + "l1_fees": { + "blob_fee": 1, + "base_fee": 15707407969 + }, + "parent_header": { + "excess_mana": 1325280776, + "mana_used": 99264175, + "proving_cost_per_mana_numerator": 152318466, + "fee_asset_price_numerator": 11312887858 + }, + "header": { + "excess_mana": 1324544951, + "mana_used": 105837320, + "proving_cost_per_mana_numerator": 147122574, + "fee_asset_price_numerator": 11397366686 + }, + "oracle_input": { + "proving_cost_modifier": -5195892, + "fee_asset_price_modifier": 84478828 + }, + "outputs": { + "fee_asset_price_at_execution": 11197762388, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 52030788, + "proving_cost": 5423612830, + "congestion_cost": 20315403438, + "congestion_multiplier": 4710139822 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 582628400, + "proving_cost": 60732327754, + "congestion_cost": 227487060515, + "congestion_multiplier": 4710139822 + } + } + }, + { + "l1_block_number": 20975117, + "l1_fees": { + "blob_fee": 1, + "base_fee": 14997613813 + }, + "parent_header": { + "excess_mana": 1324544951, + "mana_used": 105837320, + "proving_cost_per_mana_numerator": 147122574, + "fee_asset_price_numerator": 11397366686 + }, + "header": { + "excess_mana": 1330382271, + "mana_used": 90145608, + "proving_cost_per_mana_numerator": 75063816, + "fee_asset_price_numerator": 11723591217 + }, + "oracle_input": { + "proving_cost_modifier": -72058758, + "fee_asset_price_modifier": 326224531 + }, + "outputs": { + "fee_asset_price_at_execution": 11207226123, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 49679595, + "proving_cost": 5423331032, + "congestion_cost": 20482296757, + "congestion_multiplier": 4742418598 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 556770454, + "proving_cost": 60780497215, + "congestion_cost": 229549731274, + "congestion_multiplier": 4742418598 + } + } + }, + { + "l1_block_number": 20975120, + "l1_fees": { + "blob_fee": 1, + "base_fee": 14135639349 + }, + "parent_header": { + "excess_mana": 1330382271, + "mana_used": 90145608, + "proving_cost_per_mana_numerator": 75063816, + "fee_asset_price_numerator": 11723591217 + }, + "header": { + "excess_mana": 1320527879, + "mana_used": 90915825, + "proving_cost_per_mana_numerator": 27208757, + "fee_asset_price_numerator": 10969222287 + }, + "oracle_input": { + "proving_cost_modifier": -47855059, + "fee_asset_price_modifier": -754368930 + }, + "outputs": { + "fee_asset_price_at_execution": 11243846544, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 46824305, + "proving_cost": 5419424455, + "congestion_cost": 20159821850, + "congestion_multiplier": 4688054228 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 526485299, + "proving_cost": 60935176928, + "congestion_cost": 226673943235, + "congestion_multiplier": 4688054228 + } + } + }, + { + "l1_block_number": 20975123, + "l1_fees": { + "blob_fee": 1, + "base_fee": 13793046280 + }, + "parent_header": { + "excess_mana": 1320527879, + "mana_used": 90915825, + "proving_cost_per_mana_numerator": 27208757, + "fee_asset_price_numerator": 10969222287 + }, + "header": { + "excess_mana": 1311443704, + "mana_used": 101140231, + "proving_cost_per_mana_numerator": 179746030, + "fee_asset_price_numerator": 10987035599 + }, + "oracle_input": { + "proving_cost_modifier": 152537273, + "fee_asset_price_modifier": 17813312 + }, + "outputs": { + "fee_asset_price_at_execution": 11159345584, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 45689465, + "proving_cost": 5416831607, + "congestion_cost": 19875334697, + "congestion_multiplier": 4638491172 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 509864529, + "proving_cost": 60448295872, + "congestion_cost": 221795728481, + "congestion_multiplier": 4638491172 + } + } + }, + { + "l1_block_number": 20975126, + "l1_fees": { + "blob_fee": 1, + "base_fee": 13713634735 + }, + "parent_header": { + "excess_mana": 1311443704, + "mana_used": 101140231, + "proving_cost_per_mana_numerator": 179746030, + "fee_asset_price_numerator": 10987035599 + }, + "header": { + "excess_mana": 1312583935, + "mana_used": 95308047, + "proving_cost_per_mana_numerator": 186248322, + "fee_asset_price_numerator": 10453873707 + }, + "oracle_input": { + "proving_cost_modifier": 6502292, + "fee_asset_price_modifier": -533161892 + }, + "outputs": { + "fee_asset_price_at_execution": 11161333610, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 45426415, + "proving_cost": 5425100599, + "congestion_cost": 19938338854, + "congestion_multiplier": 4644683374 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 507019372, + "proving_cost": 60551357653, + "congestion_cost": 222538451578, + "congestion_multiplier": 4644683374 + } + } + }, + { + "l1_block_number": 20975129, + "l1_fees": { + "blob_fee": 1, + "base_fee": 13219632519 + }, + "parent_header": { + "excess_mana": 1312583935, + "mana_used": 95308047, + "proving_cost_per_mana_numerator": 186248322, + "fee_asset_price_numerator": 10453873707 + }, + "header": { + "excess_mana": 1307891982, + "mana_used": 93623516, + "proving_cost_per_mana_numerator": 135139372, + "fee_asset_price_numerator": 10080607623 + }, + "oracle_input": { + "proving_cost_modifier": -51108950, + "fee_asset_price_modifier": -373266084 + }, + "outputs": { + "fee_asset_price_at_execution": 11101983988, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 43790032, + "proving_cost": 5425453366, + "congestion_cost": 19794591146, + "congestion_multiplier": 4619255847 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 486156234, + "proving_cost": 60233296396, + "congestion_cost": 219759233951, + "congestion_multiplier": 4619255847 + } + } + }, + { + "l1_block_number": 20975132, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12935777298 + }, + "parent_header": { + "excess_mana": 1307891982, + "mana_used": 93623516, + "proving_cost_per_mana_numerator": 135139372, + "fee_asset_price_numerator": 10080607623 + }, + "header": { + "excess_mana": 1301515498, + "mana_used": 110330450, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 10211821717 + }, + "oracle_input": { + "proving_cost_modifier": -240364208, + "fee_asset_price_modifier": 131214094 + }, + "outputs": { + "fee_asset_price_at_execution": 11060621292, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 42849762, + "proving_cost": 5422681182, + "congestion_cost": 19593503128, + "congestion_multiplier": 4584922184 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 473944989, + "proving_cost": 59978222941, + "congestion_cost": 216716317882, + "congestion_multiplier": 4584922184 + } + } + }, + { + "l1_block_number": 20975135, + "l1_fees": { + "blob_fee": 1, + "base_fee": 13008513572 + }, + "parent_header": { + "excess_mana": 1301515498, + "mana_used": 110330450, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 10211821717 + }, + "header": { + "excess_mana": 1311845948, + "mana_used": 90935667, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 10435521602 + }, + "oracle_input": { + "proving_cost_modifier": -124659637, + "fee_asset_price_modifier": 223699885 + }, + "outputs": { + "fee_asset_price_at_execution": 11075143912, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 43090701, + "proving_cost": 5415357955, + "congestion_cost": 19872435803, + "congestion_multiplier": 4640674678 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 477235714, + "proving_cost": 59975868686, + "congestion_cost": 220090086400, + "congestion_multiplier": 4640674678 + } + } + }, + { + "l1_block_number": 20975138, + "l1_fees": { + "blob_fee": 1, + "base_fee": 13141320281 + }, + "parent_header": { + "excess_mana": 1311845948, + "mana_used": 90935667, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 10435521602 + }, + "header": { + "excess_mana": 1302781615, + "mana_used": 119918223, + "proving_cost_per_mana_numerator": 157775447, + "fee_asset_price_numerator": 10260006113 + }, + "oracle_input": { + "proving_cost_modifier": 157775447, + "fee_asset_price_modifier": -175515489 + }, + "outputs": { + "fee_asset_price_at_execution": 11099946727, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 43530623, + "proving_cost": 5415357955, + "congestion_cost": 19606794501, + "congestion_multiplier": 4591719124 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 483187596, + "proving_cost": 60110184808, + "congestion_cost": 217634374448, + "congestion_multiplier": 4591719124 + } + } + }, + { + "l1_block_number": 20975141, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12955542361 + }, + "parent_header": { + "excess_mana": 1302781615, + "mana_used": 119918223, + "proving_cost_per_mana_numerator": 157775447, + "fee_asset_price_numerator": 10260006113 + }, + "header": { + "excess_mana": 1322699838, + "mana_used": 90906414, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 10929680429 + }, + "oracle_input": { + "proving_cost_modifier": -166691750, + "fee_asset_price_modifier": 669674316 + }, + "outputs": { + "fee_asset_price_at_execution": 11080481689, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 42915234, + "proving_cost": 5423908804, + "congestion_cost": 20227153949, + "congestion_multiplier": 4699982624 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 475521464, + "proving_cost": 60099522185, + "congestion_cost": 224126608952, + "congestion_multiplier": 4699982624 + } + } + }, + { + "l1_block_number": 20975144, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12711944992 + }, + "parent_header": { + "excess_mana": 1322699838, + "mana_used": 90906414, + "proving_cost_per_mana_numerator": 0, + "fee_asset_price_numerator": 10929680429 + }, + "header": { + "excess_mana": 1313606252, + "mana_used": 109329982, + "proving_cost_per_mana_numerator": 27373813, + "fee_asset_price_numerator": 11439057352 + }, + "oracle_input": { + "proving_cost_modifier": 27373813, + "fee_asset_price_modifier": 509376923 + }, + "outputs": { + "fee_asset_price_at_execution": 11154933844, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 42108317, + "proving_cost": 5415357955, + "congestion_cost": 19921073991, + "congestion_multiplier": 4650242255 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 469715490, + "proving_cost": 60407959729, + "congestion_cost": 222218262471, + "congestion_multiplier": 4650242255 + } + } + }, + { + "l1_block_number": 20975147, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12647455153 + }, + "parent_header": { + "excess_mana": 1313606252, + "mana_used": 109329982, + "proving_cost_per_mana_numerator": 27373813, + "fee_asset_price_numerator": 11439057352 + }, + "header": { + "excess_mana": 1322936234, + "mana_used": 112778076, + "proving_cost_per_mana_numerator": 49560232, + "fee_asset_price_numerator": 11250716091 + }, + "oracle_input": { + "proving_cost_modifier": 22186419, + "fee_asset_price_modifier": -188341261 + }, + "outputs": { + "fee_asset_price_at_execution": 11211899464, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 41894695, + "proving_cost": 5416840547, + "congestion_cost": 20204322533, + "congestion_multiplier": 4701282740 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 469719108, + "proving_cost": 60733071625, + "congestion_cost": 226528832978, + "congestion_multiplier": 4701282740 + } + } + }, + { + "l1_block_number": 20975150, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12756925909 + }, + "parent_header": { + "excess_mana": 1322936234, + "mana_used": 112778076, + "proving_cost_per_mana_numerator": 49560232, + "fee_asset_price_numerator": 11250716091 + }, + "header": { + "excess_mana": 1335714310, + "mana_used": 85860560, + "proving_cost_per_mana_numerator": 72408886, + "fee_asset_price_numerator": 11664879860 + }, + "oracle_input": { + "proving_cost_modifier": 22848654, + "fee_asset_price_modifier": 414163769 + }, + "outputs": { + "fee_asset_price_at_execution": 11190802705, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 42257317, + "proving_cost": 5418042484, + "congestion_cost": 20596778232, + "congestion_multiplier": 4772096585 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 472893297, + "proving_cost": 60632244485, + "congestion_cost": 230494481552, + "congestion_multiplier": 4772096585 + } + } + }, + { + "l1_block_number": 20975153, + "l1_fees": { + "blob_fee": 1, + "base_fee": 11185568066 + }, + "parent_header": { + "excess_mana": 1335714310, + "mana_used": 85860560, + "proving_cost_per_mana_numerator": 72408886, + "fee_asset_price_numerator": 11664879860 + }, + "header": { + "excess_mana": 1321574870, + "mana_used": 96504708, + "proving_cost_per_mana_numerator": 97425002, + "fee_asset_price_numerator": 12050972543 + }, + "oracle_input": { + "proving_cost_modifier": 25016116, + "fee_asset_price_modifier": 386092683 + }, + "outputs": { + "fee_asset_price_at_execution": 11237247066, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 37052194, + "proving_cost": 5419280575, + "congestion_cost": 20154604803, + "congestion_multiplier": 4693800517 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 416364658, + "proving_cost": 60897794741, + "congestion_cost": 226482273688, + "congestion_multiplier": 4693800517 + } + } + }, + { + "l1_block_number": 20975156, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12473704501 + }, + "parent_header": { + "excess_mana": 1321574870, + "mana_used": 96504708, + "proving_cost_per_mana_numerator": 97425002, + "fee_asset_price_numerator": 12050972543 + }, + "header": { + "excess_mana": 1318079578, + "mana_used": 92818286, + "proving_cost_per_mana_numerator": 97491349, + "fee_asset_price_numerator": 11679832926 + }, + "oracle_input": { + "proving_cost_modifier": 66347, + "fee_asset_price_modifier": -371139617 + }, + "outputs": { + "fee_asset_price_at_execution": 11280717118, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 41319146, + "proving_cost": 5420636438, + "congestion_cost": 20070744800, + "congestion_multiplier": 4674644455 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 466109597, + "proving_cost": 61148666256, + "congestion_cost": 226412394436, + "congestion_multiplier": 4674644455 + } + } + }, + { + "l1_block_number": 20975159, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12501243261 + }, + "parent_header": { + "excess_mana": 1318079578, + "mana_used": 92818286, + "proving_cost_per_mana_numerator": 97491349, + "fee_asset_price_numerator": 11679832926 + }, + "header": { + "excess_mana": 1310897864, + "mana_used": 109584810, + "proving_cost_per_mana_numerator": 263701092, + "fee_asset_price_numerator": 11377695280 + }, + "oracle_input": { + "proving_cost_modifier": 166209743, + "fee_asset_price_modifier": -302137646 + }, + "outputs": { + "fee_asset_price_at_execution": 11238927505, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 41410368, + "proving_cost": 5420640034, + "congestion_cost": 19857447142, + "congestion_multiplier": 4635529825 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 465408123, + "proving_cost": 60922180372, + "congestion_cost": 223176408863, + "congestion_multiplier": 4635529825 + } + } + }, + { + "l1_block_number": 20975162, + "l1_fees": { + "blob_fee": 1, + "base_fee": 12443066368 + }, + "parent_header": { + "excess_mana": 1310897864, + "mana_used": 109584810, + "proving_cost_per_mana_numerator": 263701092, + "fee_asset_price_numerator": 11377695280 + }, + "header": { + "excess_mana": 1320482674, + "mana_used": 99018256, + "proving_cost_per_mana_numerator": 466096273, + "fee_asset_price_numerator": 11454742859 + }, + "oracle_input": { + "proving_cost_modifier": 202395181, + "fee_asset_price_modifier": 77047579 + }, + "outputs": { + "fee_asset_price_at_execution": 11205021721, + "mana_base_fee_components_in_wei": { + "data_cost": 0, + "gas_cost": 41217657, + "proving_cost": 5429657158, + "congestion_cost": 20175526521, + "congestion_multiplier": 4687806284 + }, + "mana_base_fee_components_in_fee_asset": { + "data_cost": 0, + "gas_cost": 461844741, + "proving_cost": 60839426392, + "congestion_cost": 226067212900, + "congestion_multiplier": 4687806284 + } + } + } +] \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_1.json b/l1-contracts/test/fixtures/mixed_block_1.json index 6306d467706..e3a5c4cceb9 100644 --- a/l1-contracts/test/fixtures/mixed_block_1.json +++ b/l1-contracts/test/fixtures/mixed_block_1.json @@ -58,25 +58,25 @@ ] }, "block": { - "archive": "0x0f5694321be22526e5a7e857ed9fc4afc006c5bc9052bea6449ec3adee9a2ba9", - "blockHash": "0x2627d91f0126444fb419a457900030879b28203c085aa6eb86415e2c57e84d06", - "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000004100100000000000000000000000000000000000000000000000000000000000410020000000000000000000000000000000000000000000000000000000000041003000000000000000000000000000000000000000000000000000000000004100400000000000000000000000000000000000000000000000000000000000410050000000000000000000000000000000000000000000000000000000000041006000000000000000000000000000000000000000000000000000000000004100700000000000000000000000000000000000000000000000000000000000410080000000000000000000000000000000000000000000000000000000000041009000000000000000000000000000000000000000000000000000000000004100a000000000000000000000000000000000000000000000000000000000004100b000000000000000000000000000000000000000000000000000000000004100c000000000000000000000000000000000000000000000000000000000004100d000000000000000000000000000000000000000000000000000000000004100e000000000000000000000000000000000000000000000000000000000004100f0000000000000000000000000000000000000000000000000000000000041010000000000000000000000000000000000000000000000000000000000004101100000000000000000000000000000000000000000000000000000000000410120000000000000000000000000000000000000000000000000000000000041013000000000000000000000000000000000000000000000000000000000004101400000000000000000000000000000000000000000000000000000000000410150000000000000000000000000000000000000000000000000000000000041016000000000000000000000000000000000000000000000000000000000004101700000000000000000000000000000000000000000000000000000000000410180000000000000000000000000000000000000000000000000000000000041019000000000000000000000000000000000000000000000000000000000004101a000000000000000000000000000000000000000000000000000000000004101b000000000000000000000000000000000000000000000000000000000004101c000000000000000000000000000000000000000000000000000000000004101d000000000000000000000000000000000000000000000000000000000004101e000000000000000000000000000000000000000000000000000000000004101f0000000000000000000000000000000000000000000000000000000000041020000000000000000000000000000000000000000000000000000000000004102100000000000000000000000000000000000000000000000000000000000410220000000000000000000000000000000000000000000000000000000000041023000000000000000000000000000000000000000000000000000000000004102400000000000000000000000000000000000000000000000000000000000410250000000000000000000000000000000000000000000000000000000000041026000000000000000000000000000000000000000000000000000000000004102700000000000000000000000000000000000000000000000000000000000410280000000000000000000000000000000000000000000000000000000000041029000000000000000000000000000000000000000000000000000000000004102a000000000000000000000000000000000000000000000000000000000004102b000000000000000000000000000000000000000000000000000000000004102c000000000000000000000000000000000000000000000000000000000004102d000000000000000000000000000000000000000000000000000000000004102e000000000000000000000000000000000000000000000000000000000004102f0000000000000000000000000000000000000000000000000000000000041030000000000000000000000000000000000000000000000000000000000004103100000000000000000000000000000000000000000000000000000000000410320000000000000000000000000000000000000000000000000000000000041033000000000000000000000000000000000000000000000000000000000004103400000000000000000000000000000000000000000000000000000000000410350000000000000000000000000000000000000000000000000000000000041036000000000000000000000000000000000000000000000000000000000004103700000000000000000000000000000000000000000000000000000000000410380000000000000000000000000000000000000000000000000000000000041039000000000000000000000000000000000000000000000000000000000004103a000000000000000000000000000000000000000000000000000000000004103b000000000000000000000000000000000000000000000000000000000004103c000000000000000000000000000000000000000000000000000000000004103d000000000000000000000000000000000000000000000000000000000004103e000000000000000000000000000000000000000000000000000000000004103f3f0000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004110100000000000000000000000000000000000000000000000000000000000411020000000000000000000000000000000000000000000000000000000000041103000000000000000000000000000000000000000000000000000000000004110400000000000000000000000000000000000000000000000000000000000411050000000000000000000000000000000000000000000000000000000000041106000000000000000000000000000000000000000000000000000000000004110700000000000000000000000000000000000000000000000000000000000411080000000000000000000000000000000000000000000000000000000000041109000000000000000000000000000000000000000000000000000000000004110a000000000000000000000000000000000000000000000000000000000004110b000000000000000000000000000000000000000000000000000000000004110c000000000000000000000000000000000000000000000000000000000004110d000000000000000000000000000000000000000000000000000000000004110e000000000000000000000000000000000000000000000000000000000004110f0000000000000000000000000000000000000000000000000000000000041110000000000000000000000000000000000000000000000000000000000004111100000000000000000000000000000000000000000000000000000000000411120000000000000000000000000000000000000000000000000000000000041113000000000000000000000000000000000000000000000000000000000004111400000000000000000000000000000000000000000000000000000000000411150000000000000000000000000000000000000000000000000000000000041116000000000000000000000000000000000000000000000000000000000004111700000000000000000000000000000000000000000000000000000000000411180000000000000000000000000000000000000000000000000000000000041119000000000000000000000000000000000000000000000000000000000004111a000000000000000000000000000000000000000000000000000000000004111b000000000000000000000000000000000000000000000000000000000004111c000000000000000000000000000000000000000000000000000000000004111d000000000000000000000000000000000000000000000000000000000004111e000000000000000000000000000000000000000000000000000000000004111f0000000000000000000000000000000000000000000000000000000000041120000000000000000000000000000000000000000000000000000000000004112100000000000000000000000000000000000000000000000000000000000411220000000000000000000000000000000000000000000000000000000000041123000000000000000000000000000000000000000000000000000000000004112400000000000000000000000000000000000000000000000000000000000411250000000000000000000000000000000000000000000000000000000000041126000000000000000000000000000000000000000000000000000000000004112700000000000000000000000000000000000000000000000000000000000411280000000000000000000000000000000000000000000000000000000000041129000000000000000000000000000000000000000000000000000000000004112a000000000000000000000000000000000000000000000000000000000004112b000000000000000000000000000000000000000000000000000000000004112c000000000000000000000000000000000000000000000000000000000004112d000000000000000000000000000000000000000000000000000000000004112e000000000000000000000000000000000000000000000000000000000004112f0000000000000000000000000000000000000000000000000000000000041130000000000000000000000000000000000000000000000000000000000004113100000000000000000000000000000000000000000000000000000000000411320000000000000000000000000000000000000000000000000000000000041133000000000000000000000000000000000000000000000000000000000004113400000000000000000000000000000000000000000000000000000000000411350000000000000000000000000000000000000000000000000000000000041136000000000000000000000000000000000000000000000000000000000004113700000000000000000000000000000000000000000000000000000000000411380000000000000000000000000000000000000000000000000000000000041139000000000000000000000000000000000000000000000000000000000004113a000000000000000000000000000000000000000000000000000000000004113b000000000000000000000000000000000000000000000000000000000004113c000000000000000000000000000000000000000000000000000000000004113d000000000000000000000000000000000000000000000000000000000004113e080097a6ec570e9b8e257647c9c74c5ad3edc57ca5ef6ae44d80b3c30d1d99b9b300ce48ec41d1edde0066fab553a456ae2f380d14fa8f956af1fb0217513a598900619ff12eaf97f63aa2a2311de3b6571a7b880a5247cb33b6a74787bf3f9bd5007854a2fad4e1801c6404394bf3d37ab08c135ea38a1974242e39a21273685f000f55796e72957a819e68a22e8602d73c3ba3718a5a4bd92b80b0aa444b182a00788b6e9874fb040ee679a7fae257190099a605229b948334e54a57739535d4004f1658ee3c1a91627e5d72f5a731f0796299df82ab41e72c88eee0c82fa85e003ee802add96628c693ed71afa9908138ba5a6fbf0a5f29a9c74e4e42aba6713f0000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000004200a0000000000000000000000000000000000000000000000000000000000042001000000000000000000000000000000000000000000000000000000000004200b0000000000000000000000000000000000000000000000000000000000042002000000000000000000000000000000000000000000000000000000000004200c0000000000000000000000000000000000000000000000000000000000042003000000000000000000000000000000000000000000000000000000000004200d0000000000000000000000000000000000000000000000000000000000042004000000000000000000000000000000000000000000000000000000000004200e0000000000000000000000000000000000000000000000000000000000042005000000000000000000000000000000000000000000000000000000000004200f00000000000000000000000000000000000000000000000000000000000420060000000000000000000000000000000000000000000000000000000000042010000000000000000000000000000000000000000000000000000000000004200700000000000000000000000000000000000000000000000000000000000420110000000000000000000000000000000000000000000000000000000000042008000000000000000000000000000000000000000000000000000000000004201200000000000000000000000000000000000000000000000000000000000420090000000000000000000000000000000000000000000000000000000000042013000000000000000000000000000000000000000000000000000000000004200a0000000000000000000000000000000000000000000000000000000000042014000000000000000000000000000000000000000000000000000000000004200b0000000000000000000000000000000000000000000000000000000000042015000000000000000000000000000000000000000000000000000000000004200c0000000000000000000000000000000000000000000000000000000000042016000000000000000000000000000000000000000000000000000000000004200d0000000000000000000000000000000000000000000000000000000000042017000000000000000000000000000000000000000000000000000000000004200e0000000000000000000000000000000000000000000000000000000000042018000000000000000000000000000000000000000000000000000000000004200f00000000000000000000000000000000000000000000000000000000000420190000000000000000000000000000000000000000000000000000000000042010000000000000000000000000000000000000000000000000000000000004201a0000000000000000000000000000000000000000000000000000000000042011000000000000000000000000000000000000000000000000000000000004201b0000000000000000000000000000000000000000000000000000000000042012000000000000000000000000000000000000000000000000000000000004201c0000000000000000000000000000000000000000000000000000000000042013000000000000000000000000000000000000000000000000000000000004201d0000000000000000000000000000000000000000000000000000000000042014000000000000000000000000000000000000000000000000000000000004201e0000000000000000000000000000000000000000000000000000000000042015000000000000000000000000000000000000000000000000000000000004201f00000000000000000000000000000000000000000000000000000000000420160000000000000000000000000000000000000000000000000000000000042020000000000000000000000000000000000000000000000000000000000004201700000000000000000000000000000000000000000000000000000000000420210000000000000000000000000000000000000000000000000000000000042018000000000000000000000000000000000000000000000000000000000004202200000000000000000000000000000000000000000000000000000000000420190000000000000000000000000000000000000000000000000000000000042023000000000000000000000000000000000000000000000000000000000004201a0000000000000000000000000000000000000000000000000000000000042024000000000000000000000000000000000000000000000000000000000004201b0000000000000000000000000000000000000000000000000000000000042025000000000000000000000000000000000000000000000000000000000004201c0000000000000000000000000000000000000000000000000000000000042026000000000000000000000000000000000000000000000000000000000004201d0000000000000000000000000000000000000000000000000000000000042027000000000000000000000000000000000000000000000000000000000004201e0000000000000000000000000000000000000000000000000000000000042028000000000000000000000000000000000000000000000000000000000004201f00000000000000000000000000000000000000000000000000000000000420290000000000000000000000000000000000000000000000000000000000042020000000000000000000000000000000000000000000000000000000000004202a0000000000000000000000000000000000000000000000000000000000042021000000000000000000000000000000000000000000000000000000000004202b0000000000000000000000000000000000000000000000000000000000042022000000000000000000000000000000000000000000000000000000000004202c0000000000000000000000000000000000000000000000000000000000042023000000000000000000000000000000000000000000000000000000000004202d0000000000000000000000000000000000000000000000000000000000042024000000000000000000000000000000000000000000000000000000000004202e0000000000000000000000000000000000000000000000000000000000042025000000000000000000000000000000000000000000000000000000000004202f00000000000000000000000000000000000000000000000000000000000420260000000000000000000000000000000000000000000000000000000000042030000000000000000000000000000000000000000000000000000000000004202700000000000000000000000000000000000000000000000000000000000420310000000000000000000000000000000000000000000000000000000000042028000000000000000000000000000000000000000000000000000000000004203200000000000000000000000000000000000000000000000000000000000420290000000000000000000000000000000000000000000000000000000000042033000000000000000000000000000000000000000000000000000000000004202a0000000000000000000000000000000000000000000000000000000000042034000000000000000000000000000000000000000000000000000000000004202b0000000000000000000000000000000000000000000000000000000000042035000000000000000000000000000000000000000000000000000000000004202c0000000000000000000000000000000000000000000000000000000000042036000000000000000000000000000000000000000000000000000000000004202d0000000000000000000000000000000000000000000000000000000000042037000000000000000000000000000000000000000000000000000000000004202e0000000000000000000000000000000000000000000000000000000000042038000000000000000000000000000000000000000000000000000000000004202f00000000000000000000000000000000000000000000000000000000000420390000000000000000000000000000000000000000000000000000000000042030000000000000000000000000000000000000000000000000000000000004203a0000000000000000000000000000000000000000000000000000000000042031000000000000000000000000000000000000000000000000000000000004203b0000000000000000000000000000000000000000000000000000000000042032000000000000000000000000000000000000000000000000000000000004203c0000000000000000000000000000000000000000000000000000000000042033000000000000000000000000000000000000000000000000000000000004203d0000000000000000000000000000000000000000000000000000000000042034000000000000000000000000000000000000000000000000000000000004203e0000000000000000000000000000000000000000000000000000000000042035000000000000000000000000000000000000000000000000000000000004203f00000000000000000000000000000000000000000000000000000000000420360000000000000000000000000000000000000000000000000000000000042040000000000000000000000000000000000000000000000000000000000004203700000000000000000000000000000000000000000000000000000000000420410000000000000000000000000000000000000000000000000000000000042038000000000000000000000000000000000000000000000000000000000004204200000000000000000000000000000000000000000000000000000000000420390000000000000000000000000000000000000000000000000000000000042043000000000000000000000000000000000000000000000000000000000004203a0000000000000000000000000000000000000000000000000000000000042044000000000000000000000000000000000000000000000000000000000004203b0000000000000000000000000000000000000000000000000000000000042045000000000000000000000000000000000000000000000000000000000004203c0000000000000000000000000000000000000000000000000000000000042046000000000000000000000000000000000000000000000000000000000004203d0000000000000000000000000000000000000000000000000000000000042047000000000000000000000000000000000000000000000000000000000004203e0000000000000000000000000000000000000000000000000000000000042048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008100100000000000000000000000000000000000000000000000000000000000810020000000000000000000000000000000000000000000000000000000000081003000000000000000000000000000000000000000000000000000000000008100400000000000000000000000000000000000000000000000000000000000810050000000000000000000000000000000000000000000000000000000000081006000000000000000000000000000000000000000000000000000000000008100700000000000000000000000000000000000000000000000000000000000810080000000000000000000000000000000000000000000000000000000000081009000000000000000000000000000000000000000000000000000000000008100a000000000000000000000000000000000000000000000000000000000008100b000000000000000000000000000000000000000000000000000000000008100c000000000000000000000000000000000000000000000000000000000008100d000000000000000000000000000000000000000000000000000000000008100e000000000000000000000000000000000000000000000000000000000008100f0000000000000000000000000000000000000000000000000000000000081010000000000000000000000000000000000000000000000000000000000008101100000000000000000000000000000000000000000000000000000000000810120000000000000000000000000000000000000000000000000000000000081013000000000000000000000000000000000000000000000000000000000008101400000000000000000000000000000000000000000000000000000000000810150000000000000000000000000000000000000000000000000000000000081016000000000000000000000000000000000000000000000000000000000008101700000000000000000000000000000000000000000000000000000000000810180000000000000000000000000000000000000000000000000000000000081019000000000000000000000000000000000000000000000000000000000008101a000000000000000000000000000000000000000000000000000000000008101b000000000000000000000000000000000000000000000000000000000008101c000000000000000000000000000000000000000000000000000000000008101d000000000000000000000000000000000000000000000000000000000008101e000000000000000000000000000000000000000000000000000000000008101f0000000000000000000000000000000000000000000000000000000000081020000000000000000000000000000000000000000000000000000000000008102100000000000000000000000000000000000000000000000000000000000810220000000000000000000000000000000000000000000000000000000000081023000000000000000000000000000000000000000000000000000000000008102400000000000000000000000000000000000000000000000000000000000810250000000000000000000000000000000000000000000000000000000000081026000000000000000000000000000000000000000000000000000000000008102700000000000000000000000000000000000000000000000000000000000810280000000000000000000000000000000000000000000000000000000000081029000000000000000000000000000000000000000000000000000000000008102a000000000000000000000000000000000000000000000000000000000008102b000000000000000000000000000000000000000000000000000000000008102c000000000000000000000000000000000000000000000000000000000008102d000000000000000000000000000000000000000000000000000000000008102e000000000000000000000000000000000000000000000000000000000008102f0000000000000000000000000000000000000000000000000000000000081030000000000000000000000000000000000000000000000000000000000008103100000000000000000000000000000000000000000000000000000000000810320000000000000000000000000000000000000000000000000000000000081033000000000000000000000000000000000000000000000000000000000008103400000000000000000000000000000000000000000000000000000000000810350000000000000000000000000000000000000000000000000000000000081036000000000000000000000000000000000000000000000000000000000008103700000000000000000000000000000000000000000000000000000000000810380000000000000000000000000000000000000000000000000000000000081039000000000000000000000000000000000000000000000000000000000008103a000000000000000000000000000000000000000000000000000000000008103b000000000000000000000000000000000000000000000000000000000008103c000000000000000000000000000000000000000000000000000000000008103d000000000000000000000000000000000000000000000000000000000008103e000000000000000000000000000000000000000000000000000000000008103f3f0000000000000000000000000000000000000000000000000000000000081100000000000000000000000000000000000000000000000000000000000008110100000000000000000000000000000000000000000000000000000000000811020000000000000000000000000000000000000000000000000000000000081103000000000000000000000000000000000000000000000000000000000008110400000000000000000000000000000000000000000000000000000000000811050000000000000000000000000000000000000000000000000000000000081106000000000000000000000000000000000000000000000000000000000008110700000000000000000000000000000000000000000000000000000000000811080000000000000000000000000000000000000000000000000000000000081109000000000000000000000000000000000000000000000000000000000008110a000000000000000000000000000000000000000000000000000000000008110b000000000000000000000000000000000000000000000000000000000008110c000000000000000000000000000000000000000000000000000000000008110d000000000000000000000000000000000000000000000000000000000008110e000000000000000000000000000000000000000000000000000000000008110f0000000000000000000000000000000000000000000000000000000000081110000000000000000000000000000000000000000000000000000000000008111100000000000000000000000000000000000000000000000000000000000811120000000000000000000000000000000000000000000000000000000000081113000000000000000000000000000000000000000000000000000000000008111400000000000000000000000000000000000000000000000000000000000811150000000000000000000000000000000000000000000000000000000000081116000000000000000000000000000000000000000000000000000000000008111700000000000000000000000000000000000000000000000000000000000811180000000000000000000000000000000000000000000000000000000000081119000000000000000000000000000000000000000000000000000000000008111a000000000000000000000000000000000000000000000000000000000008111b000000000000000000000000000000000000000000000000000000000008111c000000000000000000000000000000000000000000000000000000000008111d000000000000000000000000000000000000000000000000000000000008111e000000000000000000000000000000000000000000000000000000000008111f0000000000000000000000000000000000000000000000000000000000081120000000000000000000000000000000000000000000000000000000000008112100000000000000000000000000000000000000000000000000000000000811220000000000000000000000000000000000000000000000000000000000081123000000000000000000000000000000000000000000000000000000000008112400000000000000000000000000000000000000000000000000000000000811250000000000000000000000000000000000000000000000000000000000081126000000000000000000000000000000000000000000000000000000000008112700000000000000000000000000000000000000000000000000000000000811280000000000000000000000000000000000000000000000000000000000081129000000000000000000000000000000000000000000000000000000000008112a000000000000000000000000000000000000000000000000000000000008112b000000000000000000000000000000000000000000000000000000000008112c000000000000000000000000000000000000000000000000000000000008112d000000000000000000000000000000000000000000000000000000000008112e000000000000000000000000000000000000000000000000000000000008112f0000000000000000000000000000000000000000000000000000000000081130000000000000000000000000000000000000000000000000000000000008113100000000000000000000000000000000000000000000000000000000000811320000000000000000000000000000000000000000000000000000000000081133000000000000000000000000000000000000000000000000000000000008113400000000000000000000000000000000000000000000000000000000000811350000000000000000000000000000000000000000000000000000000000081136000000000000000000000000000000000000000000000000000000000008113700000000000000000000000000000000000000000000000000000000000811380000000000000000000000000000000000000000000000000000000000081139000000000000000000000000000000000000000000000000000000000008113a000000000000000000000000000000000000000000000000000000000008113b000000000000000000000000000000000000000000000000000000000008113c000000000000000000000000000000000000000000000000000000000008113d000000000000000000000000000000000000000000000000000000000008113e08003c0472260790b0bdfb8ae4dc4d437e7686b73643f2198970d84e1059a5f13500bfd46275a318e438726ff2765ae154b63ab8a0daebcbed668a5f58a0e63dc1007906b9418dc758c6b4f8454c69baa48b7889b6b511d707abe8e2cb8f7c397300aeb60c4d65a44f122e58bf9565dfe2024b3ae654d5cf2e47ecb035d53c927000bf82e8cda20345f37bbb1de3932172324b57f0b98be483392697b168e3bba8000fb4bbad884ef30edf68e45a6cf2733fcf50310c69d7c1432b29af2c0aa8040023e1622d27fee3b4a40ab975ae0eb2e31619ef3dc76eb858f7fddb6a056131004689cd7007daf98dd3218b839b8e6a29f957154347b391fdb376bd0b344be23f0000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000008200a0000000000000000000000000000000000000000000000000000000000082001000000000000000000000000000000000000000000000000000000000008200b0000000000000000000000000000000000000000000000000000000000082002000000000000000000000000000000000000000000000000000000000008200c0000000000000000000000000000000000000000000000000000000000082003000000000000000000000000000000000000000000000000000000000008200d0000000000000000000000000000000000000000000000000000000000082004000000000000000000000000000000000000000000000000000000000008200e0000000000000000000000000000000000000000000000000000000000082005000000000000000000000000000000000000000000000000000000000008200f00000000000000000000000000000000000000000000000000000000000820060000000000000000000000000000000000000000000000000000000000082010000000000000000000000000000000000000000000000000000000000008200700000000000000000000000000000000000000000000000000000000000820110000000000000000000000000000000000000000000000000000000000082008000000000000000000000000000000000000000000000000000000000008201200000000000000000000000000000000000000000000000000000000000820090000000000000000000000000000000000000000000000000000000000082013000000000000000000000000000000000000000000000000000000000008200a0000000000000000000000000000000000000000000000000000000000082014000000000000000000000000000000000000000000000000000000000008200b0000000000000000000000000000000000000000000000000000000000082015000000000000000000000000000000000000000000000000000000000008200c0000000000000000000000000000000000000000000000000000000000082016000000000000000000000000000000000000000000000000000000000008200d0000000000000000000000000000000000000000000000000000000000082017000000000000000000000000000000000000000000000000000000000008200e0000000000000000000000000000000000000000000000000000000000082018000000000000000000000000000000000000000000000000000000000008200f00000000000000000000000000000000000000000000000000000000000820190000000000000000000000000000000000000000000000000000000000082010000000000000000000000000000000000000000000000000000000000008201a0000000000000000000000000000000000000000000000000000000000082011000000000000000000000000000000000000000000000000000000000008201b0000000000000000000000000000000000000000000000000000000000082012000000000000000000000000000000000000000000000000000000000008201c0000000000000000000000000000000000000000000000000000000000082013000000000000000000000000000000000000000000000000000000000008201d0000000000000000000000000000000000000000000000000000000000082014000000000000000000000000000000000000000000000000000000000008201e0000000000000000000000000000000000000000000000000000000000082015000000000000000000000000000000000000000000000000000000000008201f00000000000000000000000000000000000000000000000000000000000820160000000000000000000000000000000000000000000000000000000000082020000000000000000000000000000000000000000000000000000000000008201700000000000000000000000000000000000000000000000000000000000820210000000000000000000000000000000000000000000000000000000000082018000000000000000000000000000000000000000000000000000000000008202200000000000000000000000000000000000000000000000000000000000820190000000000000000000000000000000000000000000000000000000000082023000000000000000000000000000000000000000000000000000000000008201a0000000000000000000000000000000000000000000000000000000000082024000000000000000000000000000000000000000000000000000000000008201b0000000000000000000000000000000000000000000000000000000000082025000000000000000000000000000000000000000000000000000000000008201c0000000000000000000000000000000000000000000000000000000000082026000000000000000000000000000000000000000000000000000000000008201d0000000000000000000000000000000000000000000000000000000000082027000000000000000000000000000000000000000000000000000000000008201e0000000000000000000000000000000000000000000000000000000000082028000000000000000000000000000000000000000000000000000000000008201f00000000000000000000000000000000000000000000000000000000000820290000000000000000000000000000000000000000000000000000000000082020000000000000000000000000000000000000000000000000000000000008202a0000000000000000000000000000000000000000000000000000000000082021000000000000000000000000000000000000000000000000000000000008202b0000000000000000000000000000000000000000000000000000000000082022000000000000000000000000000000000000000000000000000000000008202c0000000000000000000000000000000000000000000000000000000000082023000000000000000000000000000000000000000000000000000000000008202d0000000000000000000000000000000000000000000000000000000000082024000000000000000000000000000000000000000000000000000000000008202e0000000000000000000000000000000000000000000000000000000000082025000000000000000000000000000000000000000000000000000000000008202f00000000000000000000000000000000000000000000000000000000000820260000000000000000000000000000000000000000000000000000000000082030000000000000000000000000000000000000000000000000000000000008202700000000000000000000000000000000000000000000000000000000000820310000000000000000000000000000000000000000000000000000000000082028000000000000000000000000000000000000000000000000000000000008203200000000000000000000000000000000000000000000000000000000000820290000000000000000000000000000000000000000000000000000000000082033000000000000000000000000000000000000000000000000000000000008202a0000000000000000000000000000000000000000000000000000000000082034000000000000000000000000000000000000000000000000000000000008202b0000000000000000000000000000000000000000000000000000000000082035000000000000000000000000000000000000000000000000000000000008202c0000000000000000000000000000000000000000000000000000000000082036000000000000000000000000000000000000000000000000000000000008202d0000000000000000000000000000000000000000000000000000000000082037000000000000000000000000000000000000000000000000000000000008202e0000000000000000000000000000000000000000000000000000000000082038000000000000000000000000000000000000000000000000000000000008202f00000000000000000000000000000000000000000000000000000000000820390000000000000000000000000000000000000000000000000000000000082030000000000000000000000000000000000000000000000000000000000008203a0000000000000000000000000000000000000000000000000000000000082031000000000000000000000000000000000000000000000000000000000008203b0000000000000000000000000000000000000000000000000000000000082032000000000000000000000000000000000000000000000000000000000008203c0000000000000000000000000000000000000000000000000000000000082033000000000000000000000000000000000000000000000000000000000008203d0000000000000000000000000000000000000000000000000000000000082034000000000000000000000000000000000000000000000000000000000008203e0000000000000000000000000000000000000000000000000000000000082035000000000000000000000000000000000000000000000000000000000008203f00000000000000000000000000000000000000000000000000000000000820360000000000000000000000000000000000000000000000000000000000082040000000000000000000000000000000000000000000000000000000000008203700000000000000000000000000000000000000000000000000000000000820410000000000000000000000000000000000000000000000000000000000082038000000000000000000000000000000000000000000000000000000000008204200000000000000000000000000000000000000000000000000000000000820390000000000000000000000000000000000000000000000000000000000082043000000000000000000000000000000000000000000000000000000000008203a0000000000000000000000000000000000000000000000000000000000082044000000000000000000000000000000000000000000000000000000000008203b0000000000000000000000000000000000000000000000000000000000082045000000000000000000000000000000000000000000000000000000000008203c0000000000000000000000000000000000000000000000000000000000082046000000000000000000000000000000000000000000000000000000000008203d0000000000000000000000000000000000000000000000000000000000082047000000000000000000000000000000000000000000000000000000000008203e00000000000000000000000000000000000000000000000000000000000820480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000c100100000000000000000000000000000000000000000000000000000000000c100200000000000000000000000000000000000000000000000000000000000c100300000000000000000000000000000000000000000000000000000000000c100400000000000000000000000000000000000000000000000000000000000c100500000000000000000000000000000000000000000000000000000000000c100600000000000000000000000000000000000000000000000000000000000c100700000000000000000000000000000000000000000000000000000000000c100800000000000000000000000000000000000000000000000000000000000c100900000000000000000000000000000000000000000000000000000000000c100a00000000000000000000000000000000000000000000000000000000000c100b00000000000000000000000000000000000000000000000000000000000c100c00000000000000000000000000000000000000000000000000000000000c100d00000000000000000000000000000000000000000000000000000000000c100e00000000000000000000000000000000000000000000000000000000000c100f00000000000000000000000000000000000000000000000000000000000c101000000000000000000000000000000000000000000000000000000000000c101100000000000000000000000000000000000000000000000000000000000c101200000000000000000000000000000000000000000000000000000000000c101300000000000000000000000000000000000000000000000000000000000c101400000000000000000000000000000000000000000000000000000000000c101500000000000000000000000000000000000000000000000000000000000c101600000000000000000000000000000000000000000000000000000000000c101700000000000000000000000000000000000000000000000000000000000c101800000000000000000000000000000000000000000000000000000000000c101900000000000000000000000000000000000000000000000000000000000c101a00000000000000000000000000000000000000000000000000000000000c101b00000000000000000000000000000000000000000000000000000000000c101c00000000000000000000000000000000000000000000000000000000000c101d00000000000000000000000000000000000000000000000000000000000c101e00000000000000000000000000000000000000000000000000000000000c101f00000000000000000000000000000000000000000000000000000000000c102000000000000000000000000000000000000000000000000000000000000c102100000000000000000000000000000000000000000000000000000000000c102200000000000000000000000000000000000000000000000000000000000c102300000000000000000000000000000000000000000000000000000000000c102400000000000000000000000000000000000000000000000000000000000c102500000000000000000000000000000000000000000000000000000000000c102600000000000000000000000000000000000000000000000000000000000c102700000000000000000000000000000000000000000000000000000000000c102800000000000000000000000000000000000000000000000000000000000c102900000000000000000000000000000000000000000000000000000000000c102a00000000000000000000000000000000000000000000000000000000000c102b00000000000000000000000000000000000000000000000000000000000c102c00000000000000000000000000000000000000000000000000000000000c102d00000000000000000000000000000000000000000000000000000000000c102e00000000000000000000000000000000000000000000000000000000000c102f00000000000000000000000000000000000000000000000000000000000c103000000000000000000000000000000000000000000000000000000000000c103100000000000000000000000000000000000000000000000000000000000c103200000000000000000000000000000000000000000000000000000000000c103300000000000000000000000000000000000000000000000000000000000c103400000000000000000000000000000000000000000000000000000000000c103500000000000000000000000000000000000000000000000000000000000c103600000000000000000000000000000000000000000000000000000000000c103700000000000000000000000000000000000000000000000000000000000c103800000000000000000000000000000000000000000000000000000000000c103900000000000000000000000000000000000000000000000000000000000c103a00000000000000000000000000000000000000000000000000000000000c103b00000000000000000000000000000000000000000000000000000000000c103c00000000000000000000000000000000000000000000000000000000000c103d00000000000000000000000000000000000000000000000000000000000c103e00000000000000000000000000000000000000000000000000000000000c103f3f00000000000000000000000000000000000000000000000000000000000c110000000000000000000000000000000000000000000000000000000000000c110100000000000000000000000000000000000000000000000000000000000c110200000000000000000000000000000000000000000000000000000000000c110300000000000000000000000000000000000000000000000000000000000c110400000000000000000000000000000000000000000000000000000000000c110500000000000000000000000000000000000000000000000000000000000c110600000000000000000000000000000000000000000000000000000000000c110700000000000000000000000000000000000000000000000000000000000c110800000000000000000000000000000000000000000000000000000000000c110900000000000000000000000000000000000000000000000000000000000c110a00000000000000000000000000000000000000000000000000000000000c110b00000000000000000000000000000000000000000000000000000000000c110c00000000000000000000000000000000000000000000000000000000000c110d00000000000000000000000000000000000000000000000000000000000c110e00000000000000000000000000000000000000000000000000000000000c110f00000000000000000000000000000000000000000000000000000000000c111000000000000000000000000000000000000000000000000000000000000c111100000000000000000000000000000000000000000000000000000000000c111200000000000000000000000000000000000000000000000000000000000c111300000000000000000000000000000000000000000000000000000000000c111400000000000000000000000000000000000000000000000000000000000c111500000000000000000000000000000000000000000000000000000000000c111600000000000000000000000000000000000000000000000000000000000c111700000000000000000000000000000000000000000000000000000000000c111800000000000000000000000000000000000000000000000000000000000c111900000000000000000000000000000000000000000000000000000000000c111a00000000000000000000000000000000000000000000000000000000000c111b00000000000000000000000000000000000000000000000000000000000c111c00000000000000000000000000000000000000000000000000000000000c111d00000000000000000000000000000000000000000000000000000000000c111e00000000000000000000000000000000000000000000000000000000000c111f00000000000000000000000000000000000000000000000000000000000c112000000000000000000000000000000000000000000000000000000000000c112100000000000000000000000000000000000000000000000000000000000c112200000000000000000000000000000000000000000000000000000000000c112300000000000000000000000000000000000000000000000000000000000c112400000000000000000000000000000000000000000000000000000000000c112500000000000000000000000000000000000000000000000000000000000c112600000000000000000000000000000000000000000000000000000000000c112700000000000000000000000000000000000000000000000000000000000c112800000000000000000000000000000000000000000000000000000000000c112900000000000000000000000000000000000000000000000000000000000c112a00000000000000000000000000000000000000000000000000000000000c112b00000000000000000000000000000000000000000000000000000000000c112c00000000000000000000000000000000000000000000000000000000000c112d00000000000000000000000000000000000000000000000000000000000c112e00000000000000000000000000000000000000000000000000000000000c112f00000000000000000000000000000000000000000000000000000000000c113000000000000000000000000000000000000000000000000000000000000c113100000000000000000000000000000000000000000000000000000000000c113200000000000000000000000000000000000000000000000000000000000c113300000000000000000000000000000000000000000000000000000000000c113400000000000000000000000000000000000000000000000000000000000c113500000000000000000000000000000000000000000000000000000000000c113600000000000000000000000000000000000000000000000000000000000c113700000000000000000000000000000000000000000000000000000000000c113800000000000000000000000000000000000000000000000000000000000c113900000000000000000000000000000000000000000000000000000000000c113a00000000000000000000000000000000000000000000000000000000000c113b00000000000000000000000000000000000000000000000000000000000c113c00000000000000000000000000000000000000000000000000000000000c113d00000000000000000000000000000000000000000000000000000000000c113e0800f8029be42ec3f25204907ca981fb71e5b357093eb5db10fc01ca98a4e4154c0030e13d351a5bf1d5a040e82a163ca57017f39162693f85c571e441e36d702d00a550ae0f39f977d9473d6de1be3232fc68ed0c4a601d53542148695102cfc9005580bc65e4bff9c8fffa64db02c0fa6af14d9d26fd962f4c5904cbd3ddec2500758c4a0d43dfec788b2f580877c4f473adec8f168ea24424f2600e4eb4916f00342602bf90d10f8ca8e582a894dcc4c02bb89fe458532e0c632b53bae54b4d00ca43ab78ab834337e9964d84a0674c9adabdca140539c5a6bc96e0ba9a51f6004ffbfd91be292a7c6a0e255e50caa156ac2d628b40ad2128c4ab63a92d8a1c3f00000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c200a00000000000000000000000000000000000000000000000000000000000c200100000000000000000000000000000000000000000000000000000000000c200b00000000000000000000000000000000000000000000000000000000000c200200000000000000000000000000000000000000000000000000000000000c200c00000000000000000000000000000000000000000000000000000000000c200300000000000000000000000000000000000000000000000000000000000c200d00000000000000000000000000000000000000000000000000000000000c200400000000000000000000000000000000000000000000000000000000000c200e00000000000000000000000000000000000000000000000000000000000c200500000000000000000000000000000000000000000000000000000000000c200f00000000000000000000000000000000000000000000000000000000000c200600000000000000000000000000000000000000000000000000000000000c201000000000000000000000000000000000000000000000000000000000000c200700000000000000000000000000000000000000000000000000000000000c201100000000000000000000000000000000000000000000000000000000000c200800000000000000000000000000000000000000000000000000000000000c201200000000000000000000000000000000000000000000000000000000000c200900000000000000000000000000000000000000000000000000000000000c201300000000000000000000000000000000000000000000000000000000000c200a00000000000000000000000000000000000000000000000000000000000c201400000000000000000000000000000000000000000000000000000000000c200b00000000000000000000000000000000000000000000000000000000000c201500000000000000000000000000000000000000000000000000000000000c200c00000000000000000000000000000000000000000000000000000000000c201600000000000000000000000000000000000000000000000000000000000c200d00000000000000000000000000000000000000000000000000000000000c201700000000000000000000000000000000000000000000000000000000000c200e00000000000000000000000000000000000000000000000000000000000c201800000000000000000000000000000000000000000000000000000000000c200f00000000000000000000000000000000000000000000000000000000000c201900000000000000000000000000000000000000000000000000000000000c201000000000000000000000000000000000000000000000000000000000000c201a00000000000000000000000000000000000000000000000000000000000c201100000000000000000000000000000000000000000000000000000000000c201b00000000000000000000000000000000000000000000000000000000000c201200000000000000000000000000000000000000000000000000000000000c201c00000000000000000000000000000000000000000000000000000000000c201300000000000000000000000000000000000000000000000000000000000c201d00000000000000000000000000000000000000000000000000000000000c201400000000000000000000000000000000000000000000000000000000000c201e00000000000000000000000000000000000000000000000000000000000c201500000000000000000000000000000000000000000000000000000000000c201f00000000000000000000000000000000000000000000000000000000000c201600000000000000000000000000000000000000000000000000000000000c202000000000000000000000000000000000000000000000000000000000000c201700000000000000000000000000000000000000000000000000000000000c202100000000000000000000000000000000000000000000000000000000000c201800000000000000000000000000000000000000000000000000000000000c202200000000000000000000000000000000000000000000000000000000000c201900000000000000000000000000000000000000000000000000000000000c202300000000000000000000000000000000000000000000000000000000000c201a00000000000000000000000000000000000000000000000000000000000c202400000000000000000000000000000000000000000000000000000000000c201b00000000000000000000000000000000000000000000000000000000000c202500000000000000000000000000000000000000000000000000000000000c201c00000000000000000000000000000000000000000000000000000000000c202600000000000000000000000000000000000000000000000000000000000c201d00000000000000000000000000000000000000000000000000000000000c202700000000000000000000000000000000000000000000000000000000000c201e00000000000000000000000000000000000000000000000000000000000c202800000000000000000000000000000000000000000000000000000000000c201f00000000000000000000000000000000000000000000000000000000000c202900000000000000000000000000000000000000000000000000000000000c202000000000000000000000000000000000000000000000000000000000000c202a00000000000000000000000000000000000000000000000000000000000c202100000000000000000000000000000000000000000000000000000000000c202b00000000000000000000000000000000000000000000000000000000000c202200000000000000000000000000000000000000000000000000000000000c202c00000000000000000000000000000000000000000000000000000000000c202300000000000000000000000000000000000000000000000000000000000c202d00000000000000000000000000000000000000000000000000000000000c202400000000000000000000000000000000000000000000000000000000000c202e00000000000000000000000000000000000000000000000000000000000c202500000000000000000000000000000000000000000000000000000000000c202f00000000000000000000000000000000000000000000000000000000000c202600000000000000000000000000000000000000000000000000000000000c203000000000000000000000000000000000000000000000000000000000000c202700000000000000000000000000000000000000000000000000000000000c203100000000000000000000000000000000000000000000000000000000000c202800000000000000000000000000000000000000000000000000000000000c203200000000000000000000000000000000000000000000000000000000000c202900000000000000000000000000000000000000000000000000000000000c203300000000000000000000000000000000000000000000000000000000000c202a00000000000000000000000000000000000000000000000000000000000c203400000000000000000000000000000000000000000000000000000000000c202b00000000000000000000000000000000000000000000000000000000000c203500000000000000000000000000000000000000000000000000000000000c202c00000000000000000000000000000000000000000000000000000000000c203600000000000000000000000000000000000000000000000000000000000c202d00000000000000000000000000000000000000000000000000000000000c203700000000000000000000000000000000000000000000000000000000000c202e00000000000000000000000000000000000000000000000000000000000c203800000000000000000000000000000000000000000000000000000000000c202f00000000000000000000000000000000000000000000000000000000000c203900000000000000000000000000000000000000000000000000000000000c203000000000000000000000000000000000000000000000000000000000000c203a00000000000000000000000000000000000000000000000000000000000c203100000000000000000000000000000000000000000000000000000000000c203b00000000000000000000000000000000000000000000000000000000000c203200000000000000000000000000000000000000000000000000000000000c203c00000000000000000000000000000000000000000000000000000000000c203300000000000000000000000000000000000000000000000000000000000c203d00000000000000000000000000000000000000000000000000000000000c203400000000000000000000000000000000000000000000000000000000000c203e00000000000000000000000000000000000000000000000000000000000c203500000000000000000000000000000000000000000000000000000000000c203f00000000000000000000000000000000000000000000000000000000000c203600000000000000000000000000000000000000000000000000000000000c204000000000000000000000000000000000000000000000000000000000000c203700000000000000000000000000000000000000000000000000000000000c204100000000000000000000000000000000000000000000000000000000000c203800000000000000000000000000000000000000000000000000000000000c204200000000000000000000000000000000000000000000000000000000000c203900000000000000000000000000000000000000000000000000000000000c204300000000000000000000000000000000000000000000000000000000000c203a00000000000000000000000000000000000000000000000000000000000c204400000000000000000000000000000000000000000000000000000000000c203b00000000000000000000000000000000000000000000000000000000000c204500000000000000000000000000000000000000000000000000000000000c203c00000000000000000000000000000000000000000000000000000000000c204600000000000000000000000000000000000000000000000000000000000c203d00000000000000000000000000000000000000000000000000000000000c204700000000000000000000000000000000000000000000000000000000000c203e00000000000000000000000000000000000000000000000000000000000c2048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000101000000000000000000000000000000000000000000000000000000000000010100100000000000000000000000000000000000000000000000000000000001010020000000000000000000000000000000000000000000000000000000000101003000000000000000000000000000000000000000000000000000000000010100400000000000000000000000000000000000000000000000000000000001010050000000000000000000000000000000000000000000000000000000000101006000000000000000000000000000000000000000000000000000000000010100700000000000000000000000000000000000000000000000000000000001010080000000000000000000000000000000000000000000000000000000000101009000000000000000000000000000000000000000000000000000000000010100a000000000000000000000000000000000000000000000000000000000010100b000000000000000000000000000000000000000000000000000000000010100c000000000000000000000000000000000000000000000000000000000010100d000000000000000000000000000000000000000000000000000000000010100e000000000000000000000000000000000000000000000000000000000010100f0000000000000000000000000000000000000000000000000000000000101010000000000000000000000000000000000000000000000000000000000010101100000000000000000000000000000000000000000000000000000000001010120000000000000000000000000000000000000000000000000000000000101013000000000000000000000000000000000000000000000000000000000010101400000000000000000000000000000000000000000000000000000000001010150000000000000000000000000000000000000000000000000000000000101016000000000000000000000000000000000000000000000000000000000010101700000000000000000000000000000000000000000000000000000000001010180000000000000000000000000000000000000000000000000000000000101019000000000000000000000000000000000000000000000000000000000010101a000000000000000000000000000000000000000000000000000000000010101b000000000000000000000000000000000000000000000000000000000010101c000000000000000000000000000000000000000000000000000000000010101d000000000000000000000000000000000000000000000000000000000010101e000000000000000000000000000000000000000000000000000000000010101f0000000000000000000000000000000000000000000000000000000000101020000000000000000000000000000000000000000000000000000000000010102100000000000000000000000000000000000000000000000000000000001010220000000000000000000000000000000000000000000000000000000000101023000000000000000000000000000000000000000000000000000000000010102400000000000000000000000000000000000000000000000000000000001010250000000000000000000000000000000000000000000000000000000000101026000000000000000000000000000000000000000000000000000000000010102700000000000000000000000000000000000000000000000000000000001010280000000000000000000000000000000000000000000000000000000000101029000000000000000000000000000000000000000000000000000000000010102a000000000000000000000000000000000000000000000000000000000010102b000000000000000000000000000000000000000000000000000000000010102c000000000000000000000000000000000000000000000000000000000010102d000000000000000000000000000000000000000000000000000000000010102e000000000000000000000000000000000000000000000000000000000010102f0000000000000000000000000000000000000000000000000000000000101030000000000000000000000000000000000000000000000000000000000010103100000000000000000000000000000000000000000000000000000000001010320000000000000000000000000000000000000000000000000000000000101033000000000000000000000000000000000000000000000000000000000010103400000000000000000000000000000000000000000000000000000000001010350000000000000000000000000000000000000000000000000000000000101036000000000000000000000000000000000000000000000000000000000010103700000000000000000000000000000000000000000000000000000000001010380000000000000000000000000000000000000000000000000000000000101039000000000000000000000000000000000000000000000000000000000010103a000000000000000000000000000000000000000000000000000000000010103b000000000000000000000000000000000000000000000000000000000010103c000000000000000000000000000000000000000000000000000000000010103d000000000000000000000000000000000000000000000000000000000010103e000000000000000000000000000000000000000000000000000000000010103f3f0000000000000000000000000000000000000000000000000000000000101100000000000000000000000000000000000000000000000000000000000010110100000000000000000000000000000000000000000000000000000000001011020000000000000000000000000000000000000000000000000000000000101103000000000000000000000000000000000000000000000000000000000010110400000000000000000000000000000000000000000000000000000000001011050000000000000000000000000000000000000000000000000000000000101106000000000000000000000000000000000000000000000000000000000010110700000000000000000000000000000000000000000000000000000000001011080000000000000000000000000000000000000000000000000000000000101109000000000000000000000000000000000000000000000000000000000010110a000000000000000000000000000000000000000000000000000000000010110b000000000000000000000000000000000000000000000000000000000010110c000000000000000000000000000000000000000000000000000000000010110d000000000000000000000000000000000000000000000000000000000010110e000000000000000000000000000000000000000000000000000000000010110f0000000000000000000000000000000000000000000000000000000000101110000000000000000000000000000000000000000000000000000000000010111100000000000000000000000000000000000000000000000000000000001011120000000000000000000000000000000000000000000000000000000000101113000000000000000000000000000000000000000000000000000000000010111400000000000000000000000000000000000000000000000000000000001011150000000000000000000000000000000000000000000000000000000000101116000000000000000000000000000000000000000000000000000000000010111700000000000000000000000000000000000000000000000000000000001011180000000000000000000000000000000000000000000000000000000000101119000000000000000000000000000000000000000000000000000000000010111a000000000000000000000000000000000000000000000000000000000010111b000000000000000000000000000000000000000000000000000000000010111c000000000000000000000000000000000000000000000000000000000010111d000000000000000000000000000000000000000000000000000000000010111e000000000000000000000000000000000000000000000000000000000010111f0000000000000000000000000000000000000000000000000000000000101120000000000000000000000000000000000000000000000000000000000010112100000000000000000000000000000000000000000000000000000000001011220000000000000000000000000000000000000000000000000000000000101123000000000000000000000000000000000000000000000000000000000010112400000000000000000000000000000000000000000000000000000000001011250000000000000000000000000000000000000000000000000000000000101126000000000000000000000000000000000000000000000000000000000010112700000000000000000000000000000000000000000000000000000000001011280000000000000000000000000000000000000000000000000000000000101129000000000000000000000000000000000000000000000000000000000010112a000000000000000000000000000000000000000000000000000000000010112b000000000000000000000000000000000000000000000000000000000010112c000000000000000000000000000000000000000000000000000000000010112d000000000000000000000000000000000000000000000000000000000010112e000000000000000000000000000000000000000000000000000000000010112f0000000000000000000000000000000000000000000000000000000000101130000000000000000000000000000000000000000000000000000000000010113100000000000000000000000000000000000000000000000000000000001011320000000000000000000000000000000000000000000000000000000000101133000000000000000000000000000000000000000000000000000000000010113400000000000000000000000000000000000000000000000000000000001011350000000000000000000000000000000000000000000000000000000000101136000000000000000000000000000000000000000000000000000000000010113700000000000000000000000000000000000000000000000000000000001011380000000000000000000000000000000000000000000000000000000000101139000000000000000000000000000000000000000000000000000000000010113a000000000000000000000000000000000000000000000000000000000010113b000000000000000000000000000000000000000000000000000000000010113c000000000000000000000000000000000000000000000000000000000010113d000000000000000000000000000000000000000000000000000000000010113e080099145b6c0d32753835121f8b271186d01236948a4622ce78a98347fcfc98390085277a27c6acbd5ffc4c19cd65fc30056999e9bec36998f753132db0ff8e2300f3cf77a7261759ebd5f4149f6ad56746f4499cfcd4adf27a1d373f77da64d5009bc6e0e994a23cde8c95b90c1acc1b4a480c6599d1df2c3f9f6e76f3d1aff200d7a1c4a2700dacaaf07f1f0ff33837bdbabcf0b9ace17efabe0761708c4bb900dbeb8e96d14f21e57d5786b6d6ae7e5ddb1bb35935c0fb246d4bdbca62e02c00fbf12b5e0df6223b801088798e4e04d2a92ffe9a11639b7f0ce314e3412a8000d796e0724de03b796ba77069fcd6cf921e566f3aed15eb3e77258add74e9ff3f0000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010200a0000000000000000000000000000000000000000000000000000000000102001000000000000000000000000000000000000000000000000000000000010200b0000000000000000000000000000000000000000000000000000000000102002000000000000000000000000000000000000000000000000000000000010200c0000000000000000000000000000000000000000000000000000000000102003000000000000000000000000000000000000000000000000000000000010200d0000000000000000000000000000000000000000000000000000000000102004000000000000000000000000000000000000000000000000000000000010200e0000000000000000000000000000000000000000000000000000000000102005000000000000000000000000000000000000000000000000000000000010200f00000000000000000000000000000000000000000000000000000000001020060000000000000000000000000000000000000000000000000000000000102010000000000000000000000000000000000000000000000000000000000010200700000000000000000000000000000000000000000000000000000000001020110000000000000000000000000000000000000000000000000000000000102008000000000000000000000000000000000000000000000000000000000010201200000000000000000000000000000000000000000000000000000000001020090000000000000000000000000000000000000000000000000000000000102013000000000000000000000000000000000000000000000000000000000010200a0000000000000000000000000000000000000000000000000000000000102014000000000000000000000000000000000000000000000000000000000010200b0000000000000000000000000000000000000000000000000000000000102015000000000000000000000000000000000000000000000000000000000010200c0000000000000000000000000000000000000000000000000000000000102016000000000000000000000000000000000000000000000000000000000010200d0000000000000000000000000000000000000000000000000000000000102017000000000000000000000000000000000000000000000000000000000010200e0000000000000000000000000000000000000000000000000000000000102018000000000000000000000000000000000000000000000000000000000010200f00000000000000000000000000000000000000000000000000000000001020190000000000000000000000000000000000000000000000000000000000102010000000000000000000000000000000000000000000000000000000000010201a0000000000000000000000000000000000000000000000000000000000102011000000000000000000000000000000000000000000000000000000000010201b0000000000000000000000000000000000000000000000000000000000102012000000000000000000000000000000000000000000000000000000000010201c0000000000000000000000000000000000000000000000000000000000102013000000000000000000000000000000000000000000000000000000000010201d0000000000000000000000000000000000000000000000000000000000102014000000000000000000000000000000000000000000000000000000000010201e0000000000000000000000000000000000000000000000000000000000102015000000000000000000000000000000000000000000000000000000000010201f00000000000000000000000000000000000000000000000000000000001020160000000000000000000000000000000000000000000000000000000000102020000000000000000000000000000000000000000000000000000000000010201700000000000000000000000000000000000000000000000000000000001020210000000000000000000000000000000000000000000000000000000000102018000000000000000000000000000000000000000000000000000000000010202200000000000000000000000000000000000000000000000000000000001020190000000000000000000000000000000000000000000000000000000000102023000000000000000000000000000000000000000000000000000000000010201a0000000000000000000000000000000000000000000000000000000000102024000000000000000000000000000000000000000000000000000000000010201b0000000000000000000000000000000000000000000000000000000000102025000000000000000000000000000000000000000000000000000000000010201c0000000000000000000000000000000000000000000000000000000000102026000000000000000000000000000000000000000000000000000000000010201d0000000000000000000000000000000000000000000000000000000000102027000000000000000000000000000000000000000000000000000000000010201e0000000000000000000000000000000000000000000000000000000000102028000000000000000000000000000000000000000000000000000000000010201f00000000000000000000000000000000000000000000000000000000001020290000000000000000000000000000000000000000000000000000000000102020000000000000000000000000000000000000000000000000000000000010202a0000000000000000000000000000000000000000000000000000000000102021000000000000000000000000000000000000000000000000000000000010202b0000000000000000000000000000000000000000000000000000000000102022000000000000000000000000000000000000000000000000000000000010202c0000000000000000000000000000000000000000000000000000000000102023000000000000000000000000000000000000000000000000000000000010202d0000000000000000000000000000000000000000000000000000000000102024000000000000000000000000000000000000000000000000000000000010202e0000000000000000000000000000000000000000000000000000000000102025000000000000000000000000000000000000000000000000000000000010202f00000000000000000000000000000000000000000000000000000000001020260000000000000000000000000000000000000000000000000000000000102030000000000000000000000000000000000000000000000000000000000010202700000000000000000000000000000000000000000000000000000000001020310000000000000000000000000000000000000000000000000000000000102028000000000000000000000000000000000000000000000000000000000010203200000000000000000000000000000000000000000000000000000000001020290000000000000000000000000000000000000000000000000000000000102033000000000000000000000000000000000000000000000000000000000010202a0000000000000000000000000000000000000000000000000000000000102034000000000000000000000000000000000000000000000000000000000010202b0000000000000000000000000000000000000000000000000000000000102035000000000000000000000000000000000000000000000000000000000010202c0000000000000000000000000000000000000000000000000000000000102036000000000000000000000000000000000000000000000000000000000010202d0000000000000000000000000000000000000000000000000000000000102037000000000000000000000000000000000000000000000000000000000010202e0000000000000000000000000000000000000000000000000000000000102038000000000000000000000000000000000000000000000000000000000010202f00000000000000000000000000000000000000000000000000000000001020390000000000000000000000000000000000000000000000000000000000102030000000000000000000000000000000000000000000000000000000000010203a0000000000000000000000000000000000000000000000000000000000102031000000000000000000000000000000000000000000000000000000000010203b0000000000000000000000000000000000000000000000000000000000102032000000000000000000000000000000000000000000000000000000000010203c0000000000000000000000000000000000000000000000000000000000102033000000000000000000000000000000000000000000000000000000000010203d0000000000000000000000000000000000000000000000000000000000102034000000000000000000000000000000000000000000000000000000000010203e0000000000000000000000000000000000000000000000000000000000102035000000000000000000000000000000000000000000000000000000000010203f00000000000000000000000000000000000000000000000000000000001020360000000000000000000000000000000000000000000000000000000000102040000000000000000000000000000000000000000000000000000000000010203700000000000000000000000000000000000000000000000000000000001020410000000000000000000000000000000000000000000000000000000000102038000000000000000000000000000000000000000000000000000000000010204200000000000000000000000000000000000000000000000000000000001020390000000000000000000000000000000000000000000000000000000000102043000000000000000000000000000000000000000000000000000000000010203a0000000000000000000000000000000000000000000000000000000000102044000000000000000000000000000000000000000000000000000000000010203b0000000000000000000000000000000000000000000000000000000000102045000000000000000000000000000000000000000000000000000000000010203c0000000000000000000000000000000000000000000000000000000000102046000000000000000000000000000000000000000000000000000000000010203d0000000000000000000000000000000000000000000000000000000000102047000000000000000000000000000000000000000000000000000000000010203e0000000000000000000000000000000000000000000000000000000000102048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "txsEffectsHash": "0x007b27babdf78c8beb8d7a937731158a4422309edacfeb6e2b9c9125a01617a2", + "archive": "0x13232b1c92fcfba5f94aee813d7e454764f93d6292215552b8c973ef42c8e396", + "blockHash": "0x024c7ee2217388b1e45747c7233b2f3993bfc88a8a944ee89a11d9c66c24907d", + "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000004100100000000000000000000000000000000000000000000000000000000000410020000000000000000000000000000000000000000000000000000000000041003000000000000000000000000000000000000000000000000000000000004100400000000000000000000000000000000000000000000000000000000000410050000000000000000000000000000000000000000000000000000000000041006000000000000000000000000000000000000000000000000000000000004100700000000000000000000000000000000000000000000000000000000000410080000000000000000000000000000000000000000000000000000000000041009000000000000000000000000000000000000000000000000000000000004100a000000000000000000000000000000000000000000000000000000000004100b000000000000000000000000000000000000000000000000000000000004100c000000000000000000000000000000000000000000000000000000000004100d000000000000000000000000000000000000000000000000000000000004100e000000000000000000000000000000000000000000000000000000000004100f0000000000000000000000000000000000000000000000000000000000041010000000000000000000000000000000000000000000000000000000000004101100000000000000000000000000000000000000000000000000000000000410120000000000000000000000000000000000000000000000000000000000041013000000000000000000000000000000000000000000000000000000000004101400000000000000000000000000000000000000000000000000000000000410150000000000000000000000000000000000000000000000000000000000041016000000000000000000000000000000000000000000000000000000000004101700000000000000000000000000000000000000000000000000000000000410180000000000000000000000000000000000000000000000000000000000041019000000000000000000000000000000000000000000000000000000000004101a000000000000000000000000000000000000000000000000000000000004101b000000000000000000000000000000000000000000000000000000000004101c000000000000000000000000000000000000000000000000000000000004101d000000000000000000000000000000000000000000000000000000000004101e000000000000000000000000000000000000000000000000000000000004101f0000000000000000000000000000000000000000000000000000000000041020000000000000000000000000000000000000000000000000000000000004102100000000000000000000000000000000000000000000000000000000000410220000000000000000000000000000000000000000000000000000000000041023000000000000000000000000000000000000000000000000000000000004102400000000000000000000000000000000000000000000000000000000000410250000000000000000000000000000000000000000000000000000000000041026000000000000000000000000000000000000000000000000000000000004102700000000000000000000000000000000000000000000000000000000000410280000000000000000000000000000000000000000000000000000000000041029000000000000000000000000000000000000000000000000000000000004102a000000000000000000000000000000000000000000000000000000000004102b000000000000000000000000000000000000000000000000000000000004102c000000000000000000000000000000000000000000000000000000000004102d000000000000000000000000000000000000000000000000000000000004102e000000000000000000000000000000000000000000000000000000000004102f0000000000000000000000000000000000000000000000000000000000041030000000000000000000000000000000000000000000000000000000000004103100000000000000000000000000000000000000000000000000000000000410320000000000000000000000000000000000000000000000000000000000041033000000000000000000000000000000000000000000000000000000000004103400000000000000000000000000000000000000000000000000000000000410350000000000000000000000000000000000000000000000000000000000041036000000000000000000000000000000000000000000000000000000000004103700000000000000000000000000000000000000000000000000000000000410380000000000000000000000000000000000000000000000000000000000041039000000000000000000000000000000000000000000000000000000000004103a000000000000000000000000000000000000000000000000000000000004103b000000000000000000000000000000000000000000000000000000000004103c000000000000000000000000000000000000000000000000000000000004103d000000000000000000000000000000000000000000000000000000000004103e000000000000000000000000000000000000000000000000000000000004103f3f0000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004110100000000000000000000000000000000000000000000000000000000000411020000000000000000000000000000000000000000000000000000000000041103000000000000000000000000000000000000000000000000000000000004110400000000000000000000000000000000000000000000000000000000000411050000000000000000000000000000000000000000000000000000000000041106000000000000000000000000000000000000000000000000000000000004110700000000000000000000000000000000000000000000000000000000000411080000000000000000000000000000000000000000000000000000000000041109000000000000000000000000000000000000000000000000000000000004110a000000000000000000000000000000000000000000000000000000000004110b000000000000000000000000000000000000000000000000000000000004110c000000000000000000000000000000000000000000000000000000000004110d000000000000000000000000000000000000000000000000000000000004110e000000000000000000000000000000000000000000000000000000000004110f0000000000000000000000000000000000000000000000000000000000041110000000000000000000000000000000000000000000000000000000000004111100000000000000000000000000000000000000000000000000000000000411120000000000000000000000000000000000000000000000000000000000041113000000000000000000000000000000000000000000000000000000000004111400000000000000000000000000000000000000000000000000000000000411150000000000000000000000000000000000000000000000000000000000041116000000000000000000000000000000000000000000000000000000000004111700000000000000000000000000000000000000000000000000000000000411180000000000000000000000000000000000000000000000000000000000041119000000000000000000000000000000000000000000000000000000000004111a000000000000000000000000000000000000000000000000000000000004111b000000000000000000000000000000000000000000000000000000000004111c000000000000000000000000000000000000000000000000000000000004111d000000000000000000000000000000000000000000000000000000000004111e000000000000000000000000000000000000000000000000000000000004111f0000000000000000000000000000000000000000000000000000000000041120000000000000000000000000000000000000000000000000000000000004112100000000000000000000000000000000000000000000000000000000000411220000000000000000000000000000000000000000000000000000000000041123000000000000000000000000000000000000000000000000000000000004112400000000000000000000000000000000000000000000000000000000000411250000000000000000000000000000000000000000000000000000000000041126000000000000000000000000000000000000000000000000000000000004112700000000000000000000000000000000000000000000000000000000000411280000000000000000000000000000000000000000000000000000000000041129000000000000000000000000000000000000000000000000000000000004112a000000000000000000000000000000000000000000000000000000000004112b000000000000000000000000000000000000000000000000000000000004112c000000000000000000000000000000000000000000000000000000000004112d000000000000000000000000000000000000000000000000000000000004112e000000000000000000000000000000000000000000000000000000000004112f0000000000000000000000000000000000000000000000000000000000041130000000000000000000000000000000000000000000000000000000000004113100000000000000000000000000000000000000000000000000000000000411320000000000000000000000000000000000000000000000000000000000041133000000000000000000000000000000000000000000000000000000000004113400000000000000000000000000000000000000000000000000000000000411350000000000000000000000000000000000000000000000000000000000041136000000000000000000000000000000000000000000000000000000000004113700000000000000000000000000000000000000000000000000000000000411380000000000000000000000000000000000000000000000000000000000041139000000000000000000000000000000000000000000000000000000000004113a000000000000000000000000000000000000000000000000000000000004113b000000000000000000000000000000000000000000000000000000000004113c000000000000000000000000000000000000000000000000000000000004113d000000000000000000000000000000000000000000000000000000000004113e080097a6ec570e9b8e257647c9c74c5ad3edc57ca5ef6ae44d80b3c30d1d99b9b300ce48ec41d1edde0066fab553a456ae2f380d14fa8f956af1fb0217513a598900619ff12eaf97f63aa2a2311de3b6571a7b880a5247cb33b6a74787bf3f9bd5007854a2fad4e1801c6404394bf3d37ab08c135ea38a1974242e39a21273685f000f55796e72957a819e68a22e8602d73c3ba3718a5a4bd92b80b0aa444b182a00788b6e9874fb040ee679a7fae257190099a605229b948334e54a57739535d4004f1658ee3c1a91627e5d72f5a731f0796299df82ab41e72c88eee0c82fa85e003ee802add96628c693ed71afa9908138ba5a6fbf0a5f29a9c74e4e42aba6713f0000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000004200a0000000000000000000000000000000000000000000000000000000000042001000000000000000000000000000000000000000000000000000000000004200b0000000000000000000000000000000000000000000000000000000000042002000000000000000000000000000000000000000000000000000000000004200c0000000000000000000000000000000000000000000000000000000000042003000000000000000000000000000000000000000000000000000000000004200d0000000000000000000000000000000000000000000000000000000000042004000000000000000000000000000000000000000000000000000000000004200e0000000000000000000000000000000000000000000000000000000000042005000000000000000000000000000000000000000000000000000000000004200f00000000000000000000000000000000000000000000000000000000000420060000000000000000000000000000000000000000000000000000000000042010000000000000000000000000000000000000000000000000000000000004200700000000000000000000000000000000000000000000000000000000000420110000000000000000000000000000000000000000000000000000000000042008000000000000000000000000000000000000000000000000000000000004201200000000000000000000000000000000000000000000000000000000000420090000000000000000000000000000000000000000000000000000000000042013000000000000000000000000000000000000000000000000000000000004200a0000000000000000000000000000000000000000000000000000000000042014000000000000000000000000000000000000000000000000000000000004200b0000000000000000000000000000000000000000000000000000000000042015000000000000000000000000000000000000000000000000000000000004200c0000000000000000000000000000000000000000000000000000000000042016000000000000000000000000000000000000000000000000000000000004200d0000000000000000000000000000000000000000000000000000000000042017000000000000000000000000000000000000000000000000000000000004200e0000000000000000000000000000000000000000000000000000000000042018000000000000000000000000000000000000000000000000000000000004200f00000000000000000000000000000000000000000000000000000000000420190000000000000000000000000000000000000000000000000000000000042010000000000000000000000000000000000000000000000000000000000004201a0000000000000000000000000000000000000000000000000000000000042011000000000000000000000000000000000000000000000000000000000004201b0000000000000000000000000000000000000000000000000000000000042012000000000000000000000000000000000000000000000000000000000004201c0000000000000000000000000000000000000000000000000000000000042013000000000000000000000000000000000000000000000000000000000004201d0000000000000000000000000000000000000000000000000000000000042014000000000000000000000000000000000000000000000000000000000004201e0000000000000000000000000000000000000000000000000000000000042015000000000000000000000000000000000000000000000000000000000004201f00000000000000000000000000000000000000000000000000000000000420160000000000000000000000000000000000000000000000000000000000042020000000000000000000000000000000000000000000000000000000000004201700000000000000000000000000000000000000000000000000000000000420210000000000000000000000000000000000000000000000000000000000042018000000000000000000000000000000000000000000000000000000000004202200000000000000000000000000000000000000000000000000000000000420190000000000000000000000000000000000000000000000000000000000042023000000000000000000000000000000000000000000000000000000000004201a0000000000000000000000000000000000000000000000000000000000042024000000000000000000000000000000000000000000000000000000000004201b0000000000000000000000000000000000000000000000000000000000042025000000000000000000000000000000000000000000000000000000000004201c0000000000000000000000000000000000000000000000000000000000042026000000000000000000000000000000000000000000000000000000000004201d0000000000000000000000000000000000000000000000000000000000042027000000000000000000000000000000000000000000000000000000000004201e0000000000000000000000000000000000000000000000000000000000042028000000000000000000000000000000000000000000000000000000000004201f00000000000000000000000000000000000000000000000000000000000420290000000000000000000000000000000000000000000000000000000000042020000000000000000000000000000000000000000000000000000000000004202a0000000000000000000000000000000000000000000000000000000000042021000000000000000000000000000000000000000000000000000000000004202b0000000000000000000000000000000000000000000000000000000000042022000000000000000000000000000000000000000000000000000000000004202c0000000000000000000000000000000000000000000000000000000000042023000000000000000000000000000000000000000000000000000000000004202d0000000000000000000000000000000000000000000000000000000000042024000000000000000000000000000000000000000000000000000000000004202e0000000000000000000000000000000000000000000000000000000000042025000000000000000000000000000000000000000000000000000000000004202f00000000000000000000000000000000000000000000000000000000000420260000000000000000000000000000000000000000000000000000000000042030000000000000000000000000000000000000000000000000000000000004202700000000000000000000000000000000000000000000000000000000000420310000000000000000000000000000000000000000000000000000000000042028000000000000000000000000000000000000000000000000000000000004203200000000000000000000000000000000000000000000000000000000000420290000000000000000000000000000000000000000000000000000000000042033000000000000000000000000000000000000000000000000000000000004202a0000000000000000000000000000000000000000000000000000000000042034000000000000000000000000000000000000000000000000000000000004202b0000000000000000000000000000000000000000000000000000000000042035000000000000000000000000000000000000000000000000000000000004202c0000000000000000000000000000000000000000000000000000000000042036000000000000000000000000000000000000000000000000000000000004202d0000000000000000000000000000000000000000000000000000000000042037000000000000000000000000000000000000000000000000000000000004202e0000000000000000000000000000000000000000000000000000000000042038000000000000000000000000000000000000000000000000000000000004202f00000000000000000000000000000000000000000000000000000000000420390000000000000000000000000000000000000000000000000000000000042030000000000000000000000000000000000000000000000000000000000004203a0000000000000000000000000000000000000000000000000000000000042031000000000000000000000000000000000000000000000000000000000004203b0000000000000000000000000000000000000000000000000000000000042032000000000000000000000000000000000000000000000000000000000004203c0000000000000000000000000000000000000000000000000000000000042033000000000000000000000000000000000000000000000000000000000004203d0000000000000000000000000000000000000000000000000000000000042034000000000000000000000000000000000000000000000000000000000004203e0000000000000000000000000000000000000000000000000000000000042035000000000000000000000000000000000000000000000000000000000004203f00000000000000000000000000000000000000000000000000000000000420360000000000000000000000000000000000000000000000000000000000042040000000000000000000000000000000000000000000000000000000000004203700000000000000000000000000000000000000000000000000000000000420410000000000000000000000000000000000000000000000000000000000042038000000000000000000000000000000000000000000000000000000000004204200000000000000000000000000000000000000000000000000000000000420390000000000000000000000000000000000000000000000000000000000042043000000000000000000000000000000000000000000000000000000000004203a0000000000000000000000000000000000000000000000000000000000042044000000000000000000000000000000000000000000000000000000000004203b0000000000000000000000000000000000000000000000000000000000042045000000000000000000000000000000000000000000000000000000000004203c0000000000000000000000000000000000000000000000000000000000042046000000000000000000000000000000000000000000000000000000000004203d0000000000000000000000000000000000000000000000000000000000042047000000000000000000000000000000000000000000000000000000000004203e0000000000000000000000000000000000000000000000000000000000042048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008100100000000000000000000000000000000000000000000000000000000000810020000000000000000000000000000000000000000000000000000000000081003000000000000000000000000000000000000000000000000000000000008100400000000000000000000000000000000000000000000000000000000000810050000000000000000000000000000000000000000000000000000000000081006000000000000000000000000000000000000000000000000000000000008100700000000000000000000000000000000000000000000000000000000000810080000000000000000000000000000000000000000000000000000000000081009000000000000000000000000000000000000000000000000000000000008100a000000000000000000000000000000000000000000000000000000000008100b000000000000000000000000000000000000000000000000000000000008100c000000000000000000000000000000000000000000000000000000000008100d000000000000000000000000000000000000000000000000000000000008100e000000000000000000000000000000000000000000000000000000000008100f0000000000000000000000000000000000000000000000000000000000081010000000000000000000000000000000000000000000000000000000000008101100000000000000000000000000000000000000000000000000000000000810120000000000000000000000000000000000000000000000000000000000081013000000000000000000000000000000000000000000000000000000000008101400000000000000000000000000000000000000000000000000000000000810150000000000000000000000000000000000000000000000000000000000081016000000000000000000000000000000000000000000000000000000000008101700000000000000000000000000000000000000000000000000000000000810180000000000000000000000000000000000000000000000000000000000081019000000000000000000000000000000000000000000000000000000000008101a000000000000000000000000000000000000000000000000000000000008101b000000000000000000000000000000000000000000000000000000000008101c000000000000000000000000000000000000000000000000000000000008101d000000000000000000000000000000000000000000000000000000000008101e000000000000000000000000000000000000000000000000000000000008101f0000000000000000000000000000000000000000000000000000000000081020000000000000000000000000000000000000000000000000000000000008102100000000000000000000000000000000000000000000000000000000000810220000000000000000000000000000000000000000000000000000000000081023000000000000000000000000000000000000000000000000000000000008102400000000000000000000000000000000000000000000000000000000000810250000000000000000000000000000000000000000000000000000000000081026000000000000000000000000000000000000000000000000000000000008102700000000000000000000000000000000000000000000000000000000000810280000000000000000000000000000000000000000000000000000000000081029000000000000000000000000000000000000000000000000000000000008102a000000000000000000000000000000000000000000000000000000000008102b000000000000000000000000000000000000000000000000000000000008102c000000000000000000000000000000000000000000000000000000000008102d000000000000000000000000000000000000000000000000000000000008102e000000000000000000000000000000000000000000000000000000000008102f0000000000000000000000000000000000000000000000000000000000081030000000000000000000000000000000000000000000000000000000000008103100000000000000000000000000000000000000000000000000000000000810320000000000000000000000000000000000000000000000000000000000081033000000000000000000000000000000000000000000000000000000000008103400000000000000000000000000000000000000000000000000000000000810350000000000000000000000000000000000000000000000000000000000081036000000000000000000000000000000000000000000000000000000000008103700000000000000000000000000000000000000000000000000000000000810380000000000000000000000000000000000000000000000000000000000081039000000000000000000000000000000000000000000000000000000000008103a000000000000000000000000000000000000000000000000000000000008103b000000000000000000000000000000000000000000000000000000000008103c000000000000000000000000000000000000000000000000000000000008103d000000000000000000000000000000000000000000000000000000000008103e000000000000000000000000000000000000000000000000000000000008103f3f0000000000000000000000000000000000000000000000000000000000081100000000000000000000000000000000000000000000000000000000000008110100000000000000000000000000000000000000000000000000000000000811020000000000000000000000000000000000000000000000000000000000081103000000000000000000000000000000000000000000000000000000000008110400000000000000000000000000000000000000000000000000000000000811050000000000000000000000000000000000000000000000000000000000081106000000000000000000000000000000000000000000000000000000000008110700000000000000000000000000000000000000000000000000000000000811080000000000000000000000000000000000000000000000000000000000081109000000000000000000000000000000000000000000000000000000000008110a000000000000000000000000000000000000000000000000000000000008110b000000000000000000000000000000000000000000000000000000000008110c000000000000000000000000000000000000000000000000000000000008110d000000000000000000000000000000000000000000000000000000000008110e000000000000000000000000000000000000000000000000000000000008110f0000000000000000000000000000000000000000000000000000000000081110000000000000000000000000000000000000000000000000000000000008111100000000000000000000000000000000000000000000000000000000000811120000000000000000000000000000000000000000000000000000000000081113000000000000000000000000000000000000000000000000000000000008111400000000000000000000000000000000000000000000000000000000000811150000000000000000000000000000000000000000000000000000000000081116000000000000000000000000000000000000000000000000000000000008111700000000000000000000000000000000000000000000000000000000000811180000000000000000000000000000000000000000000000000000000000081119000000000000000000000000000000000000000000000000000000000008111a000000000000000000000000000000000000000000000000000000000008111b000000000000000000000000000000000000000000000000000000000008111c000000000000000000000000000000000000000000000000000000000008111d000000000000000000000000000000000000000000000000000000000008111e000000000000000000000000000000000000000000000000000000000008111f0000000000000000000000000000000000000000000000000000000000081120000000000000000000000000000000000000000000000000000000000008112100000000000000000000000000000000000000000000000000000000000811220000000000000000000000000000000000000000000000000000000000081123000000000000000000000000000000000000000000000000000000000008112400000000000000000000000000000000000000000000000000000000000811250000000000000000000000000000000000000000000000000000000000081126000000000000000000000000000000000000000000000000000000000008112700000000000000000000000000000000000000000000000000000000000811280000000000000000000000000000000000000000000000000000000000081129000000000000000000000000000000000000000000000000000000000008112a000000000000000000000000000000000000000000000000000000000008112b000000000000000000000000000000000000000000000000000000000008112c000000000000000000000000000000000000000000000000000000000008112d000000000000000000000000000000000000000000000000000000000008112e000000000000000000000000000000000000000000000000000000000008112f0000000000000000000000000000000000000000000000000000000000081130000000000000000000000000000000000000000000000000000000000008113100000000000000000000000000000000000000000000000000000000000811320000000000000000000000000000000000000000000000000000000000081133000000000000000000000000000000000000000000000000000000000008113400000000000000000000000000000000000000000000000000000000000811350000000000000000000000000000000000000000000000000000000000081136000000000000000000000000000000000000000000000000000000000008113700000000000000000000000000000000000000000000000000000000000811380000000000000000000000000000000000000000000000000000000000081139000000000000000000000000000000000000000000000000000000000008113a000000000000000000000000000000000000000000000000000000000008113b000000000000000000000000000000000000000000000000000000000008113c000000000000000000000000000000000000000000000000000000000008113d000000000000000000000000000000000000000000000000000000000008113e08003c0472260790b0bdfb8ae4dc4d437e7686b73643f2198970d84e1059a5f13500bfd46275a318e438726ff2765ae154b63ab8a0daebcbed668a5f58a0e63dc1007906b9418dc758c6b4f8454c69baa48b7889b6b511d707abe8e2cb8f7c397300aeb60c4d65a44f122e58bf9565dfe2024b3ae654d5cf2e47ecb035d53c927000bf82e8cda20345f37bbb1de3932172324b57f0b98be483392697b168e3bba8000fb4bbad884ef30edf68e45a6cf2733fcf50310c69d7c1432b29af2c0aa8040023e1622d27fee3b4a40ab975ae0eb2e31619ef3dc76eb858f7fddb6a056131004689cd7007daf98dd3218b839b8e6a29f957154347b391fdb376bd0b344be23f0000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000008200a0000000000000000000000000000000000000000000000000000000000082001000000000000000000000000000000000000000000000000000000000008200b0000000000000000000000000000000000000000000000000000000000082002000000000000000000000000000000000000000000000000000000000008200c0000000000000000000000000000000000000000000000000000000000082003000000000000000000000000000000000000000000000000000000000008200d0000000000000000000000000000000000000000000000000000000000082004000000000000000000000000000000000000000000000000000000000008200e0000000000000000000000000000000000000000000000000000000000082005000000000000000000000000000000000000000000000000000000000008200f00000000000000000000000000000000000000000000000000000000000820060000000000000000000000000000000000000000000000000000000000082010000000000000000000000000000000000000000000000000000000000008200700000000000000000000000000000000000000000000000000000000000820110000000000000000000000000000000000000000000000000000000000082008000000000000000000000000000000000000000000000000000000000008201200000000000000000000000000000000000000000000000000000000000820090000000000000000000000000000000000000000000000000000000000082013000000000000000000000000000000000000000000000000000000000008200a0000000000000000000000000000000000000000000000000000000000082014000000000000000000000000000000000000000000000000000000000008200b0000000000000000000000000000000000000000000000000000000000082015000000000000000000000000000000000000000000000000000000000008200c0000000000000000000000000000000000000000000000000000000000082016000000000000000000000000000000000000000000000000000000000008200d0000000000000000000000000000000000000000000000000000000000082017000000000000000000000000000000000000000000000000000000000008200e0000000000000000000000000000000000000000000000000000000000082018000000000000000000000000000000000000000000000000000000000008200f00000000000000000000000000000000000000000000000000000000000820190000000000000000000000000000000000000000000000000000000000082010000000000000000000000000000000000000000000000000000000000008201a0000000000000000000000000000000000000000000000000000000000082011000000000000000000000000000000000000000000000000000000000008201b0000000000000000000000000000000000000000000000000000000000082012000000000000000000000000000000000000000000000000000000000008201c0000000000000000000000000000000000000000000000000000000000082013000000000000000000000000000000000000000000000000000000000008201d0000000000000000000000000000000000000000000000000000000000082014000000000000000000000000000000000000000000000000000000000008201e0000000000000000000000000000000000000000000000000000000000082015000000000000000000000000000000000000000000000000000000000008201f00000000000000000000000000000000000000000000000000000000000820160000000000000000000000000000000000000000000000000000000000082020000000000000000000000000000000000000000000000000000000000008201700000000000000000000000000000000000000000000000000000000000820210000000000000000000000000000000000000000000000000000000000082018000000000000000000000000000000000000000000000000000000000008202200000000000000000000000000000000000000000000000000000000000820190000000000000000000000000000000000000000000000000000000000082023000000000000000000000000000000000000000000000000000000000008201a0000000000000000000000000000000000000000000000000000000000082024000000000000000000000000000000000000000000000000000000000008201b0000000000000000000000000000000000000000000000000000000000082025000000000000000000000000000000000000000000000000000000000008201c0000000000000000000000000000000000000000000000000000000000082026000000000000000000000000000000000000000000000000000000000008201d0000000000000000000000000000000000000000000000000000000000082027000000000000000000000000000000000000000000000000000000000008201e0000000000000000000000000000000000000000000000000000000000082028000000000000000000000000000000000000000000000000000000000008201f00000000000000000000000000000000000000000000000000000000000820290000000000000000000000000000000000000000000000000000000000082020000000000000000000000000000000000000000000000000000000000008202a0000000000000000000000000000000000000000000000000000000000082021000000000000000000000000000000000000000000000000000000000008202b0000000000000000000000000000000000000000000000000000000000082022000000000000000000000000000000000000000000000000000000000008202c0000000000000000000000000000000000000000000000000000000000082023000000000000000000000000000000000000000000000000000000000008202d0000000000000000000000000000000000000000000000000000000000082024000000000000000000000000000000000000000000000000000000000008202e0000000000000000000000000000000000000000000000000000000000082025000000000000000000000000000000000000000000000000000000000008202f00000000000000000000000000000000000000000000000000000000000820260000000000000000000000000000000000000000000000000000000000082030000000000000000000000000000000000000000000000000000000000008202700000000000000000000000000000000000000000000000000000000000820310000000000000000000000000000000000000000000000000000000000082028000000000000000000000000000000000000000000000000000000000008203200000000000000000000000000000000000000000000000000000000000820290000000000000000000000000000000000000000000000000000000000082033000000000000000000000000000000000000000000000000000000000008202a0000000000000000000000000000000000000000000000000000000000082034000000000000000000000000000000000000000000000000000000000008202b0000000000000000000000000000000000000000000000000000000000082035000000000000000000000000000000000000000000000000000000000008202c0000000000000000000000000000000000000000000000000000000000082036000000000000000000000000000000000000000000000000000000000008202d0000000000000000000000000000000000000000000000000000000000082037000000000000000000000000000000000000000000000000000000000008202e0000000000000000000000000000000000000000000000000000000000082038000000000000000000000000000000000000000000000000000000000008202f00000000000000000000000000000000000000000000000000000000000820390000000000000000000000000000000000000000000000000000000000082030000000000000000000000000000000000000000000000000000000000008203a0000000000000000000000000000000000000000000000000000000000082031000000000000000000000000000000000000000000000000000000000008203b0000000000000000000000000000000000000000000000000000000000082032000000000000000000000000000000000000000000000000000000000008203c0000000000000000000000000000000000000000000000000000000000082033000000000000000000000000000000000000000000000000000000000008203d0000000000000000000000000000000000000000000000000000000000082034000000000000000000000000000000000000000000000000000000000008203e0000000000000000000000000000000000000000000000000000000000082035000000000000000000000000000000000000000000000000000000000008203f00000000000000000000000000000000000000000000000000000000000820360000000000000000000000000000000000000000000000000000000000082040000000000000000000000000000000000000000000000000000000000008203700000000000000000000000000000000000000000000000000000000000820410000000000000000000000000000000000000000000000000000000000082038000000000000000000000000000000000000000000000000000000000008204200000000000000000000000000000000000000000000000000000000000820390000000000000000000000000000000000000000000000000000000000082043000000000000000000000000000000000000000000000000000000000008203a0000000000000000000000000000000000000000000000000000000000082044000000000000000000000000000000000000000000000000000000000008203b0000000000000000000000000000000000000000000000000000000000082045000000000000000000000000000000000000000000000000000000000008203c0000000000000000000000000000000000000000000000000000000000082046000000000000000000000000000000000000000000000000000000000008203d0000000000000000000000000000000000000000000000000000000000082047000000000000000000000000000000000000000000000000000000000008203e00000000000000000000000000000000000000000000000000000000000820480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000c100100000000000000000000000000000000000000000000000000000000000c100200000000000000000000000000000000000000000000000000000000000c100300000000000000000000000000000000000000000000000000000000000c100400000000000000000000000000000000000000000000000000000000000c100500000000000000000000000000000000000000000000000000000000000c100600000000000000000000000000000000000000000000000000000000000c100700000000000000000000000000000000000000000000000000000000000c100800000000000000000000000000000000000000000000000000000000000c100900000000000000000000000000000000000000000000000000000000000c100a00000000000000000000000000000000000000000000000000000000000c100b00000000000000000000000000000000000000000000000000000000000c100c00000000000000000000000000000000000000000000000000000000000c100d00000000000000000000000000000000000000000000000000000000000c100e00000000000000000000000000000000000000000000000000000000000c100f00000000000000000000000000000000000000000000000000000000000c101000000000000000000000000000000000000000000000000000000000000c101100000000000000000000000000000000000000000000000000000000000c101200000000000000000000000000000000000000000000000000000000000c101300000000000000000000000000000000000000000000000000000000000c101400000000000000000000000000000000000000000000000000000000000c101500000000000000000000000000000000000000000000000000000000000c101600000000000000000000000000000000000000000000000000000000000c101700000000000000000000000000000000000000000000000000000000000c101800000000000000000000000000000000000000000000000000000000000c101900000000000000000000000000000000000000000000000000000000000c101a00000000000000000000000000000000000000000000000000000000000c101b00000000000000000000000000000000000000000000000000000000000c101c00000000000000000000000000000000000000000000000000000000000c101d00000000000000000000000000000000000000000000000000000000000c101e00000000000000000000000000000000000000000000000000000000000c101f00000000000000000000000000000000000000000000000000000000000c102000000000000000000000000000000000000000000000000000000000000c102100000000000000000000000000000000000000000000000000000000000c102200000000000000000000000000000000000000000000000000000000000c102300000000000000000000000000000000000000000000000000000000000c102400000000000000000000000000000000000000000000000000000000000c102500000000000000000000000000000000000000000000000000000000000c102600000000000000000000000000000000000000000000000000000000000c102700000000000000000000000000000000000000000000000000000000000c102800000000000000000000000000000000000000000000000000000000000c102900000000000000000000000000000000000000000000000000000000000c102a00000000000000000000000000000000000000000000000000000000000c102b00000000000000000000000000000000000000000000000000000000000c102c00000000000000000000000000000000000000000000000000000000000c102d00000000000000000000000000000000000000000000000000000000000c102e00000000000000000000000000000000000000000000000000000000000c102f00000000000000000000000000000000000000000000000000000000000c103000000000000000000000000000000000000000000000000000000000000c103100000000000000000000000000000000000000000000000000000000000c103200000000000000000000000000000000000000000000000000000000000c103300000000000000000000000000000000000000000000000000000000000c103400000000000000000000000000000000000000000000000000000000000c103500000000000000000000000000000000000000000000000000000000000c103600000000000000000000000000000000000000000000000000000000000c103700000000000000000000000000000000000000000000000000000000000c103800000000000000000000000000000000000000000000000000000000000c103900000000000000000000000000000000000000000000000000000000000c103a00000000000000000000000000000000000000000000000000000000000c103b00000000000000000000000000000000000000000000000000000000000c103c00000000000000000000000000000000000000000000000000000000000c103d00000000000000000000000000000000000000000000000000000000000c103e00000000000000000000000000000000000000000000000000000000000c103f3f00000000000000000000000000000000000000000000000000000000000c110000000000000000000000000000000000000000000000000000000000000c110100000000000000000000000000000000000000000000000000000000000c110200000000000000000000000000000000000000000000000000000000000c110300000000000000000000000000000000000000000000000000000000000c110400000000000000000000000000000000000000000000000000000000000c110500000000000000000000000000000000000000000000000000000000000c110600000000000000000000000000000000000000000000000000000000000c110700000000000000000000000000000000000000000000000000000000000c110800000000000000000000000000000000000000000000000000000000000c110900000000000000000000000000000000000000000000000000000000000c110a00000000000000000000000000000000000000000000000000000000000c110b00000000000000000000000000000000000000000000000000000000000c110c00000000000000000000000000000000000000000000000000000000000c110d00000000000000000000000000000000000000000000000000000000000c110e00000000000000000000000000000000000000000000000000000000000c110f00000000000000000000000000000000000000000000000000000000000c111000000000000000000000000000000000000000000000000000000000000c111100000000000000000000000000000000000000000000000000000000000c111200000000000000000000000000000000000000000000000000000000000c111300000000000000000000000000000000000000000000000000000000000c111400000000000000000000000000000000000000000000000000000000000c111500000000000000000000000000000000000000000000000000000000000c111600000000000000000000000000000000000000000000000000000000000c111700000000000000000000000000000000000000000000000000000000000c111800000000000000000000000000000000000000000000000000000000000c111900000000000000000000000000000000000000000000000000000000000c111a00000000000000000000000000000000000000000000000000000000000c111b00000000000000000000000000000000000000000000000000000000000c111c00000000000000000000000000000000000000000000000000000000000c111d00000000000000000000000000000000000000000000000000000000000c111e00000000000000000000000000000000000000000000000000000000000c111f00000000000000000000000000000000000000000000000000000000000c112000000000000000000000000000000000000000000000000000000000000c112100000000000000000000000000000000000000000000000000000000000c112200000000000000000000000000000000000000000000000000000000000c112300000000000000000000000000000000000000000000000000000000000c112400000000000000000000000000000000000000000000000000000000000c112500000000000000000000000000000000000000000000000000000000000c112600000000000000000000000000000000000000000000000000000000000c112700000000000000000000000000000000000000000000000000000000000c112800000000000000000000000000000000000000000000000000000000000c112900000000000000000000000000000000000000000000000000000000000c112a00000000000000000000000000000000000000000000000000000000000c112b00000000000000000000000000000000000000000000000000000000000c112c00000000000000000000000000000000000000000000000000000000000c112d00000000000000000000000000000000000000000000000000000000000c112e00000000000000000000000000000000000000000000000000000000000c112f00000000000000000000000000000000000000000000000000000000000c113000000000000000000000000000000000000000000000000000000000000c113100000000000000000000000000000000000000000000000000000000000c113200000000000000000000000000000000000000000000000000000000000c113300000000000000000000000000000000000000000000000000000000000c113400000000000000000000000000000000000000000000000000000000000c113500000000000000000000000000000000000000000000000000000000000c113600000000000000000000000000000000000000000000000000000000000c113700000000000000000000000000000000000000000000000000000000000c113800000000000000000000000000000000000000000000000000000000000c113900000000000000000000000000000000000000000000000000000000000c113a00000000000000000000000000000000000000000000000000000000000c113b00000000000000000000000000000000000000000000000000000000000c113c00000000000000000000000000000000000000000000000000000000000c113d00000000000000000000000000000000000000000000000000000000000c113e0800f8029be42ec3f25204907ca981fb71e5b357093eb5db10fc01ca98a4e4154c0030e13d351a5bf1d5a040e82a163ca57017f39162693f85c571e441e36d702d00a550ae0f39f977d9473d6de1be3232fc68ed0c4a601d53542148695102cfc9005580bc65e4bff9c8fffa64db02c0fa6af14d9d26fd962f4c5904cbd3ddec2500758c4a0d43dfec788b2f580877c4f473adec8f168ea24424f2600e4eb4916f00342602bf90d10f8ca8e582a894dcc4c02bb89fe458532e0c632b53bae54b4d00ca43ab78ab834337e9964d84a0674c9adabdca140539c5a6bc96e0ba9a51f6004ffbfd91be292a7c6a0e255e50caa156ac2d628b40ad2128c4ab63a92d8a1c3f00000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c200a00000000000000000000000000000000000000000000000000000000000c200100000000000000000000000000000000000000000000000000000000000c200b00000000000000000000000000000000000000000000000000000000000c200200000000000000000000000000000000000000000000000000000000000c200c00000000000000000000000000000000000000000000000000000000000c200300000000000000000000000000000000000000000000000000000000000c200d00000000000000000000000000000000000000000000000000000000000c200400000000000000000000000000000000000000000000000000000000000c200e00000000000000000000000000000000000000000000000000000000000c200500000000000000000000000000000000000000000000000000000000000c200f00000000000000000000000000000000000000000000000000000000000c200600000000000000000000000000000000000000000000000000000000000c201000000000000000000000000000000000000000000000000000000000000c200700000000000000000000000000000000000000000000000000000000000c201100000000000000000000000000000000000000000000000000000000000c200800000000000000000000000000000000000000000000000000000000000c201200000000000000000000000000000000000000000000000000000000000c200900000000000000000000000000000000000000000000000000000000000c201300000000000000000000000000000000000000000000000000000000000c200a00000000000000000000000000000000000000000000000000000000000c201400000000000000000000000000000000000000000000000000000000000c200b00000000000000000000000000000000000000000000000000000000000c201500000000000000000000000000000000000000000000000000000000000c200c00000000000000000000000000000000000000000000000000000000000c201600000000000000000000000000000000000000000000000000000000000c200d00000000000000000000000000000000000000000000000000000000000c201700000000000000000000000000000000000000000000000000000000000c200e00000000000000000000000000000000000000000000000000000000000c201800000000000000000000000000000000000000000000000000000000000c200f00000000000000000000000000000000000000000000000000000000000c201900000000000000000000000000000000000000000000000000000000000c201000000000000000000000000000000000000000000000000000000000000c201a00000000000000000000000000000000000000000000000000000000000c201100000000000000000000000000000000000000000000000000000000000c201b00000000000000000000000000000000000000000000000000000000000c201200000000000000000000000000000000000000000000000000000000000c201c00000000000000000000000000000000000000000000000000000000000c201300000000000000000000000000000000000000000000000000000000000c201d00000000000000000000000000000000000000000000000000000000000c201400000000000000000000000000000000000000000000000000000000000c201e00000000000000000000000000000000000000000000000000000000000c201500000000000000000000000000000000000000000000000000000000000c201f00000000000000000000000000000000000000000000000000000000000c201600000000000000000000000000000000000000000000000000000000000c202000000000000000000000000000000000000000000000000000000000000c201700000000000000000000000000000000000000000000000000000000000c202100000000000000000000000000000000000000000000000000000000000c201800000000000000000000000000000000000000000000000000000000000c202200000000000000000000000000000000000000000000000000000000000c201900000000000000000000000000000000000000000000000000000000000c202300000000000000000000000000000000000000000000000000000000000c201a00000000000000000000000000000000000000000000000000000000000c202400000000000000000000000000000000000000000000000000000000000c201b00000000000000000000000000000000000000000000000000000000000c202500000000000000000000000000000000000000000000000000000000000c201c00000000000000000000000000000000000000000000000000000000000c202600000000000000000000000000000000000000000000000000000000000c201d00000000000000000000000000000000000000000000000000000000000c202700000000000000000000000000000000000000000000000000000000000c201e00000000000000000000000000000000000000000000000000000000000c202800000000000000000000000000000000000000000000000000000000000c201f00000000000000000000000000000000000000000000000000000000000c202900000000000000000000000000000000000000000000000000000000000c202000000000000000000000000000000000000000000000000000000000000c202a00000000000000000000000000000000000000000000000000000000000c202100000000000000000000000000000000000000000000000000000000000c202b00000000000000000000000000000000000000000000000000000000000c202200000000000000000000000000000000000000000000000000000000000c202c00000000000000000000000000000000000000000000000000000000000c202300000000000000000000000000000000000000000000000000000000000c202d00000000000000000000000000000000000000000000000000000000000c202400000000000000000000000000000000000000000000000000000000000c202e00000000000000000000000000000000000000000000000000000000000c202500000000000000000000000000000000000000000000000000000000000c202f00000000000000000000000000000000000000000000000000000000000c202600000000000000000000000000000000000000000000000000000000000c203000000000000000000000000000000000000000000000000000000000000c202700000000000000000000000000000000000000000000000000000000000c203100000000000000000000000000000000000000000000000000000000000c202800000000000000000000000000000000000000000000000000000000000c203200000000000000000000000000000000000000000000000000000000000c202900000000000000000000000000000000000000000000000000000000000c203300000000000000000000000000000000000000000000000000000000000c202a00000000000000000000000000000000000000000000000000000000000c203400000000000000000000000000000000000000000000000000000000000c202b00000000000000000000000000000000000000000000000000000000000c203500000000000000000000000000000000000000000000000000000000000c202c00000000000000000000000000000000000000000000000000000000000c203600000000000000000000000000000000000000000000000000000000000c202d00000000000000000000000000000000000000000000000000000000000c203700000000000000000000000000000000000000000000000000000000000c202e00000000000000000000000000000000000000000000000000000000000c203800000000000000000000000000000000000000000000000000000000000c202f00000000000000000000000000000000000000000000000000000000000c203900000000000000000000000000000000000000000000000000000000000c203000000000000000000000000000000000000000000000000000000000000c203a00000000000000000000000000000000000000000000000000000000000c203100000000000000000000000000000000000000000000000000000000000c203b00000000000000000000000000000000000000000000000000000000000c203200000000000000000000000000000000000000000000000000000000000c203c00000000000000000000000000000000000000000000000000000000000c203300000000000000000000000000000000000000000000000000000000000c203d00000000000000000000000000000000000000000000000000000000000c203400000000000000000000000000000000000000000000000000000000000c203e00000000000000000000000000000000000000000000000000000000000c203500000000000000000000000000000000000000000000000000000000000c203f00000000000000000000000000000000000000000000000000000000000c203600000000000000000000000000000000000000000000000000000000000c204000000000000000000000000000000000000000000000000000000000000c203700000000000000000000000000000000000000000000000000000000000c204100000000000000000000000000000000000000000000000000000000000c203800000000000000000000000000000000000000000000000000000000000c204200000000000000000000000000000000000000000000000000000000000c203900000000000000000000000000000000000000000000000000000000000c204300000000000000000000000000000000000000000000000000000000000c203a00000000000000000000000000000000000000000000000000000000000c204400000000000000000000000000000000000000000000000000000000000c203b00000000000000000000000000000000000000000000000000000000000c204500000000000000000000000000000000000000000000000000000000000c203c00000000000000000000000000000000000000000000000000000000000c204600000000000000000000000000000000000000000000000000000000000c203d00000000000000000000000000000000000000000000000000000000000c204700000000000000000000000000000000000000000000000000000000000c203e00000000000000000000000000000000000000000000000000000000000c2048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000101000000000000000000000000000000000000000000000000000000000000010100100000000000000000000000000000000000000000000000000000000001010020000000000000000000000000000000000000000000000000000000000101003000000000000000000000000000000000000000000000000000000000010100400000000000000000000000000000000000000000000000000000000001010050000000000000000000000000000000000000000000000000000000000101006000000000000000000000000000000000000000000000000000000000010100700000000000000000000000000000000000000000000000000000000001010080000000000000000000000000000000000000000000000000000000000101009000000000000000000000000000000000000000000000000000000000010100a000000000000000000000000000000000000000000000000000000000010100b000000000000000000000000000000000000000000000000000000000010100c000000000000000000000000000000000000000000000000000000000010100d000000000000000000000000000000000000000000000000000000000010100e000000000000000000000000000000000000000000000000000000000010100f0000000000000000000000000000000000000000000000000000000000101010000000000000000000000000000000000000000000000000000000000010101100000000000000000000000000000000000000000000000000000000001010120000000000000000000000000000000000000000000000000000000000101013000000000000000000000000000000000000000000000000000000000010101400000000000000000000000000000000000000000000000000000000001010150000000000000000000000000000000000000000000000000000000000101016000000000000000000000000000000000000000000000000000000000010101700000000000000000000000000000000000000000000000000000000001010180000000000000000000000000000000000000000000000000000000000101019000000000000000000000000000000000000000000000000000000000010101a000000000000000000000000000000000000000000000000000000000010101b000000000000000000000000000000000000000000000000000000000010101c000000000000000000000000000000000000000000000000000000000010101d000000000000000000000000000000000000000000000000000000000010101e000000000000000000000000000000000000000000000000000000000010101f0000000000000000000000000000000000000000000000000000000000101020000000000000000000000000000000000000000000000000000000000010102100000000000000000000000000000000000000000000000000000000001010220000000000000000000000000000000000000000000000000000000000101023000000000000000000000000000000000000000000000000000000000010102400000000000000000000000000000000000000000000000000000000001010250000000000000000000000000000000000000000000000000000000000101026000000000000000000000000000000000000000000000000000000000010102700000000000000000000000000000000000000000000000000000000001010280000000000000000000000000000000000000000000000000000000000101029000000000000000000000000000000000000000000000000000000000010102a000000000000000000000000000000000000000000000000000000000010102b000000000000000000000000000000000000000000000000000000000010102c000000000000000000000000000000000000000000000000000000000010102d000000000000000000000000000000000000000000000000000000000010102e000000000000000000000000000000000000000000000000000000000010102f0000000000000000000000000000000000000000000000000000000000101030000000000000000000000000000000000000000000000000000000000010103100000000000000000000000000000000000000000000000000000000001010320000000000000000000000000000000000000000000000000000000000101033000000000000000000000000000000000000000000000000000000000010103400000000000000000000000000000000000000000000000000000000001010350000000000000000000000000000000000000000000000000000000000101036000000000000000000000000000000000000000000000000000000000010103700000000000000000000000000000000000000000000000000000000001010380000000000000000000000000000000000000000000000000000000000101039000000000000000000000000000000000000000000000000000000000010103a000000000000000000000000000000000000000000000000000000000010103b000000000000000000000000000000000000000000000000000000000010103c000000000000000000000000000000000000000000000000000000000010103d000000000000000000000000000000000000000000000000000000000010103e000000000000000000000000000000000000000000000000000000000010103f3f0000000000000000000000000000000000000000000000000000000000101100000000000000000000000000000000000000000000000000000000000010110100000000000000000000000000000000000000000000000000000000001011020000000000000000000000000000000000000000000000000000000000101103000000000000000000000000000000000000000000000000000000000010110400000000000000000000000000000000000000000000000000000000001011050000000000000000000000000000000000000000000000000000000000101106000000000000000000000000000000000000000000000000000000000010110700000000000000000000000000000000000000000000000000000000001011080000000000000000000000000000000000000000000000000000000000101109000000000000000000000000000000000000000000000000000000000010110a000000000000000000000000000000000000000000000000000000000010110b000000000000000000000000000000000000000000000000000000000010110c000000000000000000000000000000000000000000000000000000000010110d000000000000000000000000000000000000000000000000000000000010110e000000000000000000000000000000000000000000000000000000000010110f0000000000000000000000000000000000000000000000000000000000101110000000000000000000000000000000000000000000000000000000000010111100000000000000000000000000000000000000000000000000000000001011120000000000000000000000000000000000000000000000000000000000101113000000000000000000000000000000000000000000000000000000000010111400000000000000000000000000000000000000000000000000000000001011150000000000000000000000000000000000000000000000000000000000101116000000000000000000000000000000000000000000000000000000000010111700000000000000000000000000000000000000000000000000000000001011180000000000000000000000000000000000000000000000000000000000101119000000000000000000000000000000000000000000000000000000000010111a000000000000000000000000000000000000000000000000000000000010111b000000000000000000000000000000000000000000000000000000000010111c000000000000000000000000000000000000000000000000000000000010111d000000000000000000000000000000000000000000000000000000000010111e000000000000000000000000000000000000000000000000000000000010111f0000000000000000000000000000000000000000000000000000000000101120000000000000000000000000000000000000000000000000000000000010112100000000000000000000000000000000000000000000000000000000001011220000000000000000000000000000000000000000000000000000000000101123000000000000000000000000000000000000000000000000000000000010112400000000000000000000000000000000000000000000000000000000001011250000000000000000000000000000000000000000000000000000000000101126000000000000000000000000000000000000000000000000000000000010112700000000000000000000000000000000000000000000000000000000001011280000000000000000000000000000000000000000000000000000000000101129000000000000000000000000000000000000000000000000000000000010112a000000000000000000000000000000000000000000000000000000000010112b000000000000000000000000000000000000000000000000000000000010112c000000000000000000000000000000000000000000000000000000000010112d000000000000000000000000000000000000000000000000000000000010112e000000000000000000000000000000000000000000000000000000000010112f0000000000000000000000000000000000000000000000000000000000101130000000000000000000000000000000000000000000000000000000000010113100000000000000000000000000000000000000000000000000000000001011320000000000000000000000000000000000000000000000000000000000101133000000000000000000000000000000000000000000000000000000000010113400000000000000000000000000000000000000000000000000000000001011350000000000000000000000000000000000000000000000000000000000101136000000000000000000000000000000000000000000000000000000000010113700000000000000000000000000000000000000000000000000000000001011380000000000000000000000000000000000000000000000000000000000101139000000000000000000000000000000000000000000000000000000000010113a000000000000000000000000000000000000000000000000000000000010113b000000000000000000000000000000000000000000000000000000000010113c000000000000000000000000000000000000000000000000000000000010113d000000000000000000000000000000000000000000000000000000000010113e080099145b6c0d32753835121f8b271186d01236948a4622ce78a98347fcfc98390085277a27c6acbd5ffc4c19cd65fc30056999e9bec36998f753132db0ff8e2300f3cf77a7261759ebd5f4149f6ad56746f4499cfcd4adf27a1d373f77da64d5009bc6e0e994a23cde8c95b90c1acc1b4a480c6599d1df2c3f9f6e76f3d1aff200d7a1c4a2700dacaaf07f1f0ff33837bdbabcf0b9ace17efabe0761708c4bb900dbeb8e96d14f21e57d5786b6d6ae7e5ddb1bb35935c0fb246d4bdbca62e02c00fbf12b5e0df6223b801088798e4e04d2a92ffe9a11639b7f0ce314e3412a8000d796e0724de03b796ba77069fcd6cf921e566f3aed15eb3e77258add74e9ff3f0000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010200a0000000000000000000000000000000000000000000000000000000000102001000000000000000000000000000000000000000000000000000000000010200b0000000000000000000000000000000000000000000000000000000000102002000000000000000000000000000000000000000000000000000000000010200c0000000000000000000000000000000000000000000000000000000000102003000000000000000000000000000000000000000000000000000000000010200d0000000000000000000000000000000000000000000000000000000000102004000000000000000000000000000000000000000000000000000000000010200e0000000000000000000000000000000000000000000000000000000000102005000000000000000000000000000000000000000000000000000000000010200f00000000000000000000000000000000000000000000000000000000001020060000000000000000000000000000000000000000000000000000000000102010000000000000000000000000000000000000000000000000000000000010200700000000000000000000000000000000000000000000000000000000001020110000000000000000000000000000000000000000000000000000000000102008000000000000000000000000000000000000000000000000000000000010201200000000000000000000000000000000000000000000000000000000001020090000000000000000000000000000000000000000000000000000000000102013000000000000000000000000000000000000000000000000000000000010200a0000000000000000000000000000000000000000000000000000000000102014000000000000000000000000000000000000000000000000000000000010200b0000000000000000000000000000000000000000000000000000000000102015000000000000000000000000000000000000000000000000000000000010200c0000000000000000000000000000000000000000000000000000000000102016000000000000000000000000000000000000000000000000000000000010200d0000000000000000000000000000000000000000000000000000000000102017000000000000000000000000000000000000000000000000000000000010200e0000000000000000000000000000000000000000000000000000000000102018000000000000000000000000000000000000000000000000000000000010200f00000000000000000000000000000000000000000000000000000000001020190000000000000000000000000000000000000000000000000000000000102010000000000000000000000000000000000000000000000000000000000010201a0000000000000000000000000000000000000000000000000000000000102011000000000000000000000000000000000000000000000000000000000010201b0000000000000000000000000000000000000000000000000000000000102012000000000000000000000000000000000000000000000000000000000010201c0000000000000000000000000000000000000000000000000000000000102013000000000000000000000000000000000000000000000000000000000010201d0000000000000000000000000000000000000000000000000000000000102014000000000000000000000000000000000000000000000000000000000010201e0000000000000000000000000000000000000000000000000000000000102015000000000000000000000000000000000000000000000000000000000010201f00000000000000000000000000000000000000000000000000000000001020160000000000000000000000000000000000000000000000000000000000102020000000000000000000000000000000000000000000000000000000000010201700000000000000000000000000000000000000000000000000000000001020210000000000000000000000000000000000000000000000000000000000102018000000000000000000000000000000000000000000000000000000000010202200000000000000000000000000000000000000000000000000000000001020190000000000000000000000000000000000000000000000000000000000102023000000000000000000000000000000000000000000000000000000000010201a0000000000000000000000000000000000000000000000000000000000102024000000000000000000000000000000000000000000000000000000000010201b0000000000000000000000000000000000000000000000000000000000102025000000000000000000000000000000000000000000000000000000000010201c0000000000000000000000000000000000000000000000000000000000102026000000000000000000000000000000000000000000000000000000000010201d0000000000000000000000000000000000000000000000000000000000102027000000000000000000000000000000000000000000000000000000000010201e0000000000000000000000000000000000000000000000000000000000102028000000000000000000000000000000000000000000000000000000000010201f00000000000000000000000000000000000000000000000000000000001020290000000000000000000000000000000000000000000000000000000000102020000000000000000000000000000000000000000000000000000000000010202a0000000000000000000000000000000000000000000000000000000000102021000000000000000000000000000000000000000000000000000000000010202b0000000000000000000000000000000000000000000000000000000000102022000000000000000000000000000000000000000000000000000000000010202c0000000000000000000000000000000000000000000000000000000000102023000000000000000000000000000000000000000000000000000000000010202d0000000000000000000000000000000000000000000000000000000000102024000000000000000000000000000000000000000000000000000000000010202e0000000000000000000000000000000000000000000000000000000000102025000000000000000000000000000000000000000000000000000000000010202f00000000000000000000000000000000000000000000000000000000001020260000000000000000000000000000000000000000000000000000000000102030000000000000000000000000000000000000000000000000000000000010202700000000000000000000000000000000000000000000000000000000001020310000000000000000000000000000000000000000000000000000000000102028000000000000000000000000000000000000000000000000000000000010203200000000000000000000000000000000000000000000000000000000001020290000000000000000000000000000000000000000000000000000000000102033000000000000000000000000000000000000000000000000000000000010202a0000000000000000000000000000000000000000000000000000000000102034000000000000000000000000000000000000000000000000000000000010202b0000000000000000000000000000000000000000000000000000000000102035000000000000000000000000000000000000000000000000000000000010202c0000000000000000000000000000000000000000000000000000000000102036000000000000000000000000000000000000000000000000000000000010202d0000000000000000000000000000000000000000000000000000000000102037000000000000000000000000000000000000000000000000000000000010202e0000000000000000000000000000000000000000000000000000000000102038000000000000000000000000000000000000000000000000000000000010202f00000000000000000000000000000000000000000000000000000000001020390000000000000000000000000000000000000000000000000000000000102030000000000000000000000000000000000000000000000000000000000010203a0000000000000000000000000000000000000000000000000000000000102031000000000000000000000000000000000000000000000000000000000010203b0000000000000000000000000000000000000000000000000000000000102032000000000000000000000000000000000000000000000000000000000010203c0000000000000000000000000000000000000000000000000000000000102033000000000000000000000000000000000000000000000000000000000010203d0000000000000000000000000000000000000000000000000000000000102034000000000000000000000000000000000000000000000000000000000010203e0000000000000000000000000000000000000000000000000000000000102035000000000000000000000000000000000000000000000000000000000010203f00000000000000000000000000000000000000000000000000000000001020360000000000000000000000000000000000000000000000000000000000102040000000000000000000000000000000000000000000000000000000000010203700000000000000000000000000000000000000000000000000000000001020410000000000000000000000000000000000000000000000000000000000102038000000000000000000000000000000000000000000000000000000000010204200000000000000000000000000000000000000000000000000000000001020390000000000000000000000000000000000000000000000000000000000102043000000000000000000000000000000000000000000000000000000000010203a0000000000000000000000000000000000000000000000000000000000102044000000000000000000000000000000000000000000000000000000000010203b0000000000000000000000000000000000000000000000000000000000102045000000000000000000000000000000000000000000000000000000000010203c0000000000000000000000000000000000000000000000000000000000102046000000000000000000000000000000000000000000000000000000000010203d0000000000000000000000000000000000000000000000000000000000102047000000000000000000000000000000000000000000000000000000000010203e0000000000000000000000000000000000000000000000000000000000102048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "txsEffectsHash": "0x00db66b36b24ebccb7543a74620018056cad2f0b08eaf251ad00362551f0a2d0", "decodedHeader": { "contentCommitment": { "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x000ca4a4610ad22c97c9161cedcf01faa3619f1b85457f1627d09627b71903a6", "numTxs": 4, - "txsEffectsHash": "0x007b27babdf78c8beb8d7a937731158a4422309edacfeb6e2b9c9125a01617a2" + "txsEffectsHash": "0x00db66b36b24ebccb7543a74620018056cad2f0b08eaf251ad00362551f0a2d0" }, "globalVariables": { "blockNumber": 1, "slotNumber": "0x000000000000000000000000000000000000000000000000000000000000001a", "chainId": 31337, - "timestamp": 1731106419, + "timestamp": 1731434005, "version": 1, - "coinbase": "0xe1b76c7e0eb80841fed024c0470d663250bdd96e", - "feeRecipient": "0x1f1730e56d57b24d909d5eae3094c83900c3fb2fa90e248dfddb825f2e4e55e8", + "coinbase": "0xa8f1a4313bc15dcd3681ed2b6fdd042f1ee1f823", + "feeRecipient": "0x2abdc96d2ec8465dfd2bb7401f90dd3af0db16c3cece57bd5de2b63a3d25140b", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -107,8 +107,8 @@ } } }, - "header": "0x2a05cb8aeefe9b9797f90650eae072f5ab7437807e62f9724ce1900467779860000000010000000000000000000000000000000000000000000000000000000000000004007b27babdf78c8beb8d7a937731158a4422309edacfeb6e2b9c9125a01617a200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c000ca4a4610ad22c97c9161cedcf01faa3619f1b85457f1627d09627b71903a62e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d60000001000553ea03210e12bf95ed15f0105108f39db784d318cfe9b52cba413618711ce000001001d52eeaaacb445d9193d29e0df8f0ad4bf69bc457fe955b8e05b48ae3fdc3b3f00000180160cf8d0dbcc7b6a69aede9d89adb66554ba8054d9944b6ab5475e155e8f73d4000001800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000672e9673e1b76c7e0eb80841fed024c0470d663250bdd96e1f1730e56d57b24d909d5eae3094c83900c3fb2fa90e248dfddb825f2e4e55e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x001e9220ab6b62c63ad3086a8a6c9dadffb229804bc6dac30e26403158f02810", + "header": "0x2a05cb8aeefe9b9797f90650eae072f5ab7437807e62f9724ce190046777986000000001000000000000000000000000000000000000000000000000000000000000000400db66b36b24ebccb7543a74620018056cad2f0b08eaf251ad00362551f0a2d000089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c000ca4a4610ad22c97c9161cedcf01faa3619f1b85457f1627d09627b71903a62e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d60000001000553ea03210e12bf95ed15f0105108f39db784d318cfe9b52cba413618711ce000001001d52eeaaacb445d9193d29e0df8f0ad4bf69bc457fe955b8e05b48ae3fdc3b3f00000180160cf8d0dbcc7b6a69aede9d89adb66554ba8054d9944b6ab5475e155e8f73d4000001800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000067339615a8f1a4313bc15dcd3681ed2b6fdd042f1ee1f8232abdc96d2ec8465dfd2bb7401f90dd3af0db16c3cece57bd5de2b63a3d25140b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x0058fc697c9471ef94446a35f46a068633d057596164ddf20e6152f6fac19f81", "numTxs": 4 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_2.json b/l1-contracts/test/fixtures/mixed_block_2.json index 0d26ec05a3c..1a84a75aa31 100644 --- a/l1-contracts/test/fixtures/mixed_block_2.json +++ b/l1-contracts/test/fixtures/mixed_block_2.json @@ -90,25 +90,25 @@ ] }, "block": { - "archive": "0x2ab4164ad9e20771c61fc7d9e2b1cbb2c1e02c6d050503d8d448e2bff77e56d3", - "blockHash": "0x1d3a51cdc172aa1d96a4f371c1673882cde1c0e6ecd26cc017b06dd433ea4c5b", - "body": "0x00000008000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000004100100000000000000000000000000000000000000000000000000000000000410020000000000000000000000000000000000000000000000000000000000041003000000000000000000000000000000000000000000000000000000000004100400000000000000000000000000000000000000000000000000000000000410050000000000000000000000000000000000000000000000000000000000041006000000000000000000000000000000000000000000000000000000000004100700000000000000000000000000000000000000000000000000000000000410080000000000000000000000000000000000000000000000000000000000041009000000000000000000000000000000000000000000000000000000000004100a000000000000000000000000000000000000000000000000000000000004100b000000000000000000000000000000000000000000000000000000000004100c000000000000000000000000000000000000000000000000000000000004100d000000000000000000000000000000000000000000000000000000000004100e000000000000000000000000000000000000000000000000000000000004100f0000000000000000000000000000000000000000000000000000000000041010000000000000000000000000000000000000000000000000000000000004101100000000000000000000000000000000000000000000000000000000000410120000000000000000000000000000000000000000000000000000000000041013000000000000000000000000000000000000000000000000000000000004101400000000000000000000000000000000000000000000000000000000000410150000000000000000000000000000000000000000000000000000000000041016000000000000000000000000000000000000000000000000000000000004101700000000000000000000000000000000000000000000000000000000000410180000000000000000000000000000000000000000000000000000000000041019000000000000000000000000000000000000000000000000000000000004101a000000000000000000000000000000000000000000000000000000000004101b000000000000000000000000000000000000000000000000000000000004101c000000000000000000000000000000000000000000000000000000000004101d000000000000000000000000000000000000000000000000000000000004101e000000000000000000000000000000000000000000000000000000000004101f0000000000000000000000000000000000000000000000000000000000041020000000000000000000000000000000000000000000000000000000000004102100000000000000000000000000000000000000000000000000000000000410220000000000000000000000000000000000000000000000000000000000041023000000000000000000000000000000000000000000000000000000000004102400000000000000000000000000000000000000000000000000000000000410250000000000000000000000000000000000000000000000000000000000041026000000000000000000000000000000000000000000000000000000000004102700000000000000000000000000000000000000000000000000000000000410280000000000000000000000000000000000000000000000000000000000041029000000000000000000000000000000000000000000000000000000000004102a000000000000000000000000000000000000000000000000000000000004102b000000000000000000000000000000000000000000000000000000000004102c000000000000000000000000000000000000000000000000000000000004102d000000000000000000000000000000000000000000000000000000000004102e000000000000000000000000000000000000000000000000000000000004102f0000000000000000000000000000000000000000000000000000000000041030000000000000000000000000000000000000000000000000000000000004103100000000000000000000000000000000000000000000000000000000000410320000000000000000000000000000000000000000000000000000000000041033000000000000000000000000000000000000000000000000000000000004103400000000000000000000000000000000000000000000000000000000000410350000000000000000000000000000000000000000000000000000000000041036000000000000000000000000000000000000000000000000000000000004103700000000000000000000000000000000000000000000000000000000000410380000000000000000000000000000000000000000000000000000000000041039000000000000000000000000000000000000000000000000000000000004103a000000000000000000000000000000000000000000000000000000000004103b000000000000000000000000000000000000000000000000000000000004103c000000000000000000000000000000000000000000000000000000000004103d000000000000000000000000000000000000000000000000000000000004103e000000000000000000000000000000000000000000000000000000000004103f3f0000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004110100000000000000000000000000000000000000000000000000000000000411020000000000000000000000000000000000000000000000000000000000041103000000000000000000000000000000000000000000000000000000000004110400000000000000000000000000000000000000000000000000000000000411050000000000000000000000000000000000000000000000000000000000041106000000000000000000000000000000000000000000000000000000000004110700000000000000000000000000000000000000000000000000000000000411080000000000000000000000000000000000000000000000000000000000041109000000000000000000000000000000000000000000000000000000000004110a000000000000000000000000000000000000000000000000000000000004110b000000000000000000000000000000000000000000000000000000000004110c000000000000000000000000000000000000000000000000000000000004110d000000000000000000000000000000000000000000000000000000000004110e000000000000000000000000000000000000000000000000000000000004110f0000000000000000000000000000000000000000000000000000000000041110000000000000000000000000000000000000000000000000000000000004111100000000000000000000000000000000000000000000000000000000000411120000000000000000000000000000000000000000000000000000000000041113000000000000000000000000000000000000000000000000000000000004111400000000000000000000000000000000000000000000000000000000000411150000000000000000000000000000000000000000000000000000000000041116000000000000000000000000000000000000000000000000000000000004111700000000000000000000000000000000000000000000000000000000000411180000000000000000000000000000000000000000000000000000000000041119000000000000000000000000000000000000000000000000000000000004111a000000000000000000000000000000000000000000000000000000000004111b000000000000000000000000000000000000000000000000000000000004111c000000000000000000000000000000000000000000000000000000000004111d000000000000000000000000000000000000000000000000000000000004111e000000000000000000000000000000000000000000000000000000000004111f0000000000000000000000000000000000000000000000000000000000041120000000000000000000000000000000000000000000000000000000000004112100000000000000000000000000000000000000000000000000000000000411220000000000000000000000000000000000000000000000000000000000041123000000000000000000000000000000000000000000000000000000000004112400000000000000000000000000000000000000000000000000000000000411250000000000000000000000000000000000000000000000000000000000041126000000000000000000000000000000000000000000000000000000000004112700000000000000000000000000000000000000000000000000000000000411280000000000000000000000000000000000000000000000000000000000041129000000000000000000000000000000000000000000000000000000000004112a000000000000000000000000000000000000000000000000000000000004112b000000000000000000000000000000000000000000000000000000000004112c000000000000000000000000000000000000000000000000000000000004112d000000000000000000000000000000000000000000000000000000000004112e000000000000000000000000000000000000000000000000000000000004112f0000000000000000000000000000000000000000000000000000000000041130000000000000000000000000000000000000000000000000000000000004113100000000000000000000000000000000000000000000000000000000000411320000000000000000000000000000000000000000000000000000000000041133000000000000000000000000000000000000000000000000000000000004113400000000000000000000000000000000000000000000000000000000000411350000000000000000000000000000000000000000000000000000000000041136000000000000000000000000000000000000000000000000000000000004113700000000000000000000000000000000000000000000000000000000000411380000000000000000000000000000000000000000000000000000000000041139000000000000000000000000000000000000000000000000000000000004113a000000000000000000000000000000000000000000000000000000000004113b000000000000000000000000000000000000000000000000000000000004113c000000000000000000000000000000000000000000000000000000000004113d000000000000000000000000000000000000000000000000000000000004113e080097a6ec570e9b8e257647c9c74c5ad3edc57ca5ef6ae44d80b3c30d1d99b9b300ce48ec41d1edde0066fab553a456ae2f380d14fa8f956af1fb0217513a598900619ff12eaf97f63aa2a2311de3b6571a7b880a5247cb33b6a74787bf3f9bd5007854a2fad4e1801c6404394bf3d37ab08c135ea38a1974242e39a21273685f000f55796e72957a819e68a22e8602d73c3ba3718a5a4bd92b80b0aa444b182a00788b6e9874fb040ee679a7fae257190099a605229b948334e54a57739535d4004f1658ee3c1a91627e5d72f5a731f0796299df82ab41e72c88eee0c82fa85e003ee802add96628c693ed71afa9908138ba5a6fbf0a5f29a9c74e4e42aba6713f0000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000004200a0000000000000000000000000000000000000000000000000000000000042001000000000000000000000000000000000000000000000000000000000004200b0000000000000000000000000000000000000000000000000000000000042002000000000000000000000000000000000000000000000000000000000004200c0000000000000000000000000000000000000000000000000000000000042003000000000000000000000000000000000000000000000000000000000004200d0000000000000000000000000000000000000000000000000000000000042004000000000000000000000000000000000000000000000000000000000004200e0000000000000000000000000000000000000000000000000000000000042005000000000000000000000000000000000000000000000000000000000004200f00000000000000000000000000000000000000000000000000000000000420060000000000000000000000000000000000000000000000000000000000042010000000000000000000000000000000000000000000000000000000000004200700000000000000000000000000000000000000000000000000000000000420110000000000000000000000000000000000000000000000000000000000042008000000000000000000000000000000000000000000000000000000000004201200000000000000000000000000000000000000000000000000000000000420090000000000000000000000000000000000000000000000000000000000042013000000000000000000000000000000000000000000000000000000000004200a0000000000000000000000000000000000000000000000000000000000042014000000000000000000000000000000000000000000000000000000000004200b0000000000000000000000000000000000000000000000000000000000042015000000000000000000000000000000000000000000000000000000000004200c0000000000000000000000000000000000000000000000000000000000042016000000000000000000000000000000000000000000000000000000000004200d0000000000000000000000000000000000000000000000000000000000042017000000000000000000000000000000000000000000000000000000000004200e0000000000000000000000000000000000000000000000000000000000042018000000000000000000000000000000000000000000000000000000000004200f00000000000000000000000000000000000000000000000000000000000420190000000000000000000000000000000000000000000000000000000000042010000000000000000000000000000000000000000000000000000000000004201a0000000000000000000000000000000000000000000000000000000000042011000000000000000000000000000000000000000000000000000000000004201b0000000000000000000000000000000000000000000000000000000000042012000000000000000000000000000000000000000000000000000000000004201c0000000000000000000000000000000000000000000000000000000000042013000000000000000000000000000000000000000000000000000000000004201d0000000000000000000000000000000000000000000000000000000000042014000000000000000000000000000000000000000000000000000000000004201e0000000000000000000000000000000000000000000000000000000000042015000000000000000000000000000000000000000000000000000000000004201f00000000000000000000000000000000000000000000000000000000000420160000000000000000000000000000000000000000000000000000000000042020000000000000000000000000000000000000000000000000000000000004201700000000000000000000000000000000000000000000000000000000000420210000000000000000000000000000000000000000000000000000000000042018000000000000000000000000000000000000000000000000000000000004202200000000000000000000000000000000000000000000000000000000000420190000000000000000000000000000000000000000000000000000000000042023000000000000000000000000000000000000000000000000000000000004201a0000000000000000000000000000000000000000000000000000000000042024000000000000000000000000000000000000000000000000000000000004201b0000000000000000000000000000000000000000000000000000000000042025000000000000000000000000000000000000000000000000000000000004201c0000000000000000000000000000000000000000000000000000000000042026000000000000000000000000000000000000000000000000000000000004201d0000000000000000000000000000000000000000000000000000000000042027000000000000000000000000000000000000000000000000000000000004201e0000000000000000000000000000000000000000000000000000000000042028000000000000000000000000000000000000000000000000000000000004201f00000000000000000000000000000000000000000000000000000000000420290000000000000000000000000000000000000000000000000000000000042020000000000000000000000000000000000000000000000000000000000004202a0000000000000000000000000000000000000000000000000000000000042021000000000000000000000000000000000000000000000000000000000004202b0000000000000000000000000000000000000000000000000000000000042022000000000000000000000000000000000000000000000000000000000004202c0000000000000000000000000000000000000000000000000000000000042023000000000000000000000000000000000000000000000000000000000004202d0000000000000000000000000000000000000000000000000000000000042024000000000000000000000000000000000000000000000000000000000004202e0000000000000000000000000000000000000000000000000000000000042025000000000000000000000000000000000000000000000000000000000004202f00000000000000000000000000000000000000000000000000000000000420260000000000000000000000000000000000000000000000000000000000042030000000000000000000000000000000000000000000000000000000000004202700000000000000000000000000000000000000000000000000000000000420310000000000000000000000000000000000000000000000000000000000042028000000000000000000000000000000000000000000000000000000000004203200000000000000000000000000000000000000000000000000000000000420290000000000000000000000000000000000000000000000000000000000042033000000000000000000000000000000000000000000000000000000000004202a0000000000000000000000000000000000000000000000000000000000042034000000000000000000000000000000000000000000000000000000000004202b0000000000000000000000000000000000000000000000000000000000042035000000000000000000000000000000000000000000000000000000000004202c0000000000000000000000000000000000000000000000000000000000042036000000000000000000000000000000000000000000000000000000000004202d0000000000000000000000000000000000000000000000000000000000042037000000000000000000000000000000000000000000000000000000000004202e0000000000000000000000000000000000000000000000000000000000042038000000000000000000000000000000000000000000000000000000000004202f00000000000000000000000000000000000000000000000000000000000420390000000000000000000000000000000000000000000000000000000000042030000000000000000000000000000000000000000000000000000000000004203a0000000000000000000000000000000000000000000000000000000000042031000000000000000000000000000000000000000000000000000000000004203b0000000000000000000000000000000000000000000000000000000000042032000000000000000000000000000000000000000000000000000000000004203c0000000000000000000000000000000000000000000000000000000000042033000000000000000000000000000000000000000000000000000000000004203d0000000000000000000000000000000000000000000000000000000000042034000000000000000000000000000000000000000000000000000000000004203e0000000000000000000000000000000000000000000000000000000000042035000000000000000000000000000000000000000000000000000000000004203f00000000000000000000000000000000000000000000000000000000000420360000000000000000000000000000000000000000000000000000000000042040000000000000000000000000000000000000000000000000000000000004203700000000000000000000000000000000000000000000000000000000000420410000000000000000000000000000000000000000000000000000000000042038000000000000000000000000000000000000000000000000000000000004204200000000000000000000000000000000000000000000000000000000000420390000000000000000000000000000000000000000000000000000000000042043000000000000000000000000000000000000000000000000000000000004203a0000000000000000000000000000000000000000000000000000000000042044000000000000000000000000000000000000000000000000000000000004203b0000000000000000000000000000000000000000000000000000000000042045000000000000000000000000000000000000000000000000000000000004203c0000000000000000000000000000000000000000000000000000000000042046000000000000000000000000000000000000000000000000000000000004203d0000000000000000000000000000000000000000000000000000000000042047000000000000000000000000000000000000000000000000000000000004203e0000000000000000000000000000000000000000000000000000000000042048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008100100000000000000000000000000000000000000000000000000000000000810020000000000000000000000000000000000000000000000000000000000081003000000000000000000000000000000000000000000000000000000000008100400000000000000000000000000000000000000000000000000000000000810050000000000000000000000000000000000000000000000000000000000081006000000000000000000000000000000000000000000000000000000000008100700000000000000000000000000000000000000000000000000000000000810080000000000000000000000000000000000000000000000000000000000081009000000000000000000000000000000000000000000000000000000000008100a000000000000000000000000000000000000000000000000000000000008100b000000000000000000000000000000000000000000000000000000000008100c000000000000000000000000000000000000000000000000000000000008100d000000000000000000000000000000000000000000000000000000000008100e000000000000000000000000000000000000000000000000000000000008100f0000000000000000000000000000000000000000000000000000000000081010000000000000000000000000000000000000000000000000000000000008101100000000000000000000000000000000000000000000000000000000000810120000000000000000000000000000000000000000000000000000000000081013000000000000000000000000000000000000000000000000000000000008101400000000000000000000000000000000000000000000000000000000000810150000000000000000000000000000000000000000000000000000000000081016000000000000000000000000000000000000000000000000000000000008101700000000000000000000000000000000000000000000000000000000000810180000000000000000000000000000000000000000000000000000000000081019000000000000000000000000000000000000000000000000000000000008101a000000000000000000000000000000000000000000000000000000000008101b000000000000000000000000000000000000000000000000000000000008101c000000000000000000000000000000000000000000000000000000000008101d000000000000000000000000000000000000000000000000000000000008101e000000000000000000000000000000000000000000000000000000000008101f0000000000000000000000000000000000000000000000000000000000081020000000000000000000000000000000000000000000000000000000000008102100000000000000000000000000000000000000000000000000000000000810220000000000000000000000000000000000000000000000000000000000081023000000000000000000000000000000000000000000000000000000000008102400000000000000000000000000000000000000000000000000000000000810250000000000000000000000000000000000000000000000000000000000081026000000000000000000000000000000000000000000000000000000000008102700000000000000000000000000000000000000000000000000000000000810280000000000000000000000000000000000000000000000000000000000081029000000000000000000000000000000000000000000000000000000000008102a000000000000000000000000000000000000000000000000000000000008102b000000000000000000000000000000000000000000000000000000000008102c000000000000000000000000000000000000000000000000000000000008102d000000000000000000000000000000000000000000000000000000000008102e000000000000000000000000000000000000000000000000000000000008102f0000000000000000000000000000000000000000000000000000000000081030000000000000000000000000000000000000000000000000000000000008103100000000000000000000000000000000000000000000000000000000000810320000000000000000000000000000000000000000000000000000000000081033000000000000000000000000000000000000000000000000000000000008103400000000000000000000000000000000000000000000000000000000000810350000000000000000000000000000000000000000000000000000000000081036000000000000000000000000000000000000000000000000000000000008103700000000000000000000000000000000000000000000000000000000000810380000000000000000000000000000000000000000000000000000000000081039000000000000000000000000000000000000000000000000000000000008103a000000000000000000000000000000000000000000000000000000000008103b000000000000000000000000000000000000000000000000000000000008103c000000000000000000000000000000000000000000000000000000000008103d000000000000000000000000000000000000000000000000000000000008103e000000000000000000000000000000000000000000000000000000000008103f3f0000000000000000000000000000000000000000000000000000000000081100000000000000000000000000000000000000000000000000000000000008110100000000000000000000000000000000000000000000000000000000000811020000000000000000000000000000000000000000000000000000000000081103000000000000000000000000000000000000000000000000000000000008110400000000000000000000000000000000000000000000000000000000000811050000000000000000000000000000000000000000000000000000000000081106000000000000000000000000000000000000000000000000000000000008110700000000000000000000000000000000000000000000000000000000000811080000000000000000000000000000000000000000000000000000000000081109000000000000000000000000000000000000000000000000000000000008110a000000000000000000000000000000000000000000000000000000000008110b000000000000000000000000000000000000000000000000000000000008110c000000000000000000000000000000000000000000000000000000000008110d000000000000000000000000000000000000000000000000000000000008110e000000000000000000000000000000000000000000000000000000000008110f0000000000000000000000000000000000000000000000000000000000081110000000000000000000000000000000000000000000000000000000000008111100000000000000000000000000000000000000000000000000000000000811120000000000000000000000000000000000000000000000000000000000081113000000000000000000000000000000000000000000000000000000000008111400000000000000000000000000000000000000000000000000000000000811150000000000000000000000000000000000000000000000000000000000081116000000000000000000000000000000000000000000000000000000000008111700000000000000000000000000000000000000000000000000000000000811180000000000000000000000000000000000000000000000000000000000081119000000000000000000000000000000000000000000000000000000000008111a000000000000000000000000000000000000000000000000000000000008111b000000000000000000000000000000000000000000000000000000000008111c000000000000000000000000000000000000000000000000000000000008111d000000000000000000000000000000000000000000000000000000000008111e000000000000000000000000000000000000000000000000000000000008111f0000000000000000000000000000000000000000000000000000000000081120000000000000000000000000000000000000000000000000000000000008112100000000000000000000000000000000000000000000000000000000000811220000000000000000000000000000000000000000000000000000000000081123000000000000000000000000000000000000000000000000000000000008112400000000000000000000000000000000000000000000000000000000000811250000000000000000000000000000000000000000000000000000000000081126000000000000000000000000000000000000000000000000000000000008112700000000000000000000000000000000000000000000000000000000000811280000000000000000000000000000000000000000000000000000000000081129000000000000000000000000000000000000000000000000000000000008112a000000000000000000000000000000000000000000000000000000000008112b000000000000000000000000000000000000000000000000000000000008112c000000000000000000000000000000000000000000000000000000000008112d000000000000000000000000000000000000000000000000000000000008112e000000000000000000000000000000000000000000000000000000000008112f0000000000000000000000000000000000000000000000000000000000081130000000000000000000000000000000000000000000000000000000000008113100000000000000000000000000000000000000000000000000000000000811320000000000000000000000000000000000000000000000000000000000081133000000000000000000000000000000000000000000000000000000000008113400000000000000000000000000000000000000000000000000000000000811350000000000000000000000000000000000000000000000000000000000081136000000000000000000000000000000000000000000000000000000000008113700000000000000000000000000000000000000000000000000000000000811380000000000000000000000000000000000000000000000000000000000081139000000000000000000000000000000000000000000000000000000000008113a000000000000000000000000000000000000000000000000000000000008113b000000000000000000000000000000000000000000000000000000000008113c000000000000000000000000000000000000000000000000000000000008113d000000000000000000000000000000000000000000000000000000000008113e08003c0472260790b0bdfb8ae4dc4d437e7686b73643f2198970d84e1059a5f13500bfd46275a318e438726ff2765ae154b63ab8a0daebcbed668a5f58a0e63dc1007906b9418dc758c6b4f8454c69baa48b7889b6b511d707abe8e2cb8f7c397300aeb60c4d65a44f122e58bf9565dfe2024b3ae654d5cf2e47ecb035d53c927000bf82e8cda20345f37bbb1de3932172324b57f0b98be483392697b168e3bba8000fb4bbad884ef30edf68e45a6cf2733fcf50310c69d7c1432b29af2c0aa8040023e1622d27fee3b4a40ab975ae0eb2e31619ef3dc76eb858f7fddb6a056131004689cd7007daf98dd3218b839b8e6a29f957154347b391fdb376bd0b344be23f0000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000008200a0000000000000000000000000000000000000000000000000000000000082001000000000000000000000000000000000000000000000000000000000008200b0000000000000000000000000000000000000000000000000000000000082002000000000000000000000000000000000000000000000000000000000008200c0000000000000000000000000000000000000000000000000000000000082003000000000000000000000000000000000000000000000000000000000008200d0000000000000000000000000000000000000000000000000000000000082004000000000000000000000000000000000000000000000000000000000008200e0000000000000000000000000000000000000000000000000000000000082005000000000000000000000000000000000000000000000000000000000008200f00000000000000000000000000000000000000000000000000000000000820060000000000000000000000000000000000000000000000000000000000082010000000000000000000000000000000000000000000000000000000000008200700000000000000000000000000000000000000000000000000000000000820110000000000000000000000000000000000000000000000000000000000082008000000000000000000000000000000000000000000000000000000000008201200000000000000000000000000000000000000000000000000000000000820090000000000000000000000000000000000000000000000000000000000082013000000000000000000000000000000000000000000000000000000000008200a0000000000000000000000000000000000000000000000000000000000082014000000000000000000000000000000000000000000000000000000000008200b0000000000000000000000000000000000000000000000000000000000082015000000000000000000000000000000000000000000000000000000000008200c0000000000000000000000000000000000000000000000000000000000082016000000000000000000000000000000000000000000000000000000000008200d0000000000000000000000000000000000000000000000000000000000082017000000000000000000000000000000000000000000000000000000000008200e0000000000000000000000000000000000000000000000000000000000082018000000000000000000000000000000000000000000000000000000000008200f00000000000000000000000000000000000000000000000000000000000820190000000000000000000000000000000000000000000000000000000000082010000000000000000000000000000000000000000000000000000000000008201a0000000000000000000000000000000000000000000000000000000000082011000000000000000000000000000000000000000000000000000000000008201b0000000000000000000000000000000000000000000000000000000000082012000000000000000000000000000000000000000000000000000000000008201c0000000000000000000000000000000000000000000000000000000000082013000000000000000000000000000000000000000000000000000000000008201d0000000000000000000000000000000000000000000000000000000000082014000000000000000000000000000000000000000000000000000000000008201e0000000000000000000000000000000000000000000000000000000000082015000000000000000000000000000000000000000000000000000000000008201f00000000000000000000000000000000000000000000000000000000000820160000000000000000000000000000000000000000000000000000000000082020000000000000000000000000000000000000000000000000000000000008201700000000000000000000000000000000000000000000000000000000000820210000000000000000000000000000000000000000000000000000000000082018000000000000000000000000000000000000000000000000000000000008202200000000000000000000000000000000000000000000000000000000000820190000000000000000000000000000000000000000000000000000000000082023000000000000000000000000000000000000000000000000000000000008201a0000000000000000000000000000000000000000000000000000000000082024000000000000000000000000000000000000000000000000000000000008201b0000000000000000000000000000000000000000000000000000000000082025000000000000000000000000000000000000000000000000000000000008201c0000000000000000000000000000000000000000000000000000000000082026000000000000000000000000000000000000000000000000000000000008201d0000000000000000000000000000000000000000000000000000000000082027000000000000000000000000000000000000000000000000000000000008201e0000000000000000000000000000000000000000000000000000000000082028000000000000000000000000000000000000000000000000000000000008201f00000000000000000000000000000000000000000000000000000000000820290000000000000000000000000000000000000000000000000000000000082020000000000000000000000000000000000000000000000000000000000008202a0000000000000000000000000000000000000000000000000000000000082021000000000000000000000000000000000000000000000000000000000008202b0000000000000000000000000000000000000000000000000000000000082022000000000000000000000000000000000000000000000000000000000008202c0000000000000000000000000000000000000000000000000000000000082023000000000000000000000000000000000000000000000000000000000008202d0000000000000000000000000000000000000000000000000000000000082024000000000000000000000000000000000000000000000000000000000008202e0000000000000000000000000000000000000000000000000000000000082025000000000000000000000000000000000000000000000000000000000008202f00000000000000000000000000000000000000000000000000000000000820260000000000000000000000000000000000000000000000000000000000082030000000000000000000000000000000000000000000000000000000000008202700000000000000000000000000000000000000000000000000000000000820310000000000000000000000000000000000000000000000000000000000082028000000000000000000000000000000000000000000000000000000000008203200000000000000000000000000000000000000000000000000000000000820290000000000000000000000000000000000000000000000000000000000082033000000000000000000000000000000000000000000000000000000000008202a0000000000000000000000000000000000000000000000000000000000082034000000000000000000000000000000000000000000000000000000000008202b0000000000000000000000000000000000000000000000000000000000082035000000000000000000000000000000000000000000000000000000000008202c0000000000000000000000000000000000000000000000000000000000082036000000000000000000000000000000000000000000000000000000000008202d0000000000000000000000000000000000000000000000000000000000082037000000000000000000000000000000000000000000000000000000000008202e0000000000000000000000000000000000000000000000000000000000082038000000000000000000000000000000000000000000000000000000000008202f00000000000000000000000000000000000000000000000000000000000820390000000000000000000000000000000000000000000000000000000000082030000000000000000000000000000000000000000000000000000000000008203a0000000000000000000000000000000000000000000000000000000000082031000000000000000000000000000000000000000000000000000000000008203b0000000000000000000000000000000000000000000000000000000000082032000000000000000000000000000000000000000000000000000000000008203c0000000000000000000000000000000000000000000000000000000000082033000000000000000000000000000000000000000000000000000000000008203d0000000000000000000000000000000000000000000000000000000000082034000000000000000000000000000000000000000000000000000000000008203e0000000000000000000000000000000000000000000000000000000000082035000000000000000000000000000000000000000000000000000000000008203f00000000000000000000000000000000000000000000000000000000000820360000000000000000000000000000000000000000000000000000000000082040000000000000000000000000000000000000000000000000000000000008203700000000000000000000000000000000000000000000000000000000000820410000000000000000000000000000000000000000000000000000000000082038000000000000000000000000000000000000000000000000000000000008204200000000000000000000000000000000000000000000000000000000000820390000000000000000000000000000000000000000000000000000000000082043000000000000000000000000000000000000000000000000000000000008203a0000000000000000000000000000000000000000000000000000000000082044000000000000000000000000000000000000000000000000000000000008203b0000000000000000000000000000000000000000000000000000000000082045000000000000000000000000000000000000000000000000000000000008203c0000000000000000000000000000000000000000000000000000000000082046000000000000000000000000000000000000000000000000000000000008203d0000000000000000000000000000000000000000000000000000000000082047000000000000000000000000000000000000000000000000000000000008203e00000000000000000000000000000000000000000000000000000000000820480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000c100100000000000000000000000000000000000000000000000000000000000c100200000000000000000000000000000000000000000000000000000000000c100300000000000000000000000000000000000000000000000000000000000c100400000000000000000000000000000000000000000000000000000000000c100500000000000000000000000000000000000000000000000000000000000c100600000000000000000000000000000000000000000000000000000000000c100700000000000000000000000000000000000000000000000000000000000c100800000000000000000000000000000000000000000000000000000000000c100900000000000000000000000000000000000000000000000000000000000c100a00000000000000000000000000000000000000000000000000000000000c100b00000000000000000000000000000000000000000000000000000000000c100c00000000000000000000000000000000000000000000000000000000000c100d00000000000000000000000000000000000000000000000000000000000c100e00000000000000000000000000000000000000000000000000000000000c100f00000000000000000000000000000000000000000000000000000000000c101000000000000000000000000000000000000000000000000000000000000c101100000000000000000000000000000000000000000000000000000000000c101200000000000000000000000000000000000000000000000000000000000c101300000000000000000000000000000000000000000000000000000000000c101400000000000000000000000000000000000000000000000000000000000c101500000000000000000000000000000000000000000000000000000000000c101600000000000000000000000000000000000000000000000000000000000c101700000000000000000000000000000000000000000000000000000000000c101800000000000000000000000000000000000000000000000000000000000c101900000000000000000000000000000000000000000000000000000000000c101a00000000000000000000000000000000000000000000000000000000000c101b00000000000000000000000000000000000000000000000000000000000c101c00000000000000000000000000000000000000000000000000000000000c101d00000000000000000000000000000000000000000000000000000000000c101e00000000000000000000000000000000000000000000000000000000000c101f00000000000000000000000000000000000000000000000000000000000c102000000000000000000000000000000000000000000000000000000000000c102100000000000000000000000000000000000000000000000000000000000c102200000000000000000000000000000000000000000000000000000000000c102300000000000000000000000000000000000000000000000000000000000c102400000000000000000000000000000000000000000000000000000000000c102500000000000000000000000000000000000000000000000000000000000c102600000000000000000000000000000000000000000000000000000000000c102700000000000000000000000000000000000000000000000000000000000c102800000000000000000000000000000000000000000000000000000000000c102900000000000000000000000000000000000000000000000000000000000c102a00000000000000000000000000000000000000000000000000000000000c102b00000000000000000000000000000000000000000000000000000000000c102c00000000000000000000000000000000000000000000000000000000000c102d00000000000000000000000000000000000000000000000000000000000c102e00000000000000000000000000000000000000000000000000000000000c102f00000000000000000000000000000000000000000000000000000000000c103000000000000000000000000000000000000000000000000000000000000c103100000000000000000000000000000000000000000000000000000000000c103200000000000000000000000000000000000000000000000000000000000c103300000000000000000000000000000000000000000000000000000000000c103400000000000000000000000000000000000000000000000000000000000c103500000000000000000000000000000000000000000000000000000000000c103600000000000000000000000000000000000000000000000000000000000c103700000000000000000000000000000000000000000000000000000000000c103800000000000000000000000000000000000000000000000000000000000c103900000000000000000000000000000000000000000000000000000000000c103a00000000000000000000000000000000000000000000000000000000000c103b00000000000000000000000000000000000000000000000000000000000c103c00000000000000000000000000000000000000000000000000000000000c103d00000000000000000000000000000000000000000000000000000000000c103e00000000000000000000000000000000000000000000000000000000000c103f3f00000000000000000000000000000000000000000000000000000000000c110000000000000000000000000000000000000000000000000000000000000c110100000000000000000000000000000000000000000000000000000000000c110200000000000000000000000000000000000000000000000000000000000c110300000000000000000000000000000000000000000000000000000000000c110400000000000000000000000000000000000000000000000000000000000c110500000000000000000000000000000000000000000000000000000000000c110600000000000000000000000000000000000000000000000000000000000c110700000000000000000000000000000000000000000000000000000000000c110800000000000000000000000000000000000000000000000000000000000c110900000000000000000000000000000000000000000000000000000000000c110a00000000000000000000000000000000000000000000000000000000000c110b00000000000000000000000000000000000000000000000000000000000c110c00000000000000000000000000000000000000000000000000000000000c110d00000000000000000000000000000000000000000000000000000000000c110e00000000000000000000000000000000000000000000000000000000000c110f00000000000000000000000000000000000000000000000000000000000c111000000000000000000000000000000000000000000000000000000000000c111100000000000000000000000000000000000000000000000000000000000c111200000000000000000000000000000000000000000000000000000000000c111300000000000000000000000000000000000000000000000000000000000c111400000000000000000000000000000000000000000000000000000000000c111500000000000000000000000000000000000000000000000000000000000c111600000000000000000000000000000000000000000000000000000000000c111700000000000000000000000000000000000000000000000000000000000c111800000000000000000000000000000000000000000000000000000000000c111900000000000000000000000000000000000000000000000000000000000c111a00000000000000000000000000000000000000000000000000000000000c111b00000000000000000000000000000000000000000000000000000000000c111c00000000000000000000000000000000000000000000000000000000000c111d00000000000000000000000000000000000000000000000000000000000c111e00000000000000000000000000000000000000000000000000000000000c111f00000000000000000000000000000000000000000000000000000000000c112000000000000000000000000000000000000000000000000000000000000c112100000000000000000000000000000000000000000000000000000000000c112200000000000000000000000000000000000000000000000000000000000c112300000000000000000000000000000000000000000000000000000000000c112400000000000000000000000000000000000000000000000000000000000c112500000000000000000000000000000000000000000000000000000000000c112600000000000000000000000000000000000000000000000000000000000c112700000000000000000000000000000000000000000000000000000000000c112800000000000000000000000000000000000000000000000000000000000c112900000000000000000000000000000000000000000000000000000000000c112a00000000000000000000000000000000000000000000000000000000000c112b00000000000000000000000000000000000000000000000000000000000c112c00000000000000000000000000000000000000000000000000000000000c112d00000000000000000000000000000000000000000000000000000000000c112e00000000000000000000000000000000000000000000000000000000000c112f00000000000000000000000000000000000000000000000000000000000c113000000000000000000000000000000000000000000000000000000000000c113100000000000000000000000000000000000000000000000000000000000c113200000000000000000000000000000000000000000000000000000000000c113300000000000000000000000000000000000000000000000000000000000c113400000000000000000000000000000000000000000000000000000000000c113500000000000000000000000000000000000000000000000000000000000c113600000000000000000000000000000000000000000000000000000000000c113700000000000000000000000000000000000000000000000000000000000c113800000000000000000000000000000000000000000000000000000000000c113900000000000000000000000000000000000000000000000000000000000c113a00000000000000000000000000000000000000000000000000000000000c113b00000000000000000000000000000000000000000000000000000000000c113c00000000000000000000000000000000000000000000000000000000000c113d00000000000000000000000000000000000000000000000000000000000c113e0800f8029be42ec3f25204907ca981fb71e5b357093eb5db10fc01ca98a4e4154c0030e13d351a5bf1d5a040e82a163ca57017f39162693f85c571e441e36d702d00a550ae0f39f977d9473d6de1be3232fc68ed0c4a601d53542148695102cfc9005580bc65e4bff9c8fffa64db02c0fa6af14d9d26fd962f4c5904cbd3ddec2500758c4a0d43dfec788b2f580877c4f473adec8f168ea24424f2600e4eb4916f00342602bf90d10f8ca8e582a894dcc4c02bb89fe458532e0c632b53bae54b4d00ca43ab78ab834337e9964d84a0674c9adabdca140539c5a6bc96e0ba9a51f6004ffbfd91be292a7c6a0e255e50caa156ac2d628b40ad2128c4ab63a92d8a1c3f00000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c200a00000000000000000000000000000000000000000000000000000000000c200100000000000000000000000000000000000000000000000000000000000c200b00000000000000000000000000000000000000000000000000000000000c200200000000000000000000000000000000000000000000000000000000000c200c00000000000000000000000000000000000000000000000000000000000c200300000000000000000000000000000000000000000000000000000000000c200d00000000000000000000000000000000000000000000000000000000000c200400000000000000000000000000000000000000000000000000000000000c200e00000000000000000000000000000000000000000000000000000000000c200500000000000000000000000000000000000000000000000000000000000c200f00000000000000000000000000000000000000000000000000000000000c200600000000000000000000000000000000000000000000000000000000000c201000000000000000000000000000000000000000000000000000000000000c200700000000000000000000000000000000000000000000000000000000000c201100000000000000000000000000000000000000000000000000000000000c200800000000000000000000000000000000000000000000000000000000000c201200000000000000000000000000000000000000000000000000000000000c200900000000000000000000000000000000000000000000000000000000000c201300000000000000000000000000000000000000000000000000000000000c200a00000000000000000000000000000000000000000000000000000000000c201400000000000000000000000000000000000000000000000000000000000c200b00000000000000000000000000000000000000000000000000000000000c201500000000000000000000000000000000000000000000000000000000000c200c00000000000000000000000000000000000000000000000000000000000c201600000000000000000000000000000000000000000000000000000000000c200d00000000000000000000000000000000000000000000000000000000000c201700000000000000000000000000000000000000000000000000000000000c200e00000000000000000000000000000000000000000000000000000000000c201800000000000000000000000000000000000000000000000000000000000c200f00000000000000000000000000000000000000000000000000000000000c201900000000000000000000000000000000000000000000000000000000000c201000000000000000000000000000000000000000000000000000000000000c201a00000000000000000000000000000000000000000000000000000000000c201100000000000000000000000000000000000000000000000000000000000c201b00000000000000000000000000000000000000000000000000000000000c201200000000000000000000000000000000000000000000000000000000000c201c00000000000000000000000000000000000000000000000000000000000c201300000000000000000000000000000000000000000000000000000000000c201d00000000000000000000000000000000000000000000000000000000000c201400000000000000000000000000000000000000000000000000000000000c201e00000000000000000000000000000000000000000000000000000000000c201500000000000000000000000000000000000000000000000000000000000c201f00000000000000000000000000000000000000000000000000000000000c201600000000000000000000000000000000000000000000000000000000000c202000000000000000000000000000000000000000000000000000000000000c201700000000000000000000000000000000000000000000000000000000000c202100000000000000000000000000000000000000000000000000000000000c201800000000000000000000000000000000000000000000000000000000000c202200000000000000000000000000000000000000000000000000000000000c201900000000000000000000000000000000000000000000000000000000000c202300000000000000000000000000000000000000000000000000000000000c201a00000000000000000000000000000000000000000000000000000000000c202400000000000000000000000000000000000000000000000000000000000c201b00000000000000000000000000000000000000000000000000000000000c202500000000000000000000000000000000000000000000000000000000000c201c00000000000000000000000000000000000000000000000000000000000c202600000000000000000000000000000000000000000000000000000000000c201d00000000000000000000000000000000000000000000000000000000000c202700000000000000000000000000000000000000000000000000000000000c201e00000000000000000000000000000000000000000000000000000000000c202800000000000000000000000000000000000000000000000000000000000c201f00000000000000000000000000000000000000000000000000000000000c202900000000000000000000000000000000000000000000000000000000000c202000000000000000000000000000000000000000000000000000000000000c202a00000000000000000000000000000000000000000000000000000000000c202100000000000000000000000000000000000000000000000000000000000c202b00000000000000000000000000000000000000000000000000000000000c202200000000000000000000000000000000000000000000000000000000000c202c00000000000000000000000000000000000000000000000000000000000c202300000000000000000000000000000000000000000000000000000000000c202d00000000000000000000000000000000000000000000000000000000000c202400000000000000000000000000000000000000000000000000000000000c202e00000000000000000000000000000000000000000000000000000000000c202500000000000000000000000000000000000000000000000000000000000c202f00000000000000000000000000000000000000000000000000000000000c202600000000000000000000000000000000000000000000000000000000000c203000000000000000000000000000000000000000000000000000000000000c202700000000000000000000000000000000000000000000000000000000000c203100000000000000000000000000000000000000000000000000000000000c202800000000000000000000000000000000000000000000000000000000000c203200000000000000000000000000000000000000000000000000000000000c202900000000000000000000000000000000000000000000000000000000000c203300000000000000000000000000000000000000000000000000000000000c202a00000000000000000000000000000000000000000000000000000000000c203400000000000000000000000000000000000000000000000000000000000c202b00000000000000000000000000000000000000000000000000000000000c203500000000000000000000000000000000000000000000000000000000000c202c00000000000000000000000000000000000000000000000000000000000c203600000000000000000000000000000000000000000000000000000000000c202d00000000000000000000000000000000000000000000000000000000000c203700000000000000000000000000000000000000000000000000000000000c202e00000000000000000000000000000000000000000000000000000000000c203800000000000000000000000000000000000000000000000000000000000c202f00000000000000000000000000000000000000000000000000000000000c203900000000000000000000000000000000000000000000000000000000000c203000000000000000000000000000000000000000000000000000000000000c203a00000000000000000000000000000000000000000000000000000000000c203100000000000000000000000000000000000000000000000000000000000c203b00000000000000000000000000000000000000000000000000000000000c203200000000000000000000000000000000000000000000000000000000000c203c00000000000000000000000000000000000000000000000000000000000c203300000000000000000000000000000000000000000000000000000000000c203d00000000000000000000000000000000000000000000000000000000000c203400000000000000000000000000000000000000000000000000000000000c203e00000000000000000000000000000000000000000000000000000000000c203500000000000000000000000000000000000000000000000000000000000c203f00000000000000000000000000000000000000000000000000000000000c203600000000000000000000000000000000000000000000000000000000000c204000000000000000000000000000000000000000000000000000000000000c203700000000000000000000000000000000000000000000000000000000000c204100000000000000000000000000000000000000000000000000000000000c203800000000000000000000000000000000000000000000000000000000000c204200000000000000000000000000000000000000000000000000000000000c203900000000000000000000000000000000000000000000000000000000000c204300000000000000000000000000000000000000000000000000000000000c203a00000000000000000000000000000000000000000000000000000000000c204400000000000000000000000000000000000000000000000000000000000c203b00000000000000000000000000000000000000000000000000000000000c204500000000000000000000000000000000000000000000000000000000000c203c00000000000000000000000000000000000000000000000000000000000c204600000000000000000000000000000000000000000000000000000000000c203d00000000000000000000000000000000000000000000000000000000000c204700000000000000000000000000000000000000000000000000000000000c203e00000000000000000000000000000000000000000000000000000000000c2048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000101000000000000000000000000000000000000000000000000000000000000010100100000000000000000000000000000000000000000000000000000000001010020000000000000000000000000000000000000000000000000000000000101003000000000000000000000000000000000000000000000000000000000010100400000000000000000000000000000000000000000000000000000000001010050000000000000000000000000000000000000000000000000000000000101006000000000000000000000000000000000000000000000000000000000010100700000000000000000000000000000000000000000000000000000000001010080000000000000000000000000000000000000000000000000000000000101009000000000000000000000000000000000000000000000000000000000010100a000000000000000000000000000000000000000000000000000000000010100b000000000000000000000000000000000000000000000000000000000010100c000000000000000000000000000000000000000000000000000000000010100d000000000000000000000000000000000000000000000000000000000010100e000000000000000000000000000000000000000000000000000000000010100f0000000000000000000000000000000000000000000000000000000000101010000000000000000000000000000000000000000000000000000000000010101100000000000000000000000000000000000000000000000000000000001010120000000000000000000000000000000000000000000000000000000000101013000000000000000000000000000000000000000000000000000000000010101400000000000000000000000000000000000000000000000000000000001010150000000000000000000000000000000000000000000000000000000000101016000000000000000000000000000000000000000000000000000000000010101700000000000000000000000000000000000000000000000000000000001010180000000000000000000000000000000000000000000000000000000000101019000000000000000000000000000000000000000000000000000000000010101a000000000000000000000000000000000000000000000000000000000010101b000000000000000000000000000000000000000000000000000000000010101c000000000000000000000000000000000000000000000000000000000010101d000000000000000000000000000000000000000000000000000000000010101e000000000000000000000000000000000000000000000000000000000010101f0000000000000000000000000000000000000000000000000000000000101020000000000000000000000000000000000000000000000000000000000010102100000000000000000000000000000000000000000000000000000000001010220000000000000000000000000000000000000000000000000000000000101023000000000000000000000000000000000000000000000000000000000010102400000000000000000000000000000000000000000000000000000000001010250000000000000000000000000000000000000000000000000000000000101026000000000000000000000000000000000000000000000000000000000010102700000000000000000000000000000000000000000000000000000000001010280000000000000000000000000000000000000000000000000000000000101029000000000000000000000000000000000000000000000000000000000010102a000000000000000000000000000000000000000000000000000000000010102b000000000000000000000000000000000000000000000000000000000010102c000000000000000000000000000000000000000000000000000000000010102d000000000000000000000000000000000000000000000000000000000010102e000000000000000000000000000000000000000000000000000000000010102f0000000000000000000000000000000000000000000000000000000000101030000000000000000000000000000000000000000000000000000000000010103100000000000000000000000000000000000000000000000000000000001010320000000000000000000000000000000000000000000000000000000000101033000000000000000000000000000000000000000000000000000000000010103400000000000000000000000000000000000000000000000000000000001010350000000000000000000000000000000000000000000000000000000000101036000000000000000000000000000000000000000000000000000000000010103700000000000000000000000000000000000000000000000000000000001010380000000000000000000000000000000000000000000000000000000000101039000000000000000000000000000000000000000000000000000000000010103a000000000000000000000000000000000000000000000000000000000010103b000000000000000000000000000000000000000000000000000000000010103c000000000000000000000000000000000000000000000000000000000010103d000000000000000000000000000000000000000000000000000000000010103e000000000000000000000000000000000000000000000000000000000010103f3f0000000000000000000000000000000000000000000000000000000000101100000000000000000000000000000000000000000000000000000000000010110100000000000000000000000000000000000000000000000000000000001011020000000000000000000000000000000000000000000000000000000000101103000000000000000000000000000000000000000000000000000000000010110400000000000000000000000000000000000000000000000000000000001011050000000000000000000000000000000000000000000000000000000000101106000000000000000000000000000000000000000000000000000000000010110700000000000000000000000000000000000000000000000000000000001011080000000000000000000000000000000000000000000000000000000000101109000000000000000000000000000000000000000000000000000000000010110a000000000000000000000000000000000000000000000000000000000010110b000000000000000000000000000000000000000000000000000000000010110c000000000000000000000000000000000000000000000000000000000010110d000000000000000000000000000000000000000000000000000000000010110e000000000000000000000000000000000000000000000000000000000010110f0000000000000000000000000000000000000000000000000000000000101110000000000000000000000000000000000000000000000000000000000010111100000000000000000000000000000000000000000000000000000000001011120000000000000000000000000000000000000000000000000000000000101113000000000000000000000000000000000000000000000000000000000010111400000000000000000000000000000000000000000000000000000000001011150000000000000000000000000000000000000000000000000000000000101116000000000000000000000000000000000000000000000000000000000010111700000000000000000000000000000000000000000000000000000000001011180000000000000000000000000000000000000000000000000000000000101119000000000000000000000000000000000000000000000000000000000010111a000000000000000000000000000000000000000000000000000000000010111b000000000000000000000000000000000000000000000000000000000010111c000000000000000000000000000000000000000000000000000000000010111d000000000000000000000000000000000000000000000000000000000010111e000000000000000000000000000000000000000000000000000000000010111f0000000000000000000000000000000000000000000000000000000000101120000000000000000000000000000000000000000000000000000000000010112100000000000000000000000000000000000000000000000000000000001011220000000000000000000000000000000000000000000000000000000000101123000000000000000000000000000000000000000000000000000000000010112400000000000000000000000000000000000000000000000000000000001011250000000000000000000000000000000000000000000000000000000000101126000000000000000000000000000000000000000000000000000000000010112700000000000000000000000000000000000000000000000000000000001011280000000000000000000000000000000000000000000000000000000000101129000000000000000000000000000000000000000000000000000000000010112a000000000000000000000000000000000000000000000000000000000010112b000000000000000000000000000000000000000000000000000000000010112c000000000000000000000000000000000000000000000000000000000010112d000000000000000000000000000000000000000000000000000000000010112e000000000000000000000000000000000000000000000000000000000010112f0000000000000000000000000000000000000000000000000000000000101130000000000000000000000000000000000000000000000000000000000010113100000000000000000000000000000000000000000000000000000000001011320000000000000000000000000000000000000000000000000000000000101133000000000000000000000000000000000000000000000000000000000010113400000000000000000000000000000000000000000000000000000000001011350000000000000000000000000000000000000000000000000000000000101136000000000000000000000000000000000000000000000000000000000010113700000000000000000000000000000000000000000000000000000000001011380000000000000000000000000000000000000000000000000000000000101139000000000000000000000000000000000000000000000000000000000010113a000000000000000000000000000000000000000000000000000000000010113b000000000000000000000000000000000000000000000000000000000010113c000000000000000000000000000000000000000000000000000000000010113d000000000000000000000000000000000000000000000000000000000010113e080099145b6c0d32753835121f8b271186d01236948a4622ce78a98347fcfc98390085277a27c6acbd5ffc4c19cd65fc30056999e9bec36998f753132db0ff8e2300f3cf77a7261759ebd5f4149f6ad56746f4499cfcd4adf27a1d373f77da64d5009bc6e0e994a23cde8c95b90c1acc1b4a480c6599d1df2c3f9f6e76f3d1aff200d7a1c4a2700dacaaf07f1f0ff33837bdbabcf0b9ace17efabe0761708c4bb900dbeb8e96d14f21e57d5786b6d6ae7e5ddb1bb35935c0fb246d4bdbca62e02c00fbf12b5e0df6223b801088798e4e04d2a92ffe9a11639b7f0ce314e3412a8000d796e0724de03b796ba77069fcd6cf921e566f3aed15eb3e77258add74e9ff3f0000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010200a0000000000000000000000000000000000000000000000000000000000102001000000000000000000000000000000000000000000000000000000000010200b0000000000000000000000000000000000000000000000000000000000102002000000000000000000000000000000000000000000000000000000000010200c0000000000000000000000000000000000000000000000000000000000102003000000000000000000000000000000000000000000000000000000000010200d0000000000000000000000000000000000000000000000000000000000102004000000000000000000000000000000000000000000000000000000000010200e0000000000000000000000000000000000000000000000000000000000102005000000000000000000000000000000000000000000000000000000000010200f00000000000000000000000000000000000000000000000000000000001020060000000000000000000000000000000000000000000000000000000000102010000000000000000000000000000000000000000000000000000000000010200700000000000000000000000000000000000000000000000000000000001020110000000000000000000000000000000000000000000000000000000000102008000000000000000000000000000000000000000000000000000000000010201200000000000000000000000000000000000000000000000000000000001020090000000000000000000000000000000000000000000000000000000000102013000000000000000000000000000000000000000000000000000000000010200a0000000000000000000000000000000000000000000000000000000000102014000000000000000000000000000000000000000000000000000000000010200b0000000000000000000000000000000000000000000000000000000000102015000000000000000000000000000000000000000000000000000000000010200c0000000000000000000000000000000000000000000000000000000000102016000000000000000000000000000000000000000000000000000000000010200d0000000000000000000000000000000000000000000000000000000000102017000000000000000000000000000000000000000000000000000000000010200e0000000000000000000000000000000000000000000000000000000000102018000000000000000000000000000000000000000000000000000000000010200f00000000000000000000000000000000000000000000000000000000001020190000000000000000000000000000000000000000000000000000000000102010000000000000000000000000000000000000000000000000000000000010201a0000000000000000000000000000000000000000000000000000000000102011000000000000000000000000000000000000000000000000000000000010201b0000000000000000000000000000000000000000000000000000000000102012000000000000000000000000000000000000000000000000000000000010201c0000000000000000000000000000000000000000000000000000000000102013000000000000000000000000000000000000000000000000000000000010201d0000000000000000000000000000000000000000000000000000000000102014000000000000000000000000000000000000000000000000000000000010201e0000000000000000000000000000000000000000000000000000000000102015000000000000000000000000000000000000000000000000000000000010201f00000000000000000000000000000000000000000000000000000000001020160000000000000000000000000000000000000000000000000000000000102020000000000000000000000000000000000000000000000000000000000010201700000000000000000000000000000000000000000000000000000000001020210000000000000000000000000000000000000000000000000000000000102018000000000000000000000000000000000000000000000000000000000010202200000000000000000000000000000000000000000000000000000000001020190000000000000000000000000000000000000000000000000000000000102023000000000000000000000000000000000000000000000000000000000010201a0000000000000000000000000000000000000000000000000000000000102024000000000000000000000000000000000000000000000000000000000010201b0000000000000000000000000000000000000000000000000000000000102025000000000000000000000000000000000000000000000000000000000010201c0000000000000000000000000000000000000000000000000000000000102026000000000000000000000000000000000000000000000000000000000010201d0000000000000000000000000000000000000000000000000000000000102027000000000000000000000000000000000000000000000000000000000010201e0000000000000000000000000000000000000000000000000000000000102028000000000000000000000000000000000000000000000000000000000010201f00000000000000000000000000000000000000000000000000000000001020290000000000000000000000000000000000000000000000000000000000102020000000000000000000000000000000000000000000000000000000000010202a0000000000000000000000000000000000000000000000000000000000102021000000000000000000000000000000000000000000000000000000000010202b0000000000000000000000000000000000000000000000000000000000102022000000000000000000000000000000000000000000000000000000000010202c0000000000000000000000000000000000000000000000000000000000102023000000000000000000000000000000000000000000000000000000000010202d0000000000000000000000000000000000000000000000000000000000102024000000000000000000000000000000000000000000000000000000000010202e0000000000000000000000000000000000000000000000000000000000102025000000000000000000000000000000000000000000000000000000000010202f00000000000000000000000000000000000000000000000000000000001020260000000000000000000000000000000000000000000000000000000000102030000000000000000000000000000000000000000000000000000000000010202700000000000000000000000000000000000000000000000000000000001020310000000000000000000000000000000000000000000000000000000000102028000000000000000000000000000000000000000000000000000000000010203200000000000000000000000000000000000000000000000000000000001020290000000000000000000000000000000000000000000000000000000000102033000000000000000000000000000000000000000000000000000000000010202a0000000000000000000000000000000000000000000000000000000000102034000000000000000000000000000000000000000000000000000000000010202b0000000000000000000000000000000000000000000000000000000000102035000000000000000000000000000000000000000000000000000000000010202c0000000000000000000000000000000000000000000000000000000000102036000000000000000000000000000000000000000000000000000000000010202d0000000000000000000000000000000000000000000000000000000000102037000000000000000000000000000000000000000000000000000000000010202e0000000000000000000000000000000000000000000000000000000000102038000000000000000000000000000000000000000000000000000000000010202f00000000000000000000000000000000000000000000000000000000001020390000000000000000000000000000000000000000000000000000000000102030000000000000000000000000000000000000000000000000000000000010203a0000000000000000000000000000000000000000000000000000000000102031000000000000000000000000000000000000000000000000000000000010203b0000000000000000000000000000000000000000000000000000000000102032000000000000000000000000000000000000000000000000000000000010203c0000000000000000000000000000000000000000000000000000000000102033000000000000000000000000000000000000000000000000000000000010203d0000000000000000000000000000000000000000000000000000000000102034000000000000000000000000000000000000000000000000000000000010203e0000000000000000000000000000000000000000000000000000000000102035000000000000000000000000000000000000000000000000000000000010203f00000000000000000000000000000000000000000000000000000000001020360000000000000000000000000000000000000000000000000000000000102040000000000000000000000000000000000000000000000000000000000010203700000000000000000000000000000000000000000000000000000000001020410000000000000000000000000000000000000000000000000000000000102038000000000000000000000000000000000000000000000000000000000010204200000000000000000000000000000000000000000000000000000000001020390000000000000000000000000000000000000000000000000000000000102043000000000000000000000000000000000000000000000000000000000010203a0000000000000000000000000000000000000000000000000000000000102044000000000000000000000000000000000000000000000000000000000010203b0000000000000000000000000000000000000000000000000000000000102045000000000000000000000000000000000000000000000000000000000010203c0000000000000000000000000000000000000000000000000000000000102046000000000000000000000000000000000000000000000000000000000010203d0000000000000000000000000000000000000000000000000000000000102047000000000000000000000000000000000000000000000000000000000010203e0000000000000000000000000000000000000000000000000000000000102048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000014100100000000000000000000000000000000000000000000000000000000001410020000000000000000000000000000000000000000000000000000000000141003000000000000000000000000000000000000000000000000000000000014100400000000000000000000000000000000000000000000000000000000001410050000000000000000000000000000000000000000000000000000000000141006000000000000000000000000000000000000000000000000000000000014100700000000000000000000000000000000000000000000000000000000001410080000000000000000000000000000000000000000000000000000000000141009000000000000000000000000000000000000000000000000000000000014100a000000000000000000000000000000000000000000000000000000000014100b000000000000000000000000000000000000000000000000000000000014100c000000000000000000000000000000000000000000000000000000000014100d000000000000000000000000000000000000000000000000000000000014100e000000000000000000000000000000000000000000000000000000000014100f0000000000000000000000000000000000000000000000000000000000141010000000000000000000000000000000000000000000000000000000000014101100000000000000000000000000000000000000000000000000000000001410120000000000000000000000000000000000000000000000000000000000141013000000000000000000000000000000000000000000000000000000000014101400000000000000000000000000000000000000000000000000000000001410150000000000000000000000000000000000000000000000000000000000141016000000000000000000000000000000000000000000000000000000000014101700000000000000000000000000000000000000000000000000000000001410180000000000000000000000000000000000000000000000000000000000141019000000000000000000000000000000000000000000000000000000000014101a000000000000000000000000000000000000000000000000000000000014101b000000000000000000000000000000000000000000000000000000000014101c000000000000000000000000000000000000000000000000000000000014101d000000000000000000000000000000000000000000000000000000000014101e000000000000000000000000000000000000000000000000000000000014101f0000000000000000000000000000000000000000000000000000000000141020000000000000000000000000000000000000000000000000000000000014102100000000000000000000000000000000000000000000000000000000001410220000000000000000000000000000000000000000000000000000000000141023000000000000000000000000000000000000000000000000000000000014102400000000000000000000000000000000000000000000000000000000001410250000000000000000000000000000000000000000000000000000000000141026000000000000000000000000000000000000000000000000000000000014102700000000000000000000000000000000000000000000000000000000001410280000000000000000000000000000000000000000000000000000000000141029000000000000000000000000000000000000000000000000000000000014102a000000000000000000000000000000000000000000000000000000000014102b000000000000000000000000000000000000000000000000000000000014102c000000000000000000000000000000000000000000000000000000000014102d000000000000000000000000000000000000000000000000000000000014102e000000000000000000000000000000000000000000000000000000000014102f0000000000000000000000000000000000000000000000000000000000141030000000000000000000000000000000000000000000000000000000000014103100000000000000000000000000000000000000000000000000000000001410320000000000000000000000000000000000000000000000000000000000141033000000000000000000000000000000000000000000000000000000000014103400000000000000000000000000000000000000000000000000000000001410350000000000000000000000000000000000000000000000000000000000141036000000000000000000000000000000000000000000000000000000000014103700000000000000000000000000000000000000000000000000000000001410380000000000000000000000000000000000000000000000000000000000141039000000000000000000000000000000000000000000000000000000000014103a000000000000000000000000000000000000000000000000000000000014103b000000000000000000000000000000000000000000000000000000000014103c000000000000000000000000000000000000000000000000000000000014103d000000000000000000000000000000000000000000000000000000000014103e000000000000000000000000000000000000000000000000000000000014103f3f0000000000000000000000000000000000000000000000000000000000141100000000000000000000000000000000000000000000000000000000000014110100000000000000000000000000000000000000000000000000000000001411020000000000000000000000000000000000000000000000000000000000141103000000000000000000000000000000000000000000000000000000000014110400000000000000000000000000000000000000000000000000000000001411050000000000000000000000000000000000000000000000000000000000141106000000000000000000000000000000000000000000000000000000000014110700000000000000000000000000000000000000000000000000000000001411080000000000000000000000000000000000000000000000000000000000141109000000000000000000000000000000000000000000000000000000000014110a000000000000000000000000000000000000000000000000000000000014110b000000000000000000000000000000000000000000000000000000000014110c000000000000000000000000000000000000000000000000000000000014110d000000000000000000000000000000000000000000000000000000000014110e000000000000000000000000000000000000000000000000000000000014110f0000000000000000000000000000000000000000000000000000000000141110000000000000000000000000000000000000000000000000000000000014111100000000000000000000000000000000000000000000000000000000001411120000000000000000000000000000000000000000000000000000000000141113000000000000000000000000000000000000000000000000000000000014111400000000000000000000000000000000000000000000000000000000001411150000000000000000000000000000000000000000000000000000000000141116000000000000000000000000000000000000000000000000000000000014111700000000000000000000000000000000000000000000000000000000001411180000000000000000000000000000000000000000000000000000000000141119000000000000000000000000000000000000000000000000000000000014111a000000000000000000000000000000000000000000000000000000000014111b000000000000000000000000000000000000000000000000000000000014111c000000000000000000000000000000000000000000000000000000000014111d000000000000000000000000000000000000000000000000000000000014111e000000000000000000000000000000000000000000000000000000000014111f0000000000000000000000000000000000000000000000000000000000141120000000000000000000000000000000000000000000000000000000000014112100000000000000000000000000000000000000000000000000000000001411220000000000000000000000000000000000000000000000000000000000141123000000000000000000000000000000000000000000000000000000000014112400000000000000000000000000000000000000000000000000000000001411250000000000000000000000000000000000000000000000000000000000141126000000000000000000000000000000000000000000000000000000000014112700000000000000000000000000000000000000000000000000000000001411280000000000000000000000000000000000000000000000000000000000141129000000000000000000000000000000000000000000000000000000000014112a000000000000000000000000000000000000000000000000000000000014112b000000000000000000000000000000000000000000000000000000000014112c000000000000000000000000000000000000000000000000000000000014112d000000000000000000000000000000000000000000000000000000000014112e000000000000000000000000000000000000000000000000000000000014112f0000000000000000000000000000000000000000000000000000000000141130000000000000000000000000000000000000000000000000000000000014113100000000000000000000000000000000000000000000000000000000001411320000000000000000000000000000000000000000000000000000000000141133000000000000000000000000000000000000000000000000000000000014113400000000000000000000000000000000000000000000000000000000001411350000000000000000000000000000000000000000000000000000000000141136000000000000000000000000000000000000000000000000000000000014113700000000000000000000000000000000000000000000000000000000001411380000000000000000000000000000000000000000000000000000000000141139000000000000000000000000000000000000000000000000000000000014113a000000000000000000000000000000000000000000000000000000000014113b000000000000000000000000000000000000000000000000000000000014113c000000000000000000000000000000000000000000000000000000000014113d000000000000000000000000000000000000000000000000000000000014113e08005c015113cb57d67dd6c0febd596819ac0298b6a23fc80aba17d445d540059a00f20b7d1308051fe7b68031a7c336b0b4b56738928b6510133aff1b818d5a9a0063eec1883a4f95f4933f9275e850d84b3d035f5061ed986c437a07331fd30e00d3a32d6bbc4fd843686fd0c5e118a73b847529977dca5b9e0e81f6604f22ca00c2f4f5133d9194d41e853e5e951e16690babce8461f25342c0bad20f2aa1e3000a6bf4739e7eb387913d955dc2e8f14f8cce27696b9d2e128b6acefafb80ee005763f7e0648f958b559677622a648f318fc79ebc0cb539170d49c26456e69200302e2b8a92cda941e9af8761b89899a58a587656d9710594e1d865b16522993f0000000000000000000000000000000000000000000000000000000000142000000000000000000000000000000000000000000000000000000000000014200a0000000000000000000000000000000000000000000000000000000000142001000000000000000000000000000000000000000000000000000000000014200b0000000000000000000000000000000000000000000000000000000000142002000000000000000000000000000000000000000000000000000000000014200c0000000000000000000000000000000000000000000000000000000000142003000000000000000000000000000000000000000000000000000000000014200d0000000000000000000000000000000000000000000000000000000000142004000000000000000000000000000000000000000000000000000000000014200e0000000000000000000000000000000000000000000000000000000000142005000000000000000000000000000000000000000000000000000000000014200f00000000000000000000000000000000000000000000000000000000001420060000000000000000000000000000000000000000000000000000000000142010000000000000000000000000000000000000000000000000000000000014200700000000000000000000000000000000000000000000000000000000001420110000000000000000000000000000000000000000000000000000000000142008000000000000000000000000000000000000000000000000000000000014201200000000000000000000000000000000000000000000000000000000001420090000000000000000000000000000000000000000000000000000000000142013000000000000000000000000000000000000000000000000000000000014200a0000000000000000000000000000000000000000000000000000000000142014000000000000000000000000000000000000000000000000000000000014200b0000000000000000000000000000000000000000000000000000000000142015000000000000000000000000000000000000000000000000000000000014200c0000000000000000000000000000000000000000000000000000000000142016000000000000000000000000000000000000000000000000000000000014200d0000000000000000000000000000000000000000000000000000000000142017000000000000000000000000000000000000000000000000000000000014200e0000000000000000000000000000000000000000000000000000000000142018000000000000000000000000000000000000000000000000000000000014200f00000000000000000000000000000000000000000000000000000000001420190000000000000000000000000000000000000000000000000000000000142010000000000000000000000000000000000000000000000000000000000014201a0000000000000000000000000000000000000000000000000000000000142011000000000000000000000000000000000000000000000000000000000014201b0000000000000000000000000000000000000000000000000000000000142012000000000000000000000000000000000000000000000000000000000014201c0000000000000000000000000000000000000000000000000000000000142013000000000000000000000000000000000000000000000000000000000014201d0000000000000000000000000000000000000000000000000000000000142014000000000000000000000000000000000000000000000000000000000014201e0000000000000000000000000000000000000000000000000000000000142015000000000000000000000000000000000000000000000000000000000014201f00000000000000000000000000000000000000000000000000000000001420160000000000000000000000000000000000000000000000000000000000142020000000000000000000000000000000000000000000000000000000000014201700000000000000000000000000000000000000000000000000000000001420210000000000000000000000000000000000000000000000000000000000142018000000000000000000000000000000000000000000000000000000000014202200000000000000000000000000000000000000000000000000000000001420190000000000000000000000000000000000000000000000000000000000142023000000000000000000000000000000000000000000000000000000000014201a0000000000000000000000000000000000000000000000000000000000142024000000000000000000000000000000000000000000000000000000000014201b0000000000000000000000000000000000000000000000000000000000142025000000000000000000000000000000000000000000000000000000000014201c0000000000000000000000000000000000000000000000000000000000142026000000000000000000000000000000000000000000000000000000000014201d0000000000000000000000000000000000000000000000000000000000142027000000000000000000000000000000000000000000000000000000000014201e0000000000000000000000000000000000000000000000000000000000142028000000000000000000000000000000000000000000000000000000000014201f00000000000000000000000000000000000000000000000000000000001420290000000000000000000000000000000000000000000000000000000000142020000000000000000000000000000000000000000000000000000000000014202a0000000000000000000000000000000000000000000000000000000000142021000000000000000000000000000000000000000000000000000000000014202b0000000000000000000000000000000000000000000000000000000000142022000000000000000000000000000000000000000000000000000000000014202c0000000000000000000000000000000000000000000000000000000000142023000000000000000000000000000000000000000000000000000000000014202d0000000000000000000000000000000000000000000000000000000000142024000000000000000000000000000000000000000000000000000000000014202e0000000000000000000000000000000000000000000000000000000000142025000000000000000000000000000000000000000000000000000000000014202f00000000000000000000000000000000000000000000000000000000001420260000000000000000000000000000000000000000000000000000000000142030000000000000000000000000000000000000000000000000000000000014202700000000000000000000000000000000000000000000000000000000001420310000000000000000000000000000000000000000000000000000000000142028000000000000000000000000000000000000000000000000000000000014203200000000000000000000000000000000000000000000000000000000001420290000000000000000000000000000000000000000000000000000000000142033000000000000000000000000000000000000000000000000000000000014202a0000000000000000000000000000000000000000000000000000000000142034000000000000000000000000000000000000000000000000000000000014202b0000000000000000000000000000000000000000000000000000000000142035000000000000000000000000000000000000000000000000000000000014202c0000000000000000000000000000000000000000000000000000000000142036000000000000000000000000000000000000000000000000000000000014202d0000000000000000000000000000000000000000000000000000000000142037000000000000000000000000000000000000000000000000000000000014202e0000000000000000000000000000000000000000000000000000000000142038000000000000000000000000000000000000000000000000000000000014202f00000000000000000000000000000000000000000000000000000000001420390000000000000000000000000000000000000000000000000000000000142030000000000000000000000000000000000000000000000000000000000014203a0000000000000000000000000000000000000000000000000000000000142031000000000000000000000000000000000000000000000000000000000014203b0000000000000000000000000000000000000000000000000000000000142032000000000000000000000000000000000000000000000000000000000014203c0000000000000000000000000000000000000000000000000000000000142033000000000000000000000000000000000000000000000000000000000014203d0000000000000000000000000000000000000000000000000000000000142034000000000000000000000000000000000000000000000000000000000014203e0000000000000000000000000000000000000000000000000000000000142035000000000000000000000000000000000000000000000000000000000014203f00000000000000000000000000000000000000000000000000000000001420360000000000000000000000000000000000000000000000000000000000142040000000000000000000000000000000000000000000000000000000000014203700000000000000000000000000000000000000000000000000000000001420410000000000000000000000000000000000000000000000000000000000142038000000000000000000000000000000000000000000000000000000000014204200000000000000000000000000000000000000000000000000000000001420390000000000000000000000000000000000000000000000000000000000142043000000000000000000000000000000000000000000000000000000000014203a0000000000000000000000000000000000000000000000000000000000142044000000000000000000000000000000000000000000000000000000000014203b0000000000000000000000000000000000000000000000000000000000142045000000000000000000000000000000000000000000000000000000000014203c0000000000000000000000000000000000000000000000000000000000142046000000000000000000000000000000000000000000000000000000000014203d0000000000000000000000000000000000000000000000000000000000142047000000000000000000000000000000000000000000000000000000000014203e0000000000000000000000000000000000000000000000000000000000142048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000181000000000000000000000000000000000000000000000000000000000000018100100000000000000000000000000000000000000000000000000000000001810020000000000000000000000000000000000000000000000000000000000181003000000000000000000000000000000000000000000000000000000000018100400000000000000000000000000000000000000000000000000000000001810050000000000000000000000000000000000000000000000000000000000181006000000000000000000000000000000000000000000000000000000000018100700000000000000000000000000000000000000000000000000000000001810080000000000000000000000000000000000000000000000000000000000181009000000000000000000000000000000000000000000000000000000000018100a000000000000000000000000000000000000000000000000000000000018100b000000000000000000000000000000000000000000000000000000000018100c000000000000000000000000000000000000000000000000000000000018100d000000000000000000000000000000000000000000000000000000000018100e000000000000000000000000000000000000000000000000000000000018100f0000000000000000000000000000000000000000000000000000000000181010000000000000000000000000000000000000000000000000000000000018101100000000000000000000000000000000000000000000000000000000001810120000000000000000000000000000000000000000000000000000000000181013000000000000000000000000000000000000000000000000000000000018101400000000000000000000000000000000000000000000000000000000001810150000000000000000000000000000000000000000000000000000000000181016000000000000000000000000000000000000000000000000000000000018101700000000000000000000000000000000000000000000000000000000001810180000000000000000000000000000000000000000000000000000000000181019000000000000000000000000000000000000000000000000000000000018101a000000000000000000000000000000000000000000000000000000000018101b000000000000000000000000000000000000000000000000000000000018101c000000000000000000000000000000000000000000000000000000000018101d000000000000000000000000000000000000000000000000000000000018101e000000000000000000000000000000000000000000000000000000000018101f0000000000000000000000000000000000000000000000000000000000181020000000000000000000000000000000000000000000000000000000000018102100000000000000000000000000000000000000000000000000000000001810220000000000000000000000000000000000000000000000000000000000181023000000000000000000000000000000000000000000000000000000000018102400000000000000000000000000000000000000000000000000000000001810250000000000000000000000000000000000000000000000000000000000181026000000000000000000000000000000000000000000000000000000000018102700000000000000000000000000000000000000000000000000000000001810280000000000000000000000000000000000000000000000000000000000181029000000000000000000000000000000000000000000000000000000000018102a000000000000000000000000000000000000000000000000000000000018102b000000000000000000000000000000000000000000000000000000000018102c000000000000000000000000000000000000000000000000000000000018102d000000000000000000000000000000000000000000000000000000000018102e000000000000000000000000000000000000000000000000000000000018102f0000000000000000000000000000000000000000000000000000000000181030000000000000000000000000000000000000000000000000000000000018103100000000000000000000000000000000000000000000000000000000001810320000000000000000000000000000000000000000000000000000000000181033000000000000000000000000000000000000000000000000000000000018103400000000000000000000000000000000000000000000000000000000001810350000000000000000000000000000000000000000000000000000000000181036000000000000000000000000000000000000000000000000000000000018103700000000000000000000000000000000000000000000000000000000001810380000000000000000000000000000000000000000000000000000000000181039000000000000000000000000000000000000000000000000000000000018103a000000000000000000000000000000000000000000000000000000000018103b000000000000000000000000000000000000000000000000000000000018103c000000000000000000000000000000000000000000000000000000000018103d000000000000000000000000000000000000000000000000000000000018103e000000000000000000000000000000000000000000000000000000000018103f3f0000000000000000000000000000000000000000000000000000000000181100000000000000000000000000000000000000000000000000000000000018110100000000000000000000000000000000000000000000000000000000001811020000000000000000000000000000000000000000000000000000000000181103000000000000000000000000000000000000000000000000000000000018110400000000000000000000000000000000000000000000000000000000001811050000000000000000000000000000000000000000000000000000000000181106000000000000000000000000000000000000000000000000000000000018110700000000000000000000000000000000000000000000000000000000001811080000000000000000000000000000000000000000000000000000000000181109000000000000000000000000000000000000000000000000000000000018110a000000000000000000000000000000000000000000000000000000000018110b000000000000000000000000000000000000000000000000000000000018110c000000000000000000000000000000000000000000000000000000000018110d000000000000000000000000000000000000000000000000000000000018110e000000000000000000000000000000000000000000000000000000000018110f0000000000000000000000000000000000000000000000000000000000181110000000000000000000000000000000000000000000000000000000000018111100000000000000000000000000000000000000000000000000000000001811120000000000000000000000000000000000000000000000000000000000181113000000000000000000000000000000000000000000000000000000000018111400000000000000000000000000000000000000000000000000000000001811150000000000000000000000000000000000000000000000000000000000181116000000000000000000000000000000000000000000000000000000000018111700000000000000000000000000000000000000000000000000000000001811180000000000000000000000000000000000000000000000000000000000181119000000000000000000000000000000000000000000000000000000000018111a000000000000000000000000000000000000000000000000000000000018111b000000000000000000000000000000000000000000000000000000000018111c000000000000000000000000000000000000000000000000000000000018111d000000000000000000000000000000000000000000000000000000000018111e000000000000000000000000000000000000000000000000000000000018111f0000000000000000000000000000000000000000000000000000000000181120000000000000000000000000000000000000000000000000000000000018112100000000000000000000000000000000000000000000000000000000001811220000000000000000000000000000000000000000000000000000000000181123000000000000000000000000000000000000000000000000000000000018112400000000000000000000000000000000000000000000000000000000001811250000000000000000000000000000000000000000000000000000000000181126000000000000000000000000000000000000000000000000000000000018112700000000000000000000000000000000000000000000000000000000001811280000000000000000000000000000000000000000000000000000000000181129000000000000000000000000000000000000000000000000000000000018112a000000000000000000000000000000000000000000000000000000000018112b000000000000000000000000000000000000000000000000000000000018112c000000000000000000000000000000000000000000000000000000000018112d000000000000000000000000000000000000000000000000000000000018112e000000000000000000000000000000000000000000000000000000000018112f0000000000000000000000000000000000000000000000000000000000181130000000000000000000000000000000000000000000000000000000000018113100000000000000000000000000000000000000000000000000000000001811320000000000000000000000000000000000000000000000000000000000181133000000000000000000000000000000000000000000000000000000000018113400000000000000000000000000000000000000000000000000000000001811350000000000000000000000000000000000000000000000000000000000181136000000000000000000000000000000000000000000000000000000000018113700000000000000000000000000000000000000000000000000000000001811380000000000000000000000000000000000000000000000000000000000181139000000000000000000000000000000000000000000000000000000000018113a000000000000000000000000000000000000000000000000000000000018113b000000000000000000000000000000000000000000000000000000000018113c000000000000000000000000000000000000000000000000000000000018113d000000000000000000000000000000000000000000000000000000000018113e0800f872eb9653f03af10f331da1361fa1524d3cd958cb72dacea1d424f19df3af00ffc548a17cd6ba1f2d228f30e4ddb19ecc46ad3b609977d52bb0f49e1206410032f8058bd779c520eabae2743b02ec4f71670428506fcceb2d4b69f26fb11800c0283e15fbf74ffa4eafb984030394f3c2ea6733cc0eacb0431a9475eff28f00b7f55314bfd9d441c1c624e241908228fe4da3d3a0a7fbd56814e1c8cd5d3e00f430f33a786675271736fd728c7bf7428b8c24ac948d7faf76ddb8783a496c0048fc235ead8d4b9d44929662a6384074fc4e5076bec5b7deb34f612393684300fd9b61cb1ad9b4b28f58399906e73933e3cccee8fc98a393f0eedb95b13ee63f0000000000000000000000000000000000000000000000000000000000182000000000000000000000000000000000000000000000000000000000000018200a0000000000000000000000000000000000000000000000000000000000182001000000000000000000000000000000000000000000000000000000000018200b0000000000000000000000000000000000000000000000000000000000182002000000000000000000000000000000000000000000000000000000000018200c0000000000000000000000000000000000000000000000000000000000182003000000000000000000000000000000000000000000000000000000000018200d0000000000000000000000000000000000000000000000000000000000182004000000000000000000000000000000000000000000000000000000000018200e0000000000000000000000000000000000000000000000000000000000182005000000000000000000000000000000000000000000000000000000000018200f00000000000000000000000000000000000000000000000000000000001820060000000000000000000000000000000000000000000000000000000000182010000000000000000000000000000000000000000000000000000000000018200700000000000000000000000000000000000000000000000000000000001820110000000000000000000000000000000000000000000000000000000000182008000000000000000000000000000000000000000000000000000000000018201200000000000000000000000000000000000000000000000000000000001820090000000000000000000000000000000000000000000000000000000000182013000000000000000000000000000000000000000000000000000000000018200a0000000000000000000000000000000000000000000000000000000000182014000000000000000000000000000000000000000000000000000000000018200b0000000000000000000000000000000000000000000000000000000000182015000000000000000000000000000000000000000000000000000000000018200c0000000000000000000000000000000000000000000000000000000000182016000000000000000000000000000000000000000000000000000000000018200d0000000000000000000000000000000000000000000000000000000000182017000000000000000000000000000000000000000000000000000000000018200e0000000000000000000000000000000000000000000000000000000000182018000000000000000000000000000000000000000000000000000000000018200f00000000000000000000000000000000000000000000000000000000001820190000000000000000000000000000000000000000000000000000000000182010000000000000000000000000000000000000000000000000000000000018201a0000000000000000000000000000000000000000000000000000000000182011000000000000000000000000000000000000000000000000000000000018201b0000000000000000000000000000000000000000000000000000000000182012000000000000000000000000000000000000000000000000000000000018201c0000000000000000000000000000000000000000000000000000000000182013000000000000000000000000000000000000000000000000000000000018201d0000000000000000000000000000000000000000000000000000000000182014000000000000000000000000000000000000000000000000000000000018201e0000000000000000000000000000000000000000000000000000000000182015000000000000000000000000000000000000000000000000000000000018201f00000000000000000000000000000000000000000000000000000000001820160000000000000000000000000000000000000000000000000000000000182020000000000000000000000000000000000000000000000000000000000018201700000000000000000000000000000000000000000000000000000000001820210000000000000000000000000000000000000000000000000000000000182018000000000000000000000000000000000000000000000000000000000018202200000000000000000000000000000000000000000000000000000000001820190000000000000000000000000000000000000000000000000000000000182023000000000000000000000000000000000000000000000000000000000018201a0000000000000000000000000000000000000000000000000000000000182024000000000000000000000000000000000000000000000000000000000018201b0000000000000000000000000000000000000000000000000000000000182025000000000000000000000000000000000000000000000000000000000018201c0000000000000000000000000000000000000000000000000000000000182026000000000000000000000000000000000000000000000000000000000018201d0000000000000000000000000000000000000000000000000000000000182027000000000000000000000000000000000000000000000000000000000018201e0000000000000000000000000000000000000000000000000000000000182028000000000000000000000000000000000000000000000000000000000018201f00000000000000000000000000000000000000000000000000000000001820290000000000000000000000000000000000000000000000000000000000182020000000000000000000000000000000000000000000000000000000000018202a0000000000000000000000000000000000000000000000000000000000182021000000000000000000000000000000000000000000000000000000000018202b0000000000000000000000000000000000000000000000000000000000182022000000000000000000000000000000000000000000000000000000000018202c0000000000000000000000000000000000000000000000000000000000182023000000000000000000000000000000000000000000000000000000000018202d0000000000000000000000000000000000000000000000000000000000182024000000000000000000000000000000000000000000000000000000000018202e0000000000000000000000000000000000000000000000000000000000182025000000000000000000000000000000000000000000000000000000000018202f00000000000000000000000000000000000000000000000000000000001820260000000000000000000000000000000000000000000000000000000000182030000000000000000000000000000000000000000000000000000000000018202700000000000000000000000000000000000000000000000000000000001820310000000000000000000000000000000000000000000000000000000000182028000000000000000000000000000000000000000000000000000000000018203200000000000000000000000000000000000000000000000000000000001820290000000000000000000000000000000000000000000000000000000000182033000000000000000000000000000000000000000000000000000000000018202a0000000000000000000000000000000000000000000000000000000000182034000000000000000000000000000000000000000000000000000000000018202b0000000000000000000000000000000000000000000000000000000000182035000000000000000000000000000000000000000000000000000000000018202c0000000000000000000000000000000000000000000000000000000000182036000000000000000000000000000000000000000000000000000000000018202d0000000000000000000000000000000000000000000000000000000000182037000000000000000000000000000000000000000000000000000000000018202e0000000000000000000000000000000000000000000000000000000000182038000000000000000000000000000000000000000000000000000000000018202f00000000000000000000000000000000000000000000000000000000001820390000000000000000000000000000000000000000000000000000000000182030000000000000000000000000000000000000000000000000000000000018203a0000000000000000000000000000000000000000000000000000000000182031000000000000000000000000000000000000000000000000000000000018203b0000000000000000000000000000000000000000000000000000000000182032000000000000000000000000000000000000000000000000000000000018203c0000000000000000000000000000000000000000000000000000000000182033000000000000000000000000000000000000000000000000000000000018203d0000000000000000000000000000000000000000000000000000000000182034000000000000000000000000000000000000000000000000000000000018203e0000000000000000000000000000000000000000000000000000000000182035000000000000000000000000000000000000000000000000000000000018203f00000000000000000000000000000000000000000000000000000000001820360000000000000000000000000000000000000000000000000000000000182040000000000000000000000000000000000000000000000000000000000018203700000000000000000000000000000000000000000000000000000000001820410000000000000000000000000000000000000000000000000000000000182038000000000000000000000000000000000000000000000000000000000018204200000000000000000000000000000000000000000000000000000000001820390000000000000000000000000000000000000000000000000000000000182043000000000000000000000000000000000000000000000000000000000018203a0000000000000000000000000000000000000000000000000000000000182044000000000000000000000000000000000000000000000000000000000018203b0000000000000000000000000000000000000000000000000000000000182045000000000000000000000000000000000000000000000000000000000018203c0000000000000000000000000000000000000000000000000000000000182046000000000000000000000000000000000000000000000000000000000018203d0000000000000000000000000000000000000000000000000000000000182047000000000000000000000000000000000000000000000000000000000018203e00000000000000000000000000000000000000000000000000000000001820480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c100100000000000000000000000000000000000000000000000000000000001c100200000000000000000000000000000000000000000000000000000000001c100300000000000000000000000000000000000000000000000000000000001c100400000000000000000000000000000000000000000000000000000000001c100500000000000000000000000000000000000000000000000000000000001c100600000000000000000000000000000000000000000000000000000000001c100700000000000000000000000000000000000000000000000000000000001c100800000000000000000000000000000000000000000000000000000000001c100900000000000000000000000000000000000000000000000000000000001c100a00000000000000000000000000000000000000000000000000000000001c100b00000000000000000000000000000000000000000000000000000000001c100c00000000000000000000000000000000000000000000000000000000001c100d00000000000000000000000000000000000000000000000000000000001c100e00000000000000000000000000000000000000000000000000000000001c100f00000000000000000000000000000000000000000000000000000000001c101000000000000000000000000000000000000000000000000000000000001c101100000000000000000000000000000000000000000000000000000000001c101200000000000000000000000000000000000000000000000000000000001c101300000000000000000000000000000000000000000000000000000000001c101400000000000000000000000000000000000000000000000000000000001c101500000000000000000000000000000000000000000000000000000000001c101600000000000000000000000000000000000000000000000000000000001c101700000000000000000000000000000000000000000000000000000000001c101800000000000000000000000000000000000000000000000000000000001c101900000000000000000000000000000000000000000000000000000000001c101a00000000000000000000000000000000000000000000000000000000001c101b00000000000000000000000000000000000000000000000000000000001c101c00000000000000000000000000000000000000000000000000000000001c101d00000000000000000000000000000000000000000000000000000000001c101e00000000000000000000000000000000000000000000000000000000001c101f00000000000000000000000000000000000000000000000000000000001c102000000000000000000000000000000000000000000000000000000000001c102100000000000000000000000000000000000000000000000000000000001c102200000000000000000000000000000000000000000000000000000000001c102300000000000000000000000000000000000000000000000000000000001c102400000000000000000000000000000000000000000000000000000000001c102500000000000000000000000000000000000000000000000000000000001c102600000000000000000000000000000000000000000000000000000000001c102700000000000000000000000000000000000000000000000000000000001c102800000000000000000000000000000000000000000000000000000000001c102900000000000000000000000000000000000000000000000000000000001c102a00000000000000000000000000000000000000000000000000000000001c102b00000000000000000000000000000000000000000000000000000000001c102c00000000000000000000000000000000000000000000000000000000001c102d00000000000000000000000000000000000000000000000000000000001c102e00000000000000000000000000000000000000000000000000000000001c102f00000000000000000000000000000000000000000000000000000000001c103000000000000000000000000000000000000000000000000000000000001c103100000000000000000000000000000000000000000000000000000000001c103200000000000000000000000000000000000000000000000000000000001c103300000000000000000000000000000000000000000000000000000000001c103400000000000000000000000000000000000000000000000000000000001c103500000000000000000000000000000000000000000000000000000000001c103600000000000000000000000000000000000000000000000000000000001c103700000000000000000000000000000000000000000000000000000000001c103800000000000000000000000000000000000000000000000000000000001c103900000000000000000000000000000000000000000000000000000000001c103a00000000000000000000000000000000000000000000000000000000001c103b00000000000000000000000000000000000000000000000000000000001c103c00000000000000000000000000000000000000000000000000000000001c103d00000000000000000000000000000000000000000000000000000000001c103e00000000000000000000000000000000000000000000000000000000001c103f3f00000000000000000000000000000000000000000000000000000000001c110000000000000000000000000000000000000000000000000000000000001c110100000000000000000000000000000000000000000000000000000000001c110200000000000000000000000000000000000000000000000000000000001c110300000000000000000000000000000000000000000000000000000000001c110400000000000000000000000000000000000000000000000000000000001c110500000000000000000000000000000000000000000000000000000000001c110600000000000000000000000000000000000000000000000000000000001c110700000000000000000000000000000000000000000000000000000000001c110800000000000000000000000000000000000000000000000000000000001c110900000000000000000000000000000000000000000000000000000000001c110a00000000000000000000000000000000000000000000000000000000001c110b00000000000000000000000000000000000000000000000000000000001c110c00000000000000000000000000000000000000000000000000000000001c110d00000000000000000000000000000000000000000000000000000000001c110e00000000000000000000000000000000000000000000000000000000001c110f00000000000000000000000000000000000000000000000000000000001c111000000000000000000000000000000000000000000000000000000000001c111100000000000000000000000000000000000000000000000000000000001c111200000000000000000000000000000000000000000000000000000000001c111300000000000000000000000000000000000000000000000000000000001c111400000000000000000000000000000000000000000000000000000000001c111500000000000000000000000000000000000000000000000000000000001c111600000000000000000000000000000000000000000000000000000000001c111700000000000000000000000000000000000000000000000000000000001c111800000000000000000000000000000000000000000000000000000000001c111900000000000000000000000000000000000000000000000000000000001c111a00000000000000000000000000000000000000000000000000000000001c111b00000000000000000000000000000000000000000000000000000000001c111c00000000000000000000000000000000000000000000000000000000001c111d00000000000000000000000000000000000000000000000000000000001c111e00000000000000000000000000000000000000000000000000000000001c111f00000000000000000000000000000000000000000000000000000000001c112000000000000000000000000000000000000000000000000000000000001c112100000000000000000000000000000000000000000000000000000000001c112200000000000000000000000000000000000000000000000000000000001c112300000000000000000000000000000000000000000000000000000000001c112400000000000000000000000000000000000000000000000000000000001c112500000000000000000000000000000000000000000000000000000000001c112600000000000000000000000000000000000000000000000000000000001c112700000000000000000000000000000000000000000000000000000000001c112800000000000000000000000000000000000000000000000000000000001c112900000000000000000000000000000000000000000000000000000000001c112a00000000000000000000000000000000000000000000000000000000001c112b00000000000000000000000000000000000000000000000000000000001c112c00000000000000000000000000000000000000000000000000000000001c112d00000000000000000000000000000000000000000000000000000000001c112e00000000000000000000000000000000000000000000000000000000001c112f00000000000000000000000000000000000000000000000000000000001c113000000000000000000000000000000000000000000000000000000000001c113100000000000000000000000000000000000000000000000000000000001c113200000000000000000000000000000000000000000000000000000000001c113300000000000000000000000000000000000000000000000000000000001c113400000000000000000000000000000000000000000000000000000000001c113500000000000000000000000000000000000000000000000000000000001c113600000000000000000000000000000000000000000000000000000000001c113700000000000000000000000000000000000000000000000000000000001c113800000000000000000000000000000000000000000000000000000000001c113900000000000000000000000000000000000000000000000000000000001c113a00000000000000000000000000000000000000000000000000000000001c113b00000000000000000000000000000000000000000000000000000000001c113c00000000000000000000000000000000000000000000000000000000001c113d00000000000000000000000000000000000000000000000000000000001c113e08006838aa99533bea0d4204cad17cb3c147e99c2f9089e54a4289d54733eeada2002ab314bd11ace2494a3fb0970d276da39f0fe7da19c9a2438b9c7c334d32470071703d79d8425a7eca52006df6a8f9728508a83639e3e1c2ebae2b853a087c00c9501ac04a78ac5413c9131b08708064ed2c2515b8893f12c2d1cda15a44f100a0955f93e109778d26f9e5b0d46e45c539e59b0941517bfa888eb2d7d2d8a6005adc3be9406cc5f102c6adb44746e8529a256e2396353a8659344cc3e914c4007a5fe572cf6af804f472dabf095c5eb6b30efc5fd627ad3245a8ef0f3f578c003dcaa91dfc9fdad7ba8da68a48fc662dfc0a995cbb0c1bc62099c8257d240d3f00000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c200a00000000000000000000000000000000000000000000000000000000001c200100000000000000000000000000000000000000000000000000000000001c200b00000000000000000000000000000000000000000000000000000000001c200200000000000000000000000000000000000000000000000000000000001c200c00000000000000000000000000000000000000000000000000000000001c200300000000000000000000000000000000000000000000000000000000001c200d00000000000000000000000000000000000000000000000000000000001c200400000000000000000000000000000000000000000000000000000000001c200e00000000000000000000000000000000000000000000000000000000001c200500000000000000000000000000000000000000000000000000000000001c200f00000000000000000000000000000000000000000000000000000000001c200600000000000000000000000000000000000000000000000000000000001c201000000000000000000000000000000000000000000000000000000000001c200700000000000000000000000000000000000000000000000000000000001c201100000000000000000000000000000000000000000000000000000000001c200800000000000000000000000000000000000000000000000000000000001c201200000000000000000000000000000000000000000000000000000000001c200900000000000000000000000000000000000000000000000000000000001c201300000000000000000000000000000000000000000000000000000000001c200a00000000000000000000000000000000000000000000000000000000001c201400000000000000000000000000000000000000000000000000000000001c200b00000000000000000000000000000000000000000000000000000000001c201500000000000000000000000000000000000000000000000000000000001c200c00000000000000000000000000000000000000000000000000000000001c201600000000000000000000000000000000000000000000000000000000001c200d00000000000000000000000000000000000000000000000000000000001c201700000000000000000000000000000000000000000000000000000000001c200e00000000000000000000000000000000000000000000000000000000001c201800000000000000000000000000000000000000000000000000000000001c200f00000000000000000000000000000000000000000000000000000000001c201900000000000000000000000000000000000000000000000000000000001c201000000000000000000000000000000000000000000000000000000000001c201a00000000000000000000000000000000000000000000000000000000001c201100000000000000000000000000000000000000000000000000000000001c201b00000000000000000000000000000000000000000000000000000000001c201200000000000000000000000000000000000000000000000000000000001c201c00000000000000000000000000000000000000000000000000000000001c201300000000000000000000000000000000000000000000000000000000001c201d00000000000000000000000000000000000000000000000000000000001c201400000000000000000000000000000000000000000000000000000000001c201e00000000000000000000000000000000000000000000000000000000001c201500000000000000000000000000000000000000000000000000000000001c201f00000000000000000000000000000000000000000000000000000000001c201600000000000000000000000000000000000000000000000000000000001c202000000000000000000000000000000000000000000000000000000000001c201700000000000000000000000000000000000000000000000000000000001c202100000000000000000000000000000000000000000000000000000000001c201800000000000000000000000000000000000000000000000000000000001c202200000000000000000000000000000000000000000000000000000000001c201900000000000000000000000000000000000000000000000000000000001c202300000000000000000000000000000000000000000000000000000000001c201a00000000000000000000000000000000000000000000000000000000001c202400000000000000000000000000000000000000000000000000000000001c201b00000000000000000000000000000000000000000000000000000000001c202500000000000000000000000000000000000000000000000000000000001c201c00000000000000000000000000000000000000000000000000000000001c202600000000000000000000000000000000000000000000000000000000001c201d00000000000000000000000000000000000000000000000000000000001c202700000000000000000000000000000000000000000000000000000000001c201e00000000000000000000000000000000000000000000000000000000001c202800000000000000000000000000000000000000000000000000000000001c201f00000000000000000000000000000000000000000000000000000000001c202900000000000000000000000000000000000000000000000000000000001c202000000000000000000000000000000000000000000000000000000000001c202a00000000000000000000000000000000000000000000000000000000001c202100000000000000000000000000000000000000000000000000000000001c202b00000000000000000000000000000000000000000000000000000000001c202200000000000000000000000000000000000000000000000000000000001c202c00000000000000000000000000000000000000000000000000000000001c202300000000000000000000000000000000000000000000000000000000001c202d00000000000000000000000000000000000000000000000000000000001c202400000000000000000000000000000000000000000000000000000000001c202e00000000000000000000000000000000000000000000000000000000001c202500000000000000000000000000000000000000000000000000000000001c202f00000000000000000000000000000000000000000000000000000000001c202600000000000000000000000000000000000000000000000000000000001c203000000000000000000000000000000000000000000000000000000000001c202700000000000000000000000000000000000000000000000000000000001c203100000000000000000000000000000000000000000000000000000000001c202800000000000000000000000000000000000000000000000000000000001c203200000000000000000000000000000000000000000000000000000000001c202900000000000000000000000000000000000000000000000000000000001c203300000000000000000000000000000000000000000000000000000000001c202a00000000000000000000000000000000000000000000000000000000001c203400000000000000000000000000000000000000000000000000000000001c202b00000000000000000000000000000000000000000000000000000000001c203500000000000000000000000000000000000000000000000000000000001c202c00000000000000000000000000000000000000000000000000000000001c203600000000000000000000000000000000000000000000000000000000001c202d00000000000000000000000000000000000000000000000000000000001c203700000000000000000000000000000000000000000000000000000000001c202e00000000000000000000000000000000000000000000000000000000001c203800000000000000000000000000000000000000000000000000000000001c202f00000000000000000000000000000000000000000000000000000000001c203900000000000000000000000000000000000000000000000000000000001c203000000000000000000000000000000000000000000000000000000000001c203a00000000000000000000000000000000000000000000000000000000001c203100000000000000000000000000000000000000000000000000000000001c203b00000000000000000000000000000000000000000000000000000000001c203200000000000000000000000000000000000000000000000000000000001c203c00000000000000000000000000000000000000000000000000000000001c203300000000000000000000000000000000000000000000000000000000001c203d00000000000000000000000000000000000000000000000000000000001c203400000000000000000000000000000000000000000000000000000000001c203e00000000000000000000000000000000000000000000000000000000001c203500000000000000000000000000000000000000000000000000000000001c203f00000000000000000000000000000000000000000000000000000000001c203600000000000000000000000000000000000000000000000000000000001c204000000000000000000000000000000000000000000000000000000000001c203700000000000000000000000000000000000000000000000000000000001c204100000000000000000000000000000000000000000000000000000000001c203800000000000000000000000000000000000000000000000000000000001c204200000000000000000000000000000000000000000000000000000000001c203900000000000000000000000000000000000000000000000000000000001c204300000000000000000000000000000000000000000000000000000000001c203a00000000000000000000000000000000000000000000000000000000001c204400000000000000000000000000000000000000000000000000000000001c203b00000000000000000000000000000000000000000000000000000000001c204500000000000000000000000000000000000000000000000000000000001c203c00000000000000000000000000000000000000000000000000000000001c204600000000000000000000000000000000000000000000000000000000001c203d00000000000000000000000000000000000000000000000000000000001c204700000000000000000000000000000000000000000000000000000000001c203e00000000000000000000000000000000000000000000000000000000001c2048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000201000000000000000000000000000000000000000000000000000000000000020100100000000000000000000000000000000000000000000000000000000002010020000000000000000000000000000000000000000000000000000000000201003000000000000000000000000000000000000000000000000000000000020100400000000000000000000000000000000000000000000000000000000002010050000000000000000000000000000000000000000000000000000000000201006000000000000000000000000000000000000000000000000000000000020100700000000000000000000000000000000000000000000000000000000002010080000000000000000000000000000000000000000000000000000000000201009000000000000000000000000000000000000000000000000000000000020100a000000000000000000000000000000000000000000000000000000000020100b000000000000000000000000000000000000000000000000000000000020100c000000000000000000000000000000000000000000000000000000000020100d000000000000000000000000000000000000000000000000000000000020100e000000000000000000000000000000000000000000000000000000000020100f0000000000000000000000000000000000000000000000000000000000201010000000000000000000000000000000000000000000000000000000000020101100000000000000000000000000000000000000000000000000000000002010120000000000000000000000000000000000000000000000000000000000201013000000000000000000000000000000000000000000000000000000000020101400000000000000000000000000000000000000000000000000000000002010150000000000000000000000000000000000000000000000000000000000201016000000000000000000000000000000000000000000000000000000000020101700000000000000000000000000000000000000000000000000000000002010180000000000000000000000000000000000000000000000000000000000201019000000000000000000000000000000000000000000000000000000000020101a000000000000000000000000000000000000000000000000000000000020101b000000000000000000000000000000000000000000000000000000000020101c000000000000000000000000000000000000000000000000000000000020101d000000000000000000000000000000000000000000000000000000000020101e000000000000000000000000000000000000000000000000000000000020101f0000000000000000000000000000000000000000000000000000000000201020000000000000000000000000000000000000000000000000000000000020102100000000000000000000000000000000000000000000000000000000002010220000000000000000000000000000000000000000000000000000000000201023000000000000000000000000000000000000000000000000000000000020102400000000000000000000000000000000000000000000000000000000002010250000000000000000000000000000000000000000000000000000000000201026000000000000000000000000000000000000000000000000000000000020102700000000000000000000000000000000000000000000000000000000002010280000000000000000000000000000000000000000000000000000000000201029000000000000000000000000000000000000000000000000000000000020102a000000000000000000000000000000000000000000000000000000000020102b000000000000000000000000000000000000000000000000000000000020102c000000000000000000000000000000000000000000000000000000000020102d000000000000000000000000000000000000000000000000000000000020102e000000000000000000000000000000000000000000000000000000000020102f0000000000000000000000000000000000000000000000000000000000201030000000000000000000000000000000000000000000000000000000000020103100000000000000000000000000000000000000000000000000000000002010320000000000000000000000000000000000000000000000000000000000201033000000000000000000000000000000000000000000000000000000000020103400000000000000000000000000000000000000000000000000000000002010350000000000000000000000000000000000000000000000000000000000201036000000000000000000000000000000000000000000000000000000000020103700000000000000000000000000000000000000000000000000000000002010380000000000000000000000000000000000000000000000000000000000201039000000000000000000000000000000000000000000000000000000000020103a000000000000000000000000000000000000000000000000000000000020103b000000000000000000000000000000000000000000000000000000000020103c000000000000000000000000000000000000000000000000000000000020103d000000000000000000000000000000000000000000000000000000000020103e000000000000000000000000000000000000000000000000000000000020103f3f0000000000000000000000000000000000000000000000000000000000201100000000000000000000000000000000000000000000000000000000000020110100000000000000000000000000000000000000000000000000000000002011020000000000000000000000000000000000000000000000000000000000201103000000000000000000000000000000000000000000000000000000000020110400000000000000000000000000000000000000000000000000000000002011050000000000000000000000000000000000000000000000000000000000201106000000000000000000000000000000000000000000000000000000000020110700000000000000000000000000000000000000000000000000000000002011080000000000000000000000000000000000000000000000000000000000201109000000000000000000000000000000000000000000000000000000000020110a000000000000000000000000000000000000000000000000000000000020110b000000000000000000000000000000000000000000000000000000000020110c000000000000000000000000000000000000000000000000000000000020110d000000000000000000000000000000000000000000000000000000000020110e000000000000000000000000000000000000000000000000000000000020110f0000000000000000000000000000000000000000000000000000000000201110000000000000000000000000000000000000000000000000000000000020111100000000000000000000000000000000000000000000000000000000002011120000000000000000000000000000000000000000000000000000000000201113000000000000000000000000000000000000000000000000000000000020111400000000000000000000000000000000000000000000000000000000002011150000000000000000000000000000000000000000000000000000000000201116000000000000000000000000000000000000000000000000000000000020111700000000000000000000000000000000000000000000000000000000002011180000000000000000000000000000000000000000000000000000000000201119000000000000000000000000000000000000000000000000000000000020111a000000000000000000000000000000000000000000000000000000000020111b000000000000000000000000000000000000000000000000000000000020111c000000000000000000000000000000000000000000000000000000000020111d000000000000000000000000000000000000000000000000000000000020111e000000000000000000000000000000000000000000000000000000000020111f0000000000000000000000000000000000000000000000000000000000201120000000000000000000000000000000000000000000000000000000000020112100000000000000000000000000000000000000000000000000000000002011220000000000000000000000000000000000000000000000000000000000201123000000000000000000000000000000000000000000000000000000000020112400000000000000000000000000000000000000000000000000000000002011250000000000000000000000000000000000000000000000000000000000201126000000000000000000000000000000000000000000000000000000000020112700000000000000000000000000000000000000000000000000000000002011280000000000000000000000000000000000000000000000000000000000201129000000000000000000000000000000000000000000000000000000000020112a000000000000000000000000000000000000000000000000000000000020112b000000000000000000000000000000000000000000000000000000000020112c000000000000000000000000000000000000000000000000000000000020112d000000000000000000000000000000000000000000000000000000000020112e000000000000000000000000000000000000000000000000000000000020112f0000000000000000000000000000000000000000000000000000000000201130000000000000000000000000000000000000000000000000000000000020113100000000000000000000000000000000000000000000000000000000002011320000000000000000000000000000000000000000000000000000000000201133000000000000000000000000000000000000000000000000000000000020113400000000000000000000000000000000000000000000000000000000002011350000000000000000000000000000000000000000000000000000000000201136000000000000000000000000000000000000000000000000000000000020113700000000000000000000000000000000000000000000000000000000002011380000000000000000000000000000000000000000000000000000000000201139000000000000000000000000000000000000000000000000000000000020113a000000000000000000000000000000000000000000000000000000000020113b000000000000000000000000000000000000000000000000000000000020113c000000000000000000000000000000000000000000000000000000000020113d000000000000000000000000000000000000000000000000000000000020113e0800e9805e8a4faa87fc419af08a6d956f18976c46ea694bbd4cf6946e6d02033200e0925a6b172b4b01bb76eb1d3f7dd2ced118bca70d223a6d61afa1b75915ae00383590492d2f99a0283d1de57015b4b6b0759a8023af2c68fb4929dee2f303007ed57100dd77e2b6405f780503ef61b7b53e13f344b6e6a6eff3e3c13de0d0001ab1b0c348c46184dbc86ff79f248e7da1b09d3f9c6a986e98fe45389f060d0023d134bc68d7efa25e255001069827dc0bee766c08c988d6300071ed27fe6c0031cbb780b07f632cbaf767dc80608cc0a8e1d1df3ecd6f5d8bc0ca6703e4f4002c7dc9e731fc5f6456b2a70b4e636ac17d5e0cd36d3a591116a9e124f735863f0000000000000000000000000000000000000000000000000000000000202000000000000000000000000000000000000000000000000000000000000020200a0000000000000000000000000000000000000000000000000000000000202001000000000000000000000000000000000000000000000000000000000020200b0000000000000000000000000000000000000000000000000000000000202002000000000000000000000000000000000000000000000000000000000020200c0000000000000000000000000000000000000000000000000000000000202003000000000000000000000000000000000000000000000000000000000020200d0000000000000000000000000000000000000000000000000000000000202004000000000000000000000000000000000000000000000000000000000020200e0000000000000000000000000000000000000000000000000000000000202005000000000000000000000000000000000000000000000000000000000020200f00000000000000000000000000000000000000000000000000000000002020060000000000000000000000000000000000000000000000000000000000202010000000000000000000000000000000000000000000000000000000000020200700000000000000000000000000000000000000000000000000000000002020110000000000000000000000000000000000000000000000000000000000202008000000000000000000000000000000000000000000000000000000000020201200000000000000000000000000000000000000000000000000000000002020090000000000000000000000000000000000000000000000000000000000202013000000000000000000000000000000000000000000000000000000000020200a0000000000000000000000000000000000000000000000000000000000202014000000000000000000000000000000000000000000000000000000000020200b0000000000000000000000000000000000000000000000000000000000202015000000000000000000000000000000000000000000000000000000000020200c0000000000000000000000000000000000000000000000000000000000202016000000000000000000000000000000000000000000000000000000000020200d0000000000000000000000000000000000000000000000000000000000202017000000000000000000000000000000000000000000000000000000000020200e0000000000000000000000000000000000000000000000000000000000202018000000000000000000000000000000000000000000000000000000000020200f00000000000000000000000000000000000000000000000000000000002020190000000000000000000000000000000000000000000000000000000000202010000000000000000000000000000000000000000000000000000000000020201a0000000000000000000000000000000000000000000000000000000000202011000000000000000000000000000000000000000000000000000000000020201b0000000000000000000000000000000000000000000000000000000000202012000000000000000000000000000000000000000000000000000000000020201c0000000000000000000000000000000000000000000000000000000000202013000000000000000000000000000000000000000000000000000000000020201d0000000000000000000000000000000000000000000000000000000000202014000000000000000000000000000000000000000000000000000000000020201e0000000000000000000000000000000000000000000000000000000000202015000000000000000000000000000000000000000000000000000000000020201f00000000000000000000000000000000000000000000000000000000002020160000000000000000000000000000000000000000000000000000000000202020000000000000000000000000000000000000000000000000000000000020201700000000000000000000000000000000000000000000000000000000002020210000000000000000000000000000000000000000000000000000000000202018000000000000000000000000000000000000000000000000000000000020202200000000000000000000000000000000000000000000000000000000002020190000000000000000000000000000000000000000000000000000000000202023000000000000000000000000000000000000000000000000000000000020201a0000000000000000000000000000000000000000000000000000000000202024000000000000000000000000000000000000000000000000000000000020201b0000000000000000000000000000000000000000000000000000000000202025000000000000000000000000000000000000000000000000000000000020201c0000000000000000000000000000000000000000000000000000000000202026000000000000000000000000000000000000000000000000000000000020201d0000000000000000000000000000000000000000000000000000000000202027000000000000000000000000000000000000000000000000000000000020201e0000000000000000000000000000000000000000000000000000000000202028000000000000000000000000000000000000000000000000000000000020201f00000000000000000000000000000000000000000000000000000000002020290000000000000000000000000000000000000000000000000000000000202020000000000000000000000000000000000000000000000000000000000020202a0000000000000000000000000000000000000000000000000000000000202021000000000000000000000000000000000000000000000000000000000020202b0000000000000000000000000000000000000000000000000000000000202022000000000000000000000000000000000000000000000000000000000020202c0000000000000000000000000000000000000000000000000000000000202023000000000000000000000000000000000000000000000000000000000020202d0000000000000000000000000000000000000000000000000000000000202024000000000000000000000000000000000000000000000000000000000020202e0000000000000000000000000000000000000000000000000000000000202025000000000000000000000000000000000000000000000000000000000020202f00000000000000000000000000000000000000000000000000000000002020260000000000000000000000000000000000000000000000000000000000202030000000000000000000000000000000000000000000000000000000000020202700000000000000000000000000000000000000000000000000000000002020310000000000000000000000000000000000000000000000000000000000202028000000000000000000000000000000000000000000000000000000000020203200000000000000000000000000000000000000000000000000000000002020290000000000000000000000000000000000000000000000000000000000202033000000000000000000000000000000000000000000000000000000000020202a0000000000000000000000000000000000000000000000000000000000202034000000000000000000000000000000000000000000000000000000000020202b0000000000000000000000000000000000000000000000000000000000202035000000000000000000000000000000000000000000000000000000000020202c0000000000000000000000000000000000000000000000000000000000202036000000000000000000000000000000000000000000000000000000000020202d0000000000000000000000000000000000000000000000000000000000202037000000000000000000000000000000000000000000000000000000000020202e0000000000000000000000000000000000000000000000000000000000202038000000000000000000000000000000000000000000000000000000000020202f00000000000000000000000000000000000000000000000000000000002020390000000000000000000000000000000000000000000000000000000000202030000000000000000000000000000000000000000000000000000000000020203a0000000000000000000000000000000000000000000000000000000000202031000000000000000000000000000000000000000000000000000000000020203b0000000000000000000000000000000000000000000000000000000000202032000000000000000000000000000000000000000000000000000000000020203c0000000000000000000000000000000000000000000000000000000000202033000000000000000000000000000000000000000000000000000000000020203d0000000000000000000000000000000000000000000000000000000000202034000000000000000000000000000000000000000000000000000000000020203e0000000000000000000000000000000000000000000000000000000000202035000000000000000000000000000000000000000000000000000000000020203f00000000000000000000000000000000000000000000000000000000002020360000000000000000000000000000000000000000000000000000000000202040000000000000000000000000000000000000000000000000000000000020203700000000000000000000000000000000000000000000000000000000002020410000000000000000000000000000000000000000000000000000000000202038000000000000000000000000000000000000000000000000000000000020204200000000000000000000000000000000000000000000000000000000002020390000000000000000000000000000000000000000000000000000000000202043000000000000000000000000000000000000000000000000000000000020203a0000000000000000000000000000000000000000000000000000000000202044000000000000000000000000000000000000000000000000000000000020203b0000000000000000000000000000000000000000000000000000000000202045000000000000000000000000000000000000000000000000000000000020203c0000000000000000000000000000000000000000000000000000000000202046000000000000000000000000000000000000000000000000000000000020203d0000000000000000000000000000000000000000000000000000000000202047000000000000000000000000000000000000000000000000000000000020203e0000000000000000000000000000000000000000000000000000000000202048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "txsEffectsHash": "0x006355bc5a5a6353eca00eac5e4aede081b359a25bcf81604aacd84dd1947561", + "archive": "0x18d695c543b39ed4aebf51260b01cd023d27c36e90e2756413803fe06d376c70", + "blockHash": "0x1794217194decb456524466a01a7356e8b08b751ef0bc596431405c749627782", + "body": "0x00000008000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000004100100000000000000000000000000000000000000000000000000000000000410020000000000000000000000000000000000000000000000000000000000041003000000000000000000000000000000000000000000000000000000000004100400000000000000000000000000000000000000000000000000000000000410050000000000000000000000000000000000000000000000000000000000041006000000000000000000000000000000000000000000000000000000000004100700000000000000000000000000000000000000000000000000000000000410080000000000000000000000000000000000000000000000000000000000041009000000000000000000000000000000000000000000000000000000000004100a000000000000000000000000000000000000000000000000000000000004100b000000000000000000000000000000000000000000000000000000000004100c000000000000000000000000000000000000000000000000000000000004100d000000000000000000000000000000000000000000000000000000000004100e000000000000000000000000000000000000000000000000000000000004100f0000000000000000000000000000000000000000000000000000000000041010000000000000000000000000000000000000000000000000000000000004101100000000000000000000000000000000000000000000000000000000000410120000000000000000000000000000000000000000000000000000000000041013000000000000000000000000000000000000000000000000000000000004101400000000000000000000000000000000000000000000000000000000000410150000000000000000000000000000000000000000000000000000000000041016000000000000000000000000000000000000000000000000000000000004101700000000000000000000000000000000000000000000000000000000000410180000000000000000000000000000000000000000000000000000000000041019000000000000000000000000000000000000000000000000000000000004101a000000000000000000000000000000000000000000000000000000000004101b000000000000000000000000000000000000000000000000000000000004101c000000000000000000000000000000000000000000000000000000000004101d000000000000000000000000000000000000000000000000000000000004101e000000000000000000000000000000000000000000000000000000000004101f0000000000000000000000000000000000000000000000000000000000041020000000000000000000000000000000000000000000000000000000000004102100000000000000000000000000000000000000000000000000000000000410220000000000000000000000000000000000000000000000000000000000041023000000000000000000000000000000000000000000000000000000000004102400000000000000000000000000000000000000000000000000000000000410250000000000000000000000000000000000000000000000000000000000041026000000000000000000000000000000000000000000000000000000000004102700000000000000000000000000000000000000000000000000000000000410280000000000000000000000000000000000000000000000000000000000041029000000000000000000000000000000000000000000000000000000000004102a000000000000000000000000000000000000000000000000000000000004102b000000000000000000000000000000000000000000000000000000000004102c000000000000000000000000000000000000000000000000000000000004102d000000000000000000000000000000000000000000000000000000000004102e000000000000000000000000000000000000000000000000000000000004102f0000000000000000000000000000000000000000000000000000000000041030000000000000000000000000000000000000000000000000000000000004103100000000000000000000000000000000000000000000000000000000000410320000000000000000000000000000000000000000000000000000000000041033000000000000000000000000000000000000000000000000000000000004103400000000000000000000000000000000000000000000000000000000000410350000000000000000000000000000000000000000000000000000000000041036000000000000000000000000000000000000000000000000000000000004103700000000000000000000000000000000000000000000000000000000000410380000000000000000000000000000000000000000000000000000000000041039000000000000000000000000000000000000000000000000000000000004103a000000000000000000000000000000000000000000000000000000000004103b000000000000000000000000000000000000000000000000000000000004103c000000000000000000000000000000000000000000000000000000000004103d000000000000000000000000000000000000000000000000000000000004103e000000000000000000000000000000000000000000000000000000000004103f3f0000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004110100000000000000000000000000000000000000000000000000000000000411020000000000000000000000000000000000000000000000000000000000041103000000000000000000000000000000000000000000000000000000000004110400000000000000000000000000000000000000000000000000000000000411050000000000000000000000000000000000000000000000000000000000041106000000000000000000000000000000000000000000000000000000000004110700000000000000000000000000000000000000000000000000000000000411080000000000000000000000000000000000000000000000000000000000041109000000000000000000000000000000000000000000000000000000000004110a000000000000000000000000000000000000000000000000000000000004110b000000000000000000000000000000000000000000000000000000000004110c000000000000000000000000000000000000000000000000000000000004110d000000000000000000000000000000000000000000000000000000000004110e000000000000000000000000000000000000000000000000000000000004110f0000000000000000000000000000000000000000000000000000000000041110000000000000000000000000000000000000000000000000000000000004111100000000000000000000000000000000000000000000000000000000000411120000000000000000000000000000000000000000000000000000000000041113000000000000000000000000000000000000000000000000000000000004111400000000000000000000000000000000000000000000000000000000000411150000000000000000000000000000000000000000000000000000000000041116000000000000000000000000000000000000000000000000000000000004111700000000000000000000000000000000000000000000000000000000000411180000000000000000000000000000000000000000000000000000000000041119000000000000000000000000000000000000000000000000000000000004111a000000000000000000000000000000000000000000000000000000000004111b000000000000000000000000000000000000000000000000000000000004111c000000000000000000000000000000000000000000000000000000000004111d000000000000000000000000000000000000000000000000000000000004111e000000000000000000000000000000000000000000000000000000000004111f0000000000000000000000000000000000000000000000000000000000041120000000000000000000000000000000000000000000000000000000000004112100000000000000000000000000000000000000000000000000000000000411220000000000000000000000000000000000000000000000000000000000041123000000000000000000000000000000000000000000000000000000000004112400000000000000000000000000000000000000000000000000000000000411250000000000000000000000000000000000000000000000000000000000041126000000000000000000000000000000000000000000000000000000000004112700000000000000000000000000000000000000000000000000000000000411280000000000000000000000000000000000000000000000000000000000041129000000000000000000000000000000000000000000000000000000000004112a000000000000000000000000000000000000000000000000000000000004112b000000000000000000000000000000000000000000000000000000000004112c000000000000000000000000000000000000000000000000000000000004112d000000000000000000000000000000000000000000000000000000000004112e000000000000000000000000000000000000000000000000000000000004112f0000000000000000000000000000000000000000000000000000000000041130000000000000000000000000000000000000000000000000000000000004113100000000000000000000000000000000000000000000000000000000000411320000000000000000000000000000000000000000000000000000000000041133000000000000000000000000000000000000000000000000000000000004113400000000000000000000000000000000000000000000000000000000000411350000000000000000000000000000000000000000000000000000000000041136000000000000000000000000000000000000000000000000000000000004113700000000000000000000000000000000000000000000000000000000000411380000000000000000000000000000000000000000000000000000000000041139000000000000000000000000000000000000000000000000000000000004113a000000000000000000000000000000000000000000000000000000000004113b000000000000000000000000000000000000000000000000000000000004113c000000000000000000000000000000000000000000000000000000000004113d000000000000000000000000000000000000000000000000000000000004113e080097a6ec570e9b8e257647c9c74c5ad3edc57ca5ef6ae44d80b3c30d1d99b9b300ce48ec41d1edde0066fab553a456ae2f380d14fa8f956af1fb0217513a598900619ff12eaf97f63aa2a2311de3b6571a7b880a5247cb33b6a74787bf3f9bd5007854a2fad4e1801c6404394bf3d37ab08c135ea38a1974242e39a21273685f000f55796e72957a819e68a22e8602d73c3ba3718a5a4bd92b80b0aa444b182a00788b6e9874fb040ee679a7fae257190099a605229b948334e54a57739535d4004f1658ee3c1a91627e5d72f5a731f0796299df82ab41e72c88eee0c82fa85e003ee802add96628c693ed71afa9908138ba5a6fbf0a5f29a9c74e4e42aba6713f0000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000004200a0000000000000000000000000000000000000000000000000000000000042001000000000000000000000000000000000000000000000000000000000004200b0000000000000000000000000000000000000000000000000000000000042002000000000000000000000000000000000000000000000000000000000004200c0000000000000000000000000000000000000000000000000000000000042003000000000000000000000000000000000000000000000000000000000004200d0000000000000000000000000000000000000000000000000000000000042004000000000000000000000000000000000000000000000000000000000004200e0000000000000000000000000000000000000000000000000000000000042005000000000000000000000000000000000000000000000000000000000004200f00000000000000000000000000000000000000000000000000000000000420060000000000000000000000000000000000000000000000000000000000042010000000000000000000000000000000000000000000000000000000000004200700000000000000000000000000000000000000000000000000000000000420110000000000000000000000000000000000000000000000000000000000042008000000000000000000000000000000000000000000000000000000000004201200000000000000000000000000000000000000000000000000000000000420090000000000000000000000000000000000000000000000000000000000042013000000000000000000000000000000000000000000000000000000000004200a0000000000000000000000000000000000000000000000000000000000042014000000000000000000000000000000000000000000000000000000000004200b0000000000000000000000000000000000000000000000000000000000042015000000000000000000000000000000000000000000000000000000000004200c0000000000000000000000000000000000000000000000000000000000042016000000000000000000000000000000000000000000000000000000000004200d0000000000000000000000000000000000000000000000000000000000042017000000000000000000000000000000000000000000000000000000000004200e0000000000000000000000000000000000000000000000000000000000042018000000000000000000000000000000000000000000000000000000000004200f00000000000000000000000000000000000000000000000000000000000420190000000000000000000000000000000000000000000000000000000000042010000000000000000000000000000000000000000000000000000000000004201a0000000000000000000000000000000000000000000000000000000000042011000000000000000000000000000000000000000000000000000000000004201b0000000000000000000000000000000000000000000000000000000000042012000000000000000000000000000000000000000000000000000000000004201c0000000000000000000000000000000000000000000000000000000000042013000000000000000000000000000000000000000000000000000000000004201d0000000000000000000000000000000000000000000000000000000000042014000000000000000000000000000000000000000000000000000000000004201e0000000000000000000000000000000000000000000000000000000000042015000000000000000000000000000000000000000000000000000000000004201f00000000000000000000000000000000000000000000000000000000000420160000000000000000000000000000000000000000000000000000000000042020000000000000000000000000000000000000000000000000000000000004201700000000000000000000000000000000000000000000000000000000000420210000000000000000000000000000000000000000000000000000000000042018000000000000000000000000000000000000000000000000000000000004202200000000000000000000000000000000000000000000000000000000000420190000000000000000000000000000000000000000000000000000000000042023000000000000000000000000000000000000000000000000000000000004201a0000000000000000000000000000000000000000000000000000000000042024000000000000000000000000000000000000000000000000000000000004201b0000000000000000000000000000000000000000000000000000000000042025000000000000000000000000000000000000000000000000000000000004201c0000000000000000000000000000000000000000000000000000000000042026000000000000000000000000000000000000000000000000000000000004201d0000000000000000000000000000000000000000000000000000000000042027000000000000000000000000000000000000000000000000000000000004201e0000000000000000000000000000000000000000000000000000000000042028000000000000000000000000000000000000000000000000000000000004201f00000000000000000000000000000000000000000000000000000000000420290000000000000000000000000000000000000000000000000000000000042020000000000000000000000000000000000000000000000000000000000004202a0000000000000000000000000000000000000000000000000000000000042021000000000000000000000000000000000000000000000000000000000004202b0000000000000000000000000000000000000000000000000000000000042022000000000000000000000000000000000000000000000000000000000004202c0000000000000000000000000000000000000000000000000000000000042023000000000000000000000000000000000000000000000000000000000004202d0000000000000000000000000000000000000000000000000000000000042024000000000000000000000000000000000000000000000000000000000004202e0000000000000000000000000000000000000000000000000000000000042025000000000000000000000000000000000000000000000000000000000004202f00000000000000000000000000000000000000000000000000000000000420260000000000000000000000000000000000000000000000000000000000042030000000000000000000000000000000000000000000000000000000000004202700000000000000000000000000000000000000000000000000000000000420310000000000000000000000000000000000000000000000000000000000042028000000000000000000000000000000000000000000000000000000000004203200000000000000000000000000000000000000000000000000000000000420290000000000000000000000000000000000000000000000000000000000042033000000000000000000000000000000000000000000000000000000000004202a0000000000000000000000000000000000000000000000000000000000042034000000000000000000000000000000000000000000000000000000000004202b0000000000000000000000000000000000000000000000000000000000042035000000000000000000000000000000000000000000000000000000000004202c0000000000000000000000000000000000000000000000000000000000042036000000000000000000000000000000000000000000000000000000000004202d0000000000000000000000000000000000000000000000000000000000042037000000000000000000000000000000000000000000000000000000000004202e0000000000000000000000000000000000000000000000000000000000042038000000000000000000000000000000000000000000000000000000000004202f00000000000000000000000000000000000000000000000000000000000420390000000000000000000000000000000000000000000000000000000000042030000000000000000000000000000000000000000000000000000000000004203a0000000000000000000000000000000000000000000000000000000000042031000000000000000000000000000000000000000000000000000000000004203b0000000000000000000000000000000000000000000000000000000000042032000000000000000000000000000000000000000000000000000000000004203c0000000000000000000000000000000000000000000000000000000000042033000000000000000000000000000000000000000000000000000000000004203d0000000000000000000000000000000000000000000000000000000000042034000000000000000000000000000000000000000000000000000000000004203e0000000000000000000000000000000000000000000000000000000000042035000000000000000000000000000000000000000000000000000000000004203f00000000000000000000000000000000000000000000000000000000000420360000000000000000000000000000000000000000000000000000000000042040000000000000000000000000000000000000000000000000000000000004203700000000000000000000000000000000000000000000000000000000000420410000000000000000000000000000000000000000000000000000000000042038000000000000000000000000000000000000000000000000000000000004204200000000000000000000000000000000000000000000000000000000000420390000000000000000000000000000000000000000000000000000000000042043000000000000000000000000000000000000000000000000000000000004203a0000000000000000000000000000000000000000000000000000000000042044000000000000000000000000000000000000000000000000000000000004203b0000000000000000000000000000000000000000000000000000000000042045000000000000000000000000000000000000000000000000000000000004203c0000000000000000000000000000000000000000000000000000000000042046000000000000000000000000000000000000000000000000000000000004203d0000000000000000000000000000000000000000000000000000000000042047000000000000000000000000000000000000000000000000000000000004203e0000000000000000000000000000000000000000000000000000000000042048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008100100000000000000000000000000000000000000000000000000000000000810020000000000000000000000000000000000000000000000000000000000081003000000000000000000000000000000000000000000000000000000000008100400000000000000000000000000000000000000000000000000000000000810050000000000000000000000000000000000000000000000000000000000081006000000000000000000000000000000000000000000000000000000000008100700000000000000000000000000000000000000000000000000000000000810080000000000000000000000000000000000000000000000000000000000081009000000000000000000000000000000000000000000000000000000000008100a000000000000000000000000000000000000000000000000000000000008100b000000000000000000000000000000000000000000000000000000000008100c000000000000000000000000000000000000000000000000000000000008100d000000000000000000000000000000000000000000000000000000000008100e000000000000000000000000000000000000000000000000000000000008100f0000000000000000000000000000000000000000000000000000000000081010000000000000000000000000000000000000000000000000000000000008101100000000000000000000000000000000000000000000000000000000000810120000000000000000000000000000000000000000000000000000000000081013000000000000000000000000000000000000000000000000000000000008101400000000000000000000000000000000000000000000000000000000000810150000000000000000000000000000000000000000000000000000000000081016000000000000000000000000000000000000000000000000000000000008101700000000000000000000000000000000000000000000000000000000000810180000000000000000000000000000000000000000000000000000000000081019000000000000000000000000000000000000000000000000000000000008101a000000000000000000000000000000000000000000000000000000000008101b000000000000000000000000000000000000000000000000000000000008101c000000000000000000000000000000000000000000000000000000000008101d000000000000000000000000000000000000000000000000000000000008101e000000000000000000000000000000000000000000000000000000000008101f0000000000000000000000000000000000000000000000000000000000081020000000000000000000000000000000000000000000000000000000000008102100000000000000000000000000000000000000000000000000000000000810220000000000000000000000000000000000000000000000000000000000081023000000000000000000000000000000000000000000000000000000000008102400000000000000000000000000000000000000000000000000000000000810250000000000000000000000000000000000000000000000000000000000081026000000000000000000000000000000000000000000000000000000000008102700000000000000000000000000000000000000000000000000000000000810280000000000000000000000000000000000000000000000000000000000081029000000000000000000000000000000000000000000000000000000000008102a000000000000000000000000000000000000000000000000000000000008102b000000000000000000000000000000000000000000000000000000000008102c000000000000000000000000000000000000000000000000000000000008102d000000000000000000000000000000000000000000000000000000000008102e000000000000000000000000000000000000000000000000000000000008102f0000000000000000000000000000000000000000000000000000000000081030000000000000000000000000000000000000000000000000000000000008103100000000000000000000000000000000000000000000000000000000000810320000000000000000000000000000000000000000000000000000000000081033000000000000000000000000000000000000000000000000000000000008103400000000000000000000000000000000000000000000000000000000000810350000000000000000000000000000000000000000000000000000000000081036000000000000000000000000000000000000000000000000000000000008103700000000000000000000000000000000000000000000000000000000000810380000000000000000000000000000000000000000000000000000000000081039000000000000000000000000000000000000000000000000000000000008103a000000000000000000000000000000000000000000000000000000000008103b000000000000000000000000000000000000000000000000000000000008103c000000000000000000000000000000000000000000000000000000000008103d000000000000000000000000000000000000000000000000000000000008103e000000000000000000000000000000000000000000000000000000000008103f3f0000000000000000000000000000000000000000000000000000000000081100000000000000000000000000000000000000000000000000000000000008110100000000000000000000000000000000000000000000000000000000000811020000000000000000000000000000000000000000000000000000000000081103000000000000000000000000000000000000000000000000000000000008110400000000000000000000000000000000000000000000000000000000000811050000000000000000000000000000000000000000000000000000000000081106000000000000000000000000000000000000000000000000000000000008110700000000000000000000000000000000000000000000000000000000000811080000000000000000000000000000000000000000000000000000000000081109000000000000000000000000000000000000000000000000000000000008110a000000000000000000000000000000000000000000000000000000000008110b000000000000000000000000000000000000000000000000000000000008110c000000000000000000000000000000000000000000000000000000000008110d000000000000000000000000000000000000000000000000000000000008110e000000000000000000000000000000000000000000000000000000000008110f0000000000000000000000000000000000000000000000000000000000081110000000000000000000000000000000000000000000000000000000000008111100000000000000000000000000000000000000000000000000000000000811120000000000000000000000000000000000000000000000000000000000081113000000000000000000000000000000000000000000000000000000000008111400000000000000000000000000000000000000000000000000000000000811150000000000000000000000000000000000000000000000000000000000081116000000000000000000000000000000000000000000000000000000000008111700000000000000000000000000000000000000000000000000000000000811180000000000000000000000000000000000000000000000000000000000081119000000000000000000000000000000000000000000000000000000000008111a000000000000000000000000000000000000000000000000000000000008111b000000000000000000000000000000000000000000000000000000000008111c000000000000000000000000000000000000000000000000000000000008111d000000000000000000000000000000000000000000000000000000000008111e000000000000000000000000000000000000000000000000000000000008111f0000000000000000000000000000000000000000000000000000000000081120000000000000000000000000000000000000000000000000000000000008112100000000000000000000000000000000000000000000000000000000000811220000000000000000000000000000000000000000000000000000000000081123000000000000000000000000000000000000000000000000000000000008112400000000000000000000000000000000000000000000000000000000000811250000000000000000000000000000000000000000000000000000000000081126000000000000000000000000000000000000000000000000000000000008112700000000000000000000000000000000000000000000000000000000000811280000000000000000000000000000000000000000000000000000000000081129000000000000000000000000000000000000000000000000000000000008112a000000000000000000000000000000000000000000000000000000000008112b000000000000000000000000000000000000000000000000000000000008112c000000000000000000000000000000000000000000000000000000000008112d000000000000000000000000000000000000000000000000000000000008112e000000000000000000000000000000000000000000000000000000000008112f0000000000000000000000000000000000000000000000000000000000081130000000000000000000000000000000000000000000000000000000000008113100000000000000000000000000000000000000000000000000000000000811320000000000000000000000000000000000000000000000000000000000081133000000000000000000000000000000000000000000000000000000000008113400000000000000000000000000000000000000000000000000000000000811350000000000000000000000000000000000000000000000000000000000081136000000000000000000000000000000000000000000000000000000000008113700000000000000000000000000000000000000000000000000000000000811380000000000000000000000000000000000000000000000000000000000081139000000000000000000000000000000000000000000000000000000000008113a000000000000000000000000000000000000000000000000000000000008113b000000000000000000000000000000000000000000000000000000000008113c000000000000000000000000000000000000000000000000000000000008113d000000000000000000000000000000000000000000000000000000000008113e08003c0472260790b0bdfb8ae4dc4d437e7686b73643f2198970d84e1059a5f13500bfd46275a318e438726ff2765ae154b63ab8a0daebcbed668a5f58a0e63dc1007906b9418dc758c6b4f8454c69baa48b7889b6b511d707abe8e2cb8f7c397300aeb60c4d65a44f122e58bf9565dfe2024b3ae654d5cf2e47ecb035d53c927000bf82e8cda20345f37bbb1de3932172324b57f0b98be483392697b168e3bba8000fb4bbad884ef30edf68e45a6cf2733fcf50310c69d7c1432b29af2c0aa8040023e1622d27fee3b4a40ab975ae0eb2e31619ef3dc76eb858f7fddb6a056131004689cd7007daf98dd3218b839b8e6a29f957154347b391fdb376bd0b344be23f0000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000008200a0000000000000000000000000000000000000000000000000000000000082001000000000000000000000000000000000000000000000000000000000008200b0000000000000000000000000000000000000000000000000000000000082002000000000000000000000000000000000000000000000000000000000008200c0000000000000000000000000000000000000000000000000000000000082003000000000000000000000000000000000000000000000000000000000008200d0000000000000000000000000000000000000000000000000000000000082004000000000000000000000000000000000000000000000000000000000008200e0000000000000000000000000000000000000000000000000000000000082005000000000000000000000000000000000000000000000000000000000008200f00000000000000000000000000000000000000000000000000000000000820060000000000000000000000000000000000000000000000000000000000082010000000000000000000000000000000000000000000000000000000000008200700000000000000000000000000000000000000000000000000000000000820110000000000000000000000000000000000000000000000000000000000082008000000000000000000000000000000000000000000000000000000000008201200000000000000000000000000000000000000000000000000000000000820090000000000000000000000000000000000000000000000000000000000082013000000000000000000000000000000000000000000000000000000000008200a0000000000000000000000000000000000000000000000000000000000082014000000000000000000000000000000000000000000000000000000000008200b0000000000000000000000000000000000000000000000000000000000082015000000000000000000000000000000000000000000000000000000000008200c0000000000000000000000000000000000000000000000000000000000082016000000000000000000000000000000000000000000000000000000000008200d0000000000000000000000000000000000000000000000000000000000082017000000000000000000000000000000000000000000000000000000000008200e0000000000000000000000000000000000000000000000000000000000082018000000000000000000000000000000000000000000000000000000000008200f00000000000000000000000000000000000000000000000000000000000820190000000000000000000000000000000000000000000000000000000000082010000000000000000000000000000000000000000000000000000000000008201a0000000000000000000000000000000000000000000000000000000000082011000000000000000000000000000000000000000000000000000000000008201b0000000000000000000000000000000000000000000000000000000000082012000000000000000000000000000000000000000000000000000000000008201c0000000000000000000000000000000000000000000000000000000000082013000000000000000000000000000000000000000000000000000000000008201d0000000000000000000000000000000000000000000000000000000000082014000000000000000000000000000000000000000000000000000000000008201e0000000000000000000000000000000000000000000000000000000000082015000000000000000000000000000000000000000000000000000000000008201f00000000000000000000000000000000000000000000000000000000000820160000000000000000000000000000000000000000000000000000000000082020000000000000000000000000000000000000000000000000000000000008201700000000000000000000000000000000000000000000000000000000000820210000000000000000000000000000000000000000000000000000000000082018000000000000000000000000000000000000000000000000000000000008202200000000000000000000000000000000000000000000000000000000000820190000000000000000000000000000000000000000000000000000000000082023000000000000000000000000000000000000000000000000000000000008201a0000000000000000000000000000000000000000000000000000000000082024000000000000000000000000000000000000000000000000000000000008201b0000000000000000000000000000000000000000000000000000000000082025000000000000000000000000000000000000000000000000000000000008201c0000000000000000000000000000000000000000000000000000000000082026000000000000000000000000000000000000000000000000000000000008201d0000000000000000000000000000000000000000000000000000000000082027000000000000000000000000000000000000000000000000000000000008201e0000000000000000000000000000000000000000000000000000000000082028000000000000000000000000000000000000000000000000000000000008201f00000000000000000000000000000000000000000000000000000000000820290000000000000000000000000000000000000000000000000000000000082020000000000000000000000000000000000000000000000000000000000008202a0000000000000000000000000000000000000000000000000000000000082021000000000000000000000000000000000000000000000000000000000008202b0000000000000000000000000000000000000000000000000000000000082022000000000000000000000000000000000000000000000000000000000008202c0000000000000000000000000000000000000000000000000000000000082023000000000000000000000000000000000000000000000000000000000008202d0000000000000000000000000000000000000000000000000000000000082024000000000000000000000000000000000000000000000000000000000008202e0000000000000000000000000000000000000000000000000000000000082025000000000000000000000000000000000000000000000000000000000008202f00000000000000000000000000000000000000000000000000000000000820260000000000000000000000000000000000000000000000000000000000082030000000000000000000000000000000000000000000000000000000000008202700000000000000000000000000000000000000000000000000000000000820310000000000000000000000000000000000000000000000000000000000082028000000000000000000000000000000000000000000000000000000000008203200000000000000000000000000000000000000000000000000000000000820290000000000000000000000000000000000000000000000000000000000082033000000000000000000000000000000000000000000000000000000000008202a0000000000000000000000000000000000000000000000000000000000082034000000000000000000000000000000000000000000000000000000000008202b0000000000000000000000000000000000000000000000000000000000082035000000000000000000000000000000000000000000000000000000000008202c0000000000000000000000000000000000000000000000000000000000082036000000000000000000000000000000000000000000000000000000000008202d0000000000000000000000000000000000000000000000000000000000082037000000000000000000000000000000000000000000000000000000000008202e0000000000000000000000000000000000000000000000000000000000082038000000000000000000000000000000000000000000000000000000000008202f00000000000000000000000000000000000000000000000000000000000820390000000000000000000000000000000000000000000000000000000000082030000000000000000000000000000000000000000000000000000000000008203a0000000000000000000000000000000000000000000000000000000000082031000000000000000000000000000000000000000000000000000000000008203b0000000000000000000000000000000000000000000000000000000000082032000000000000000000000000000000000000000000000000000000000008203c0000000000000000000000000000000000000000000000000000000000082033000000000000000000000000000000000000000000000000000000000008203d0000000000000000000000000000000000000000000000000000000000082034000000000000000000000000000000000000000000000000000000000008203e0000000000000000000000000000000000000000000000000000000000082035000000000000000000000000000000000000000000000000000000000008203f00000000000000000000000000000000000000000000000000000000000820360000000000000000000000000000000000000000000000000000000000082040000000000000000000000000000000000000000000000000000000000008203700000000000000000000000000000000000000000000000000000000000820410000000000000000000000000000000000000000000000000000000000082038000000000000000000000000000000000000000000000000000000000008204200000000000000000000000000000000000000000000000000000000000820390000000000000000000000000000000000000000000000000000000000082043000000000000000000000000000000000000000000000000000000000008203a0000000000000000000000000000000000000000000000000000000000082044000000000000000000000000000000000000000000000000000000000008203b0000000000000000000000000000000000000000000000000000000000082045000000000000000000000000000000000000000000000000000000000008203c0000000000000000000000000000000000000000000000000000000000082046000000000000000000000000000000000000000000000000000000000008203d0000000000000000000000000000000000000000000000000000000000082047000000000000000000000000000000000000000000000000000000000008203e00000000000000000000000000000000000000000000000000000000000820480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000c100100000000000000000000000000000000000000000000000000000000000c100200000000000000000000000000000000000000000000000000000000000c100300000000000000000000000000000000000000000000000000000000000c100400000000000000000000000000000000000000000000000000000000000c100500000000000000000000000000000000000000000000000000000000000c100600000000000000000000000000000000000000000000000000000000000c100700000000000000000000000000000000000000000000000000000000000c100800000000000000000000000000000000000000000000000000000000000c100900000000000000000000000000000000000000000000000000000000000c100a00000000000000000000000000000000000000000000000000000000000c100b00000000000000000000000000000000000000000000000000000000000c100c00000000000000000000000000000000000000000000000000000000000c100d00000000000000000000000000000000000000000000000000000000000c100e00000000000000000000000000000000000000000000000000000000000c100f00000000000000000000000000000000000000000000000000000000000c101000000000000000000000000000000000000000000000000000000000000c101100000000000000000000000000000000000000000000000000000000000c101200000000000000000000000000000000000000000000000000000000000c101300000000000000000000000000000000000000000000000000000000000c101400000000000000000000000000000000000000000000000000000000000c101500000000000000000000000000000000000000000000000000000000000c101600000000000000000000000000000000000000000000000000000000000c101700000000000000000000000000000000000000000000000000000000000c101800000000000000000000000000000000000000000000000000000000000c101900000000000000000000000000000000000000000000000000000000000c101a00000000000000000000000000000000000000000000000000000000000c101b00000000000000000000000000000000000000000000000000000000000c101c00000000000000000000000000000000000000000000000000000000000c101d00000000000000000000000000000000000000000000000000000000000c101e00000000000000000000000000000000000000000000000000000000000c101f00000000000000000000000000000000000000000000000000000000000c102000000000000000000000000000000000000000000000000000000000000c102100000000000000000000000000000000000000000000000000000000000c102200000000000000000000000000000000000000000000000000000000000c102300000000000000000000000000000000000000000000000000000000000c102400000000000000000000000000000000000000000000000000000000000c102500000000000000000000000000000000000000000000000000000000000c102600000000000000000000000000000000000000000000000000000000000c102700000000000000000000000000000000000000000000000000000000000c102800000000000000000000000000000000000000000000000000000000000c102900000000000000000000000000000000000000000000000000000000000c102a00000000000000000000000000000000000000000000000000000000000c102b00000000000000000000000000000000000000000000000000000000000c102c00000000000000000000000000000000000000000000000000000000000c102d00000000000000000000000000000000000000000000000000000000000c102e00000000000000000000000000000000000000000000000000000000000c102f00000000000000000000000000000000000000000000000000000000000c103000000000000000000000000000000000000000000000000000000000000c103100000000000000000000000000000000000000000000000000000000000c103200000000000000000000000000000000000000000000000000000000000c103300000000000000000000000000000000000000000000000000000000000c103400000000000000000000000000000000000000000000000000000000000c103500000000000000000000000000000000000000000000000000000000000c103600000000000000000000000000000000000000000000000000000000000c103700000000000000000000000000000000000000000000000000000000000c103800000000000000000000000000000000000000000000000000000000000c103900000000000000000000000000000000000000000000000000000000000c103a00000000000000000000000000000000000000000000000000000000000c103b00000000000000000000000000000000000000000000000000000000000c103c00000000000000000000000000000000000000000000000000000000000c103d00000000000000000000000000000000000000000000000000000000000c103e00000000000000000000000000000000000000000000000000000000000c103f3f00000000000000000000000000000000000000000000000000000000000c110000000000000000000000000000000000000000000000000000000000000c110100000000000000000000000000000000000000000000000000000000000c110200000000000000000000000000000000000000000000000000000000000c110300000000000000000000000000000000000000000000000000000000000c110400000000000000000000000000000000000000000000000000000000000c110500000000000000000000000000000000000000000000000000000000000c110600000000000000000000000000000000000000000000000000000000000c110700000000000000000000000000000000000000000000000000000000000c110800000000000000000000000000000000000000000000000000000000000c110900000000000000000000000000000000000000000000000000000000000c110a00000000000000000000000000000000000000000000000000000000000c110b00000000000000000000000000000000000000000000000000000000000c110c00000000000000000000000000000000000000000000000000000000000c110d00000000000000000000000000000000000000000000000000000000000c110e00000000000000000000000000000000000000000000000000000000000c110f00000000000000000000000000000000000000000000000000000000000c111000000000000000000000000000000000000000000000000000000000000c111100000000000000000000000000000000000000000000000000000000000c111200000000000000000000000000000000000000000000000000000000000c111300000000000000000000000000000000000000000000000000000000000c111400000000000000000000000000000000000000000000000000000000000c111500000000000000000000000000000000000000000000000000000000000c111600000000000000000000000000000000000000000000000000000000000c111700000000000000000000000000000000000000000000000000000000000c111800000000000000000000000000000000000000000000000000000000000c111900000000000000000000000000000000000000000000000000000000000c111a00000000000000000000000000000000000000000000000000000000000c111b00000000000000000000000000000000000000000000000000000000000c111c00000000000000000000000000000000000000000000000000000000000c111d00000000000000000000000000000000000000000000000000000000000c111e00000000000000000000000000000000000000000000000000000000000c111f00000000000000000000000000000000000000000000000000000000000c112000000000000000000000000000000000000000000000000000000000000c112100000000000000000000000000000000000000000000000000000000000c112200000000000000000000000000000000000000000000000000000000000c112300000000000000000000000000000000000000000000000000000000000c112400000000000000000000000000000000000000000000000000000000000c112500000000000000000000000000000000000000000000000000000000000c112600000000000000000000000000000000000000000000000000000000000c112700000000000000000000000000000000000000000000000000000000000c112800000000000000000000000000000000000000000000000000000000000c112900000000000000000000000000000000000000000000000000000000000c112a00000000000000000000000000000000000000000000000000000000000c112b00000000000000000000000000000000000000000000000000000000000c112c00000000000000000000000000000000000000000000000000000000000c112d00000000000000000000000000000000000000000000000000000000000c112e00000000000000000000000000000000000000000000000000000000000c112f00000000000000000000000000000000000000000000000000000000000c113000000000000000000000000000000000000000000000000000000000000c113100000000000000000000000000000000000000000000000000000000000c113200000000000000000000000000000000000000000000000000000000000c113300000000000000000000000000000000000000000000000000000000000c113400000000000000000000000000000000000000000000000000000000000c113500000000000000000000000000000000000000000000000000000000000c113600000000000000000000000000000000000000000000000000000000000c113700000000000000000000000000000000000000000000000000000000000c113800000000000000000000000000000000000000000000000000000000000c113900000000000000000000000000000000000000000000000000000000000c113a00000000000000000000000000000000000000000000000000000000000c113b00000000000000000000000000000000000000000000000000000000000c113c00000000000000000000000000000000000000000000000000000000000c113d00000000000000000000000000000000000000000000000000000000000c113e0800f8029be42ec3f25204907ca981fb71e5b357093eb5db10fc01ca98a4e4154c0030e13d351a5bf1d5a040e82a163ca57017f39162693f85c571e441e36d702d00a550ae0f39f977d9473d6de1be3232fc68ed0c4a601d53542148695102cfc9005580bc65e4bff9c8fffa64db02c0fa6af14d9d26fd962f4c5904cbd3ddec2500758c4a0d43dfec788b2f580877c4f473adec8f168ea24424f2600e4eb4916f00342602bf90d10f8ca8e582a894dcc4c02bb89fe458532e0c632b53bae54b4d00ca43ab78ab834337e9964d84a0674c9adabdca140539c5a6bc96e0ba9a51f6004ffbfd91be292a7c6a0e255e50caa156ac2d628b40ad2128c4ab63a92d8a1c3f00000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c200a00000000000000000000000000000000000000000000000000000000000c200100000000000000000000000000000000000000000000000000000000000c200b00000000000000000000000000000000000000000000000000000000000c200200000000000000000000000000000000000000000000000000000000000c200c00000000000000000000000000000000000000000000000000000000000c200300000000000000000000000000000000000000000000000000000000000c200d00000000000000000000000000000000000000000000000000000000000c200400000000000000000000000000000000000000000000000000000000000c200e00000000000000000000000000000000000000000000000000000000000c200500000000000000000000000000000000000000000000000000000000000c200f00000000000000000000000000000000000000000000000000000000000c200600000000000000000000000000000000000000000000000000000000000c201000000000000000000000000000000000000000000000000000000000000c200700000000000000000000000000000000000000000000000000000000000c201100000000000000000000000000000000000000000000000000000000000c200800000000000000000000000000000000000000000000000000000000000c201200000000000000000000000000000000000000000000000000000000000c200900000000000000000000000000000000000000000000000000000000000c201300000000000000000000000000000000000000000000000000000000000c200a00000000000000000000000000000000000000000000000000000000000c201400000000000000000000000000000000000000000000000000000000000c200b00000000000000000000000000000000000000000000000000000000000c201500000000000000000000000000000000000000000000000000000000000c200c00000000000000000000000000000000000000000000000000000000000c201600000000000000000000000000000000000000000000000000000000000c200d00000000000000000000000000000000000000000000000000000000000c201700000000000000000000000000000000000000000000000000000000000c200e00000000000000000000000000000000000000000000000000000000000c201800000000000000000000000000000000000000000000000000000000000c200f00000000000000000000000000000000000000000000000000000000000c201900000000000000000000000000000000000000000000000000000000000c201000000000000000000000000000000000000000000000000000000000000c201a00000000000000000000000000000000000000000000000000000000000c201100000000000000000000000000000000000000000000000000000000000c201b00000000000000000000000000000000000000000000000000000000000c201200000000000000000000000000000000000000000000000000000000000c201c00000000000000000000000000000000000000000000000000000000000c201300000000000000000000000000000000000000000000000000000000000c201d00000000000000000000000000000000000000000000000000000000000c201400000000000000000000000000000000000000000000000000000000000c201e00000000000000000000000000000000000000000000000000000000000c201500000000000000000000000000000000000000000000000000000000000c201f00000000000000000000000000000000000000000000000000000000000c201600000000000000000000000000000000000000000000000000000000000c202000000000000000000000000000000000000000000000000000000000000c201700000000000000000000000000000000000000000000000000000000000c202100000000000000000000000000000000000000000000000000000000000c201800000000000000000000000000000000000000000000000000000000000c202200000000000000000000000000000000000000000000000000000000000c201900000000000000000000000000000000000000000000000000000000000c202300000000000000000000000000000000000000000000000000000000000c201a00000000000000000000000000000000000000000000000000000000000c202400000000000000000000000000000000000000000000000000000000000c201b00000000000000000000000000000000000000000000000000000000000c202500000000000000000000000000000000000000000000000000000000000c201c00000000000000000000000000000000000000000000000000000000000c202600000000000000000000000000000000000000000000000000000000000c201d00000000000000000000000000000000000000000000000000000000000c202700000000000000000000000000000000000000000000000000000000000c201e00000000000000000000000000000000000000000000000000000000000c202800000000000000000000000000000000000000000000000000000000000c201f00000000000000000000000000000000000000000000000000000000000c202900000000000000000000000000000000000000000000000000000000000c202000000000000000000000000000000000000000000000000000000000000c202a00000000000000000000000000000000000000000000000000000000000c202100000000000000000000000000000000000000000000000000000000000c202b00000000000000000000000000000000000000000000000000000000000c202200000000000000000000000000000000000000000000000000000000000c202c00000000000000000000000000000000000000000000000000000000000c202300000000000000000000000000000000000000000000000000000000000c202d00000000000000000000000000000000000000000000000000000000000c202400000000000000000000000000000000000000000000000000000000000c202e00000000000000000000000000000000000000000000000000000000000c202500000000000000000000000000000000000000000000000000000000000c202f00000000000000000000000000000000000000000000000000000000000c202600000000000000000000000000000000000000000000000000000000000c203000000000000000000000000000000000000000000000000000000000000c202700000000000000000000000000000000000000000000000000000000000c203100000000000000000000000000000000000000000000000000000000000c202800000000000000000000000000000000000000000000000000000000000c203200000000000000000000000000000000000000000000000000000000000c202900000000000000000000000000000000000000000000000000000000000c203300000000000000000000000000000000000000000000000000000000000c202a00000000000000000000000000000000000000000000000000000000000c203400000000000000000000000000000000000000000000000000000000000c202b00000000000000000000000000000000000000000000000000000000000c203500000000000000000000000000000000000000000000000000000000000c202c00000000000000000000000000000000000000000000000000000000000c203600000000000000000000000000000000000000000000000000000000000c202d00000000000000000000000000000000000000000000000000000000000c203700000000000000000000000000000000000000000000000000000000000c202e00000000000000000000000000000000000000000000000000000000000c203800000000000000000000000000000000000000000000000000000000000c202f00000000000000000000000000000000000000000000000000000000000c203900000000000000000000000000000000000000000000000000000000000c203000000000000000000000000000000000000000000000000000000000000c203a00000000000000000000000000000000000000000000000000000000000c203100000000000000000000000000000000000000000000000000000000000c203b00000000000000000000000000000000000000000000000000000000000c203200000000000000000000000000000000000000000000000000000000000c203c00000000000000000000000000000000000000000000000000000000000c203300000000000000000000000000000000000000000000000000000000000c203d00000000000000000000000000000000000000000000000000000000000c203400000000000000000000000000000000000000000000000000000000000c203e00000000000000000000000000000000000000000000000000000000000c203500000000000000000000000000000000000000000000000000000000000c203f00000000000000000000000000000000000000000000000000000000000c203600000000000000000000000000000000000000000000000000000000000c204000000000000000000000000000000000000000000000000000000000000c203700000000000000000000000000000000000000000000000000000000000c204100000000000000000000000000000000000000000000000000000000000c203800000000000000000000000000000000000000000000000000000000000c204200000000000000000000000000000000000000000000000000000000000c203900000000000000000000000000000000000000000000000000000000000c204300000000000000000000000000000000000000000000000000000000000c203a00000000000000000000000000000000000000000000000000000000000c204400000000000000000000000000000000000000000000000000000000000c203b00000000000000000000000000000000000000000000000000000000000c204500000000000000000000000000000000000000000000000000000000000c203c00000000000000000000000000000000000000000000000000000000000c204600000000000000000000000000000000000000000000000000000000000c203d00000000000000000000000000000000000000000000000000000000000c204700000000000000000000000000000000000000000000000000000000000c203e00000000000000000000000000000000000000000000000000000000000c2048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000101000000000000000000000000000000000000000000000000000000000000010100100000000000000000000000000000000000000000000000000000000001010020000000000000000000000000000000000000000000000000000000000101003000000000000000000000000000000000000000000000000000000000010100400000000000000000000000000000000000000000000000000000000001010050000000000000000000000000000000000000000000000000000000000101006000000000000000000000000000000000000000000000000000000000010100700000000000000000000000000000000000000000000000000000000001010080000000000000000000000000000000000000000000000000000000000101009000000000000000000000000000000000000000000000000000000000010100a000000000000000000000000000000000000000000000000000000000010100b000000000000000000000000000000000000000000000000000000000010100c000000000000000000000000000000000000000000000000000000000010100d000000000000000000000000000000000000000000000000000000000010100e000000000000000000000000000000000000000000000000000000000010100f0000000000000000000000000000000000000000000000000000000000101010000000000000000000000000000000000000000000000000000000000010101100000000000000000000000000000000000000000000000000000000001010120000000000000000000000000000000000000000000000000000000000101013000000000000000000000000000000000000000000000000000000000010101400000000000000000000000000000000000000000000000000000000001010150000000000000000000000000000000000000000000000000000000000101016000000000000000000000000000000000000000000000000000000000010101700000000000000000000000000000000000000000000000000000000001010180000000000000000000000000000000000000000000000000000000000101019000000000000000000000000000000000000000000000000000000000010101a000000000000000000000000000000000000000000000000000000000010101b000000000000000000000000000000000000000000000000000000000010101c000000000000000000000000000000000000000000000000000000000010101d000000000000000000000000000000000000000000000000000000000010101e000000000000000000000000000000000000000000000000000000000010101f0000000000000000000000000000000000000000000000000000000000101020000000000000000000000000000000000000000000000000000000000010102100000000000000000000000000000000000000000000000000000000001010220000000000000000000000000000000000000000000000000000000000101023000000000000000000000000000000000000000000000000000000000010102400000000000000000000000000000000000000000000000000000000001010250000000000000000000000000000000000000000000000000000000000101026000000000000000000000000000000000000000000000000000000000010102700000000000000000000000000000000000000000000000000000000001010280000000000000000000000000000000000000000000000000000000000101029000000000000000000000000000000000000000000000000000000000010102a000000000000000000000000000000000000000000000000000000000010102b000000000000000000000000000000000000000000000000000000000010102c000000000000000000000000000000000000000000000000000000000010102d000000000000000000000000000000000000000000000000000000000010102e000000000000000000000000000000000000000000000000000000000010102f0000000000000000000000000000000000000000000000000000000000101030000000000000000000000000000000000000000000000000000000000010103100000000000000000000000000000000000000000000000000000000001010320000000000000000000000000000000000000000000000000000000000101033000000000000000000000000000000000000000000000000000000000010103400000000000000000000000000000000000000000000000000000000001010350000000000000000000000000000000000000000000000000000000000101036000000000000000000000000000000000000000000000000000000000010103700000000000000000000000000000000000000000000000000000000001010380000000000000000000000000000000000000000000000000000000000101039000000000000000000000000000000000000000000000000000000000010103a000000000000000000000000000000000000000000000000000000000010103b000000000000000000000000000000000000000000000000000000000010103c000000000000000000000000000000000000000000000000000000000010103d000000000000000000000000000000000000000000000000000000000010103e000000000000000000000000000000000000000000000000000000000010103f3f0000000000000000000000000000000000000000000000000000000000101100000000000000000000000000000000000000000000000000000000000010110100000000000000000000000000000000000000000000000000000000001011020000000000000000000000000000000000000000000000000000000000101103000000000000000000000000000000000000000000000000000000000010110400000000000000000000000000000000000000000000000000000000001011050000000000000000000000000000000000000000000000000000000000101106000000000000000000000000000000000000000000000000000000000010110700000000000000000000000000000000000000000000000000000000001011080000000000000000000000000000000000000000000000000000000000101109000000000000000000000000000000000000000000000000000000000010110a000000000000000000000000000000000000000000000000000000000010110b000000000000000000000000000000000000000000000000000000000010110c000000000000000000000000000000000000000000000000000000000010110d000000000000000000000000000000000000000000000000000000000010110e000000000000000000000000000000000000000000000000000000000010110f0000000000000000000000000000000000000000000000000000000000101110000000000000000000000000000000000000000000000000000000000010111100000000000000000000000000000000000000000000000000000000001011120000000000000000000000000000000000000000000000000000000000101113000000000000000000000000000000000000000000000000000000000010111400000000000000000000000000000000000000000000000000000000001011150000000000000000000000000000000000000000000000000000000000101116000000000000000000000000000000000000000000000000000000000010111700000000000000000000000000000000000000000000000000000000001011180000000000000000000000000000000000000000000000000000000000101119000000000000000000000000000000000000000000000000000000000010111a000000000000000000000000000000000000000000000000000000000010111b000000000000000000000000000000000000000000000000000000000010111c000000000000000000000000000000000000000000000000000000000010111d000000000000000000000000000000000000000000000000000000000010111e000000000000000000000000000000000000000000000000000000000010111f0000000000000000000000000000000000000000000000000000000000101120000000000000000000000000000000000000000000000000000000000010112100000000000000000000000000000000000000000000000000000000001011220000000000000000000000000000000000000000000000000000000000101123000000000000000000000000000000000000000000000000000000000010112400000000000000000000000000000000000000000000000000000000001011250000000000000000000000000000000000000000000000000000000000101126000000000000000000000000000000000000000000000000000000000010112700000000000000000000000000000000000000000000000000000000001011280000000000000000000000000000000000000000000000000000000000101129000000000000000000000000000000000000000000000000000000000010112a000000000000000000000000000000000000000000000000000000000010112b000000000000000000000000000000000000000000000000000000000010112c000000000000000000000000000000000000000000000000000000000010112d000000000000000000000000000000000000000000000000000000000010112e000000000000000000000000000000000000000000000000000000000010112f0000000000000000000000000000000000000000000000000000000000101130000000000000000000000000000000000000000000000000000000000010113100000000000000000000000000000000000000000000000000000000001011320000000000000000000000000000000000000000000000000000000000101133000000000000000000000000000000000000000000000000000000000010113400000000000000000000000000000000000000000000000000000000001011350000000000000000000000000000000000000000000000000000000000101136000000000000000000000000000000000000000000000000000000000010113700000000000000000000000000000000000000000000000000000000001011380000000000000000000000000000000000000000000000000000000000101139000000000000000000000000000000000000000000000000000000000010113a000000000000000000000000000000000000000000000000000000000010113b000000000000000000000000000000000000000000000000000000000010113c000000000000000000000000000000000000000000000000000000000010113d000000000000000000000000000000000000000000000000000000000010113e080099145b6c0d32753835121f8b271186d01236948a4622ce78a98347fcfc98390085277a27c6acbd5ffc4c19cd65fc30056999e9bec36998f753132db0ff8e2300f3cf77a7261759ebd5f4149f6ad56746f4499cfcd4adf27a1d373f77da64d5009bc6e0e994a23cde8c95b90c1acc1b4a480c6599d1df2c3f9f6e76f3d1aff200d7a1c4a2700dacaaf07f1f0ff33837bdbabcf0b9ace17efabe0761708c4bb900dbeb8e96d14f21e57d5786b6d6ae7e5ddb1bb35935c0fb246d4bdbca62e02c00fbf12b5e0df6223b801088798e4e04d2a92ffe9a11639b7f0ce314e3412a8000d796e0724de03b796ba77069fcd6cf921e566f3aed15eb3e77258add74e9ff3f0000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010200a0000000000000000000000000000000000000000000000000000000000102001000000000000000000000000000000000000000000000000000000000010200b0000000000000000000000000000000000000000000000000000000000102002000000000000000000000000000000000000000000000000000000000010200c0000000000000000000000000000000000000000000000000000000000102003000000000000000000000000000000000000000000000000000000000010200d0000000000000000000000000000000000000000000000000000000000102004000000000000000000000000000000000000000000000000000000000010200e0000000000000000000000000000000000000000000000000000000000102005000000000000000000000000000000000000000000000000000000000010200f00000000000000000000000000000000000000000000000000000000001020060000000000000000000000000000000000000000000000000000000000102010000000000000000000000000000000000000000000000000000000000010200700000000000000000000000000000000000000000000000000000000001020110000000000000000000000000000000000000000000000000000000000102008000000000000000000000000000000000000000000000000000000000010201200000000000000000000000000000000000000000000000000000000001020090000000000000000000000000000000000000000000000000000000000102013000000000000000000000000000000000000000000000000000000000010200a0000000000000000000000000000000000000000000000000000000000102014000000000000000000000000000000000000000000000000000000000010200b0000000000000000000000000000000000000000000000000000000000102015000000000000000000000000000000000000000000000000000000000010200c0000000000000000000000000000000000000000000000000000000000102016000000000000000000000000000000000000000000000000000000000010200d0000000000000000000000000000000000000000000000000000000000102017000000000000000000000000000000000000000000000000000000000010200e0000000000000000000000000000000000000000000000000000000000102018000000000000000000000000000000000000000000000000000000000010200f00000000000000000000000000000000000000000000000000000000001020190000000000000000000000000000000000000000000000000000000000102010000000000000000000000000000000000000000000000000000000000010201a0000000000000000000000000000000000000000000000000000000000102011000000000000000000000000000000000000000000000000000000000010201b0000000000000000000000000000000000000000000000000000000000102012000000000000000000000000000000000000000000000000000000000010201c0000000000000000000000000000000000000000000000000000000000102013000000000000000000000000000000000000000000000000000000000010201d0000000000000000000000000000000000000000000000000000000000102014000000000000000000000000000000000000000000000000000000000010201e0000000000000000000000000000000000000000000000000000000000102015000000000000000000000000000000000000000000000000000000000010201f00000000000000000000000000000000000000000000000000000000001020160000000000000000000000000000000000000000000000000000000000102020000000000000000000000000000000000000000000000000000000000010201700000000000000000000000000000000000000000000000000000000001020210000000000000000000000000000000000000000000000000000000000102018000000000000000000000000000000000000000000000000000000000010202200000000000000000000000000000000000000000000000000000000001020190000000000000000000000000000000000000000000000000000000000102023000000000000000000000000000000000000000000000000000000000010201a0000000000000000000000000000000000000000000000000000000000102024000000000000000000000000000000000000000000000000000000000010201b0000000000000000000000000000000000000000000000000000000000102025000000000000000000000000000000000000000000000000000000000010201c0000000000000000000000000000000000000000000000000000000000102026000000000000000000000000000000000000000000000000000000000010201d0000000000000000000000000000000000000000000000000000000000102027000000000000000000000000000000000000000000000000000000000010201e0000000000000000000000000000000000000000000000000000000000102028000000000000000000000000000000000000000000000000000000000010201f00000000000000000000000000000000000000000000000000000000001020290000000000000000000000000000000000000000000000000000000000102020000000000000000000000000000000000000000000000000000000000010202a0000000000000000000000000000000000000000000000000000000000102021000000000000000000000000000000000000000000000000000000000010202b0000000000000000000000000000000000000000000000000000000000102022000000000000000000000000000000000000000000000000000000000010202c0000000000000000000000000000000000000000000000000000000000102023000000000000000000000000000000000000000000000000000000000010202d0000000000000000000000000000000000000000000000000000000000102024000000000000000000000000000000000000000000000000000000000010202e0000000000000000000000000000000000000000000000000000000000102025000000000000000000000000000000000000000000000000000000000010202f00000000000000000000000000000000000000000000000000000000001020260000000000000000000000000000000000000000000000000000000000102030000000000000000000000000000000000000000000000000000000000010202700000000000000000000000000000000000000000000000000000000001020310000000000000000000000000000000000000000000000000000000000102028000000000000000000000000000000000000000000000000000000000010203200000000000000000000000000000000000000000000000000000000001020290000000000000000000000000000000000000000000000000000000000102033000000000000000000000000000000000000000000000000000000000010202a0000000000000000000000000000000000000000000000000000000000102034000000000000000000000000000000000000000000000000000000000010202b0000000000000000000000000000000000000000000000000000000000102035000000000000000000000000000000000000000000000000000000000010202c0000000000000000000000000000000000000000000000000000000000102036000000000000000000000000000000000000000000000000000000000010202d0000000000000000000000000000000000000000000000000000000000102037000000000000000000000000000000000000000000000000000000000010202e0000000000000000000000000000000000000000000000000000000000102038000000000000000000000000000000000000000000000000000000000010202f00000000000000000000000000000000000000000000000000000000001020390000000000000000000000000000000000000000000000000000000000102030000000000000000000000000000000000000000000000000000000000010203a0000000000000000000000000000000000000000000000000000000000102031000000000000000000000000000000000000000000000000000000000010203b0000000000000000000000000000000000000000000000000000000000102032000000000000000000000000000000000000000000000000000000000010203c0000000000000000000000000000000000000000000000000000000000102033000000000000000000000000000000000000000000000000000000000010203d0000000000000000000000000000000000000000000000000000000000102034000000000000000000000000000000000000000000000000000000000010203e0000000000000000000000000000000000000000000000000000000000102035000000000000000000000000000000000000000000000000000000000010203f00000000000000000000000000000000000000000000000000000000001020360000000000000000000000000000000000000000000000000000000000102040000000000000000000000000000000000000000000000000000000000010203700000000000000000000000000000000000000000000000000000000001020410000000000000000000000000000000000000000000000000000000000102038000000000000000000000000000000000000000000000000000000000010204200000000000000000000000000000000000000000000000000000000001020390000000000000000000000000000000000000000000000000000000000102043000000000000000000000000000000000000000000000000000000000010203a0000000000000000000000000000000000000000000000000000000000102044000000000000000000000000000000000000000000000000000000000010203b0000000000000000000000000000000000000000000000000000000000102045000000000000000000000000000000000000000000000000000000000010203c0000000000000000000000000000000000000000000000000000000000102046000000000000000000000000000000000000000000000000000000000010203d0000000000000000000000000000000000000000000000000000000000102047000000000000000000000000000000000000000000000000000000000010203e0000000000000000000000000000000000000000000000000000000000102048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000014100100000000000000000000000000000000000000000000000000000000001410020000000000000000000000000000000000000000000000000000000000141003000000000000000000000000000000000000000000000000000000000014100400000000000000000000000000000000000000000000000000000000001410050000000000000000000000000000000000000000000000000000000000141006000000000000000000000000000000000000000000000000000000000014100700000000000000000000000000000000000000000000000000000000001410080000000000000000000000000000000000000000000000000000000000141009000000000000000000000000000000000000000000000000000000000014100a000000000000000000000000000000000000000000000000000000000014100b000000000000000000000000000000000000000000000000000000000014100c000000000000000000000000000000000000000000000000000000000014100d000000000000000000000000000000000000000000000000000000000014100e000000000000000000000000000000000000000000000000000000000014100f0000000000000000000000000000000000000000000000000000000000141010000000000000000000000000000000000000000000000000000000000014101100000000000000000000000000000000000000000000000000000000001410120000000000000000000000000000000000000000000000000000000000141013000000000000000000000000000000000000000000000000000000000014101400000000000000000000000000000000000000000000000000000000001410150000000000000000000000000000000000000000000000000000000000141016000000000000000000000000000000000000000000000000000000000014101700000000000000000000000000000000000000000000000000000000001410180000000000000000000000000000000000000000000000000000000000141019000000000000000000000000000000000000000000000000000000000014101a000000000000000000000000000000000000000000000000000000000014101b000000000000000000000000000000000000000000000000000000000014101c000000000000000000000000000000000000000000000000000000000014101d000000000000000000000000000000000000000000000000000000000014101e000000000000000000000000000000000000000000000000000000000014101f0000000000000000000000000000000000000000000000000000000000141020000000000000000000000000000000000000000000000000000000000014102100000000000000000000000000000000000000000000000000000000001410220000000000000000000000000000000000000000000000000000000000141023000000000000000000000000000000000000000000000000000000000014102400000000000000000000000000000000000000000000000000000000001410250000000000000000000000000000000000000000000000000000000000141026000000000000000000000000000000000000000000000000000000000014102700000000000000000000000000000000000000000000000000000000001410280000000000000000000000000000000000000000000000000000000000141029000000000000000000000000000000000000000000000000000000000014102a000000000000000000000000000000000000000000000000000000000014102b000000000000000000000000000000000000000000000000000000000014102c000000000000000000000000000000000000000000000000000000000014102d000000000000000000000000000000000000000000000000000000000014102e000000000000000000000000000000000000000000000000000000000014102f0000000000000000000000000000000000000000000000000000000000141030000000000000000000000000000000000000000000000000000000000014103100000000000000000000000000000000000000000000000000000000001410320000000000000000000000000000000000000000000000000000000000141033000000000000000000000000000000000000000000000000000000000014103400000000000000000000000000000000000000000000000000000000001410350000000000000000000000000000000000000000000000000000000000141036000000000000000000000000000000000000000000000000000000000014103700000000000000000000000000000000000000000000000000000000001410380000000000000000000000000000000000000000000000000000000000141039000000000000000000000000000000000000000000000000000000000014103a000000000000000000000000000000000000000000000000000000000014103b000000000000000000000000000000000000000000000000000000000014103c000000000000000000000000000000000000000000000000000000000014103d000000000000000000000000000000000000000000000000000000000014103e000000000000000000000000000000000000000000000000000000000014103f3f0000000000000000000000000000000000000000000000000000000000141100000000000000000000000000000000000000000000000000000000000014110100000000000000000000000000000000000000000000000000000000001411020000000000000000000000000000000000000000000000000000000000141103000000000000000000000000000000000000000000000000000000000014110400000000000000000000000000000000000000000000000000000000001411050000000000000000000000000000000000000000000000000000000000141106000000000000000000000000000000000000000000000000000000000014110700000000000000000000000000000000000000000000000000000000001411080000000000000000000000000000000000000000000000000000000000141109000000000000000000000000000000000000000000000000000000000014110a000000000000000000000000000000000000000000000000000000000014110b000000000000000000000000000000000000000000000000000000000014110c000000000000000000000000000000000000000000000000000000000014110d000000000000000000000000000000000000000000000000000000000014110e000000000000000000000000000000000000000000000000000000000014110f0000000000000000000000000000000000000000000000000000000000141110000000000000000000000000000000000000000000000000000000000014111100000000000000000000000000000000000000000000000000000000001411120000000000000000000000000000000000000000000000000000000000141113000000000000000000000000000000000000000000000000000000000014111400000000000000000000000000000000000000000000000000000000001411150000000000000000000000000000000000000000000000000000000000141116000000000000000000000000000000000000000000000000000000000014111700000000000000000000000000000000000000000000000000000000001411180000000000000000000000000000000000000000000000000000000000141119000000000000000000000000000000000000000000000000000000000014111a000000000000000000000000000000000000000000000000000000000014111b000000000000000000000000000000000000000000000000000000000014111c000000000000000000000000000000000000000000000000000000000014111d000000000000000000000000000000000000000000000000000000000014111e000000000000000000000000000000000000000000000000000000000014111f0000000000000000000000000000000000000000000000000000000000141120000000000000000000000000000000000000000000000000000000000014112100000000000000000000000000000000000000000000000000000000001411220000000000000000000000000000000000000000000000000000000000141123000000000000000000000000000000000000000000000000000000000014112400000000000000000000000000000000000000000000000000000000001411250000000000000000000000000000000000000000000000000000000000141126000000000000000000000000000000000000000000000000000000000014112700000000000000000000000000000000000000000000000000000000001411280000000000000000000000000000000000000000000000000000000000141129000000000000000000000000000000000000000000000000000000000014112a000000000000000000000000000000000000000000000000000000000014112b000000000000000000000000000000000000000000000000000000000014112c000000000000000000000000000000000000000000000000000000000014112d000000000000000000000000000000000000000000000000000000000014112e000000000000000000000000000000000000000000000000000000000014112f0000000000000000000000000000000000000000000000000000000000141130000000000000000000000000000000000000000000000000000000000014113100000000000000000000000000000000000000000000000000000000001411320000000000000000000000000000000000000000000000000000000000141133000000000000000000000000000000000000000000000000000000000014113400000000000000000000000000000000000000000000000000000000001411350000000000000000000000000000000000000000000000000000000000141136000000000000000000000000000000000000000000000000000000000014113700000000000000000000000000000000000000000000000000000000001411380000000000000000000000000000000000000000000000000000000000141139000000000000000000000000000000000000000000000000000000000014113a000000000000000000000000000000000000000000000000000000000014113b000000000000000000000000000000000000000000000000000000000014113c000000000000000000000000000000000000000000000000000000000014113d000000000000000000000000000000000000000000000000000000000014113e08005c015113cb57d67dd6c0febd596819ac0298b6a23fc80aba17d445d540059a00f20b7d1308051fe7b68031a7c336b0b4b56738928b6510133aff1b818d5a9a0063eec1883a4f95f4933f9275e850d84b3d035f5061ed986c437a07331fd30e00d3a32d6bbc4fd843686fd0c5e118a73b847529977dca5b9e0e81f6604f22ca00c2f4f5133d9194d41e853e5e951e16690babce8461f25342c0bad20f2aa1e3000a6bf4739e7eb387913d955dc2e8f14f8cce27696b9d2e128b6acefafb80ee005763f7e0648f958b559677622a648f318fc79ebc0cb539170d49c26456e69200302e2b8a92cda941e9af8761b89899a58a587656d9710594e1d865b16522993f0000000000000000000000000000000000000000000000000000000000142000000000000000000000000000000000000000000000000000000000000014200a0000000000000000000000000000000000000000000000000000000000142001000000000000000000000000000000000000000000000000000000000014200b0000000000000000000000000000000000000000000000000000000000142002000000000000000000000000000000000000000000000000000000000014200c0000000000000000000000000000000000000000000000000000000000142003000000000000000000000000000000000000000000000000000000000014200d0000000000000000000000000000000000000000000000000000000000142004000000000000000000000000000000000000000000000000000000000014200e0000000000000000000000000000000000000000000000000000000000142005000000000000000000000000000000000000000000000000000000000014200f00000000000000000000000000000000000000000000000000000000001420060000000000000000000000000000000000000000000000000000000000142010000000000000000000000000000000000000000000000000000000000014200700000000000000000000000000000000000000000000000000000000001420110000000000000000000000000000000000000000000000000000000000142008000000000000000000000000000000000000000000000000000000000014201200000000000000000000000000000000000000000000000000000000001420090000000000000000000000000000000000000000000000000000000000142013000000000000000000000000000000000000000000000000000000000014200a0000000000000000000000000000000000000000000000000000000000142014000000000000000000000000000000000000000000000000000000000014200b0000000000000000000000000000000000000000000000000000000000142015000000000000000000000000000000000000000000000000000000000014200c0000000000000000000000000000000000000000000000000000000000142016000000000000000000000000000000000000000000000000000000000014200d0000000000000000000000000000000000000000000000000000000000142017000000000000000000000000000000000000000000000000000000000014200e0000000000000000000000000000000000000000000000000000000000142018000000000000000000000000000000000000000000000000000000000014200f00000000000000000000000000000000000000000000000000000000001420190000000000000000000000000000000000000000000000000000000000142010000000000000000000000000000000000000000000000000000000000014201a0000000000000000000000000000000000000000000000000000000000142011000000000000000000000000000000000000000000000000000000000014201b0000000000000000000000000000000000000000000000000000000000142012000000000000000000000000000000000000000000000000000000000014201c0000000000000000000000000000000000000000000000000000000000142013000000000000000000000000000000000000000000000000000000000014201d0000000000000000000000000000000000000000000000000000000000142014000000000000000000000000000000000000000000000000000000000014201e0000000000000000000000000000000000000000000000000000000000142015000000000000000000000000000000000000000000000000000000000014201f00000000000000000000000000000000000000000000000000000000001420160000000000000000000000000000000000000000000000000000000000142020000000000000000000000000000000000000000000000000000000000014201700000000000000000000000000000000000000000000000000000000001420210000000000000000000000000000000000000000000000000000000000142018000000000000000000000000000000000000000000000000000000000014202200000000000000000000000000000000000000000000000000000000001420190000000000000000000000000000000000000000000000000000000000142023000000000000000000000000000000000000000000000000000000000014201a0000000000000000000000000000000000000000000000000000000000142024000000000000000000000000000000000000000000000000000000000014201b0000000000000000000000000000000000000000000000000000000000142025000000000000000000000000000000000000000000000000000000000014201c0000000000000000000000000000000000000000000000000000000000142026000000000000000000000000000000000000000000000000000000000014201d0000000000000000000000000000000000000000000000000000000000142027000000000000000000000000000000000000000000000000000000000014201e0000000000000000000000000000000000000000000000000000000000142028000000000000000000000000000000000000000000000000000000000014201f00000000000000000000000000000000000000000000000000000000001420290000000000000000000000000000000000000000000000000000000000142020000000000000000000000000000000000000000000000000000000000014202a0000000000000000000000000000000000000000000000000000000000142021000000000000000000000000000000000000000000000000000000000014202b0000000000000000000000000000000000000000000000000000000000142022000000000000000000000000000000000000000000000000000000000014202c0000000000000000000000000000000000000000000000000000000000142023000000000000000000000000000000000000000000000000000000000014202d0000000000000000000000000000000000000000000000000000000000142024000000000000000000000000000000000000000000000000000000000014202e0000000000000000000000000000000000000000000000000000000000142025000000000000000000000000000000000000000000000000000000000014202f00000000000000000000000000000000000000000000000000000000001420260000000000000000000000000000000000000000000000000000000000142030000000000000000000000000000000000000000000000000000000000014202700000000000000000000000000000000000000000000000000000000001420310000000000000000000000000000000000000000000000000000000000142028000000000000000000000000000000000000000000000000000000000014203200000000000000000000000000000000000000000000000000000000001420290000000000000000000000000000000000000000000000000000000000142033000000000000000000000000000000000000000000000000000000000014202a0000000000000000000000000000000000000000000000000000000000142034000000000000000000000000000000000000000000000000000000000014202b0000000000000000000000000000000000000000000000000000000000142035000000000000000000000000000000000000000000000000000000000014202c0000000000000000000000000000000000000000000000000000000000142036000000000000000000000000000000000000000000000000000000000014202d0000000000000000000000000000000000000000000000000000000000142037000000000000000000000000000000000000000000000000000000000014202e0000000000000000000000000000000000000000000000000000000000142038000000000000000000000000000000000000000000000000000000000014202f00000000000000000000000000000000000000000000000000000000001420390000000000000000000000000000000000000000000000000000000000142030000000000000000000000000000000000000000000000000000000000014203a0000000000000000000000000000000000000000000000000000000000142031000000000000000000000000000000000000000000000000000000000014203b0000000000000000000000000000000000000000000000000000000000142032000000000000000000000000000000000000000000000000000000000014203c0000000000000000000000000000000000000000000000000000000000142033000000000000000000000000000000000000000000000000000000000014203d0000000000000000000000000000000000000000000000000000000000142034000000000000000000000000000000000000000000000000000000000014203e0000000000000000000000000000000000000000000000000000000000142035000000000000000000000000000000000000000000000000000000000014203f00000000000000000000000000000000000000000000000000000000001420360000000000000000000000000000000000000000000000000000000000142040000000000000000000000000000000000000000000000000000000000014203700000000000000000000000000000000000000000000000000000000001420410000000000000000000000000000000000000000000000000000000000142038000000000000000000000000000000000000000000000000000000000014204200000000000000000000000000000000000000000000000000000000001420390000000000000000000000000000000000000000000000000000000000142043000000000000000000000000000000000000000000000000000000000014203a0000000000000000000000000000000000000000000000000000000000142044000000000000000000000000000000000000000000000000000000000014203b0000000000000000000000000000000000000000000000000000000000142045000000000000000000000000000000000000000000000000000000000014203c0000000000000000000000000000000000000000000000000000000000142046000000000000000000000000000000000000000000000000000000000014203d0000000000000000000000000000000000000000000000000000000000142047000000000000000000000000000000000000000000000000000000000014203e0000000000000000000000000000000000000000000000000000000000142048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000181000000000000000000000000000000000000000000000000000000000000018100100000000000000000000000000000000000000000000000000000000001810020000000000000000000000000000000000000000000000000000000000181003000000000000000000000000000000000000000000000000000000000018100400000000000000000000000000000000000000000000000000000000001810050000000000000000000000000000000000000000000000000000000000181006000000000000000000000000000000000000000000000000000000000018100700000000000000000000000000000000000000000000000000000000001810080000000000000000000000000000000000000000000000000000000000181009000000000000000000000000000000000000000000000000000000000018100a000000000000000000000000000000000000000000000000000000000018100b000000000000000000000000000000000000000000000000000000000018100c000000000000000000000000000000000000000000000000000000000018100d000000000000000000000000000000000000000000000000000000000018100e000000000000000000000000000000000000000000000000000000000018100f0000000000000000000000000000000000000000000000000000000000181010000000000000000000000000000000000000000000000000000000000018101100000000000000000000000000000000000000000000000000000000001810120000000000000000000000000000000000000000000000000000000000181013000000000000000000000000000000000000000000000000000000000018101400000000000000000000000000000000000000000000000000000000001810150000000000000000000000000000000000000000000000000000000000181016000000000000000000000000000000000000000000000000000000000018101700000000000000000000000000000000000000000000000000000000001810180000000000000000000000000000000000000000000000000000000000181019000000000000000000000000000000000000000000000000000000000018101a000000000000000000000000000000000000000000000000000000000018101b000000000000000000000000000000000000000000000000000000000018101c000000000000000000000000000000000000000000000000000000000018101d000000000000000000000000000000000000000000000000000000000018101e000000000000000000000000000000000000000000000000000000000018101f0000000000000000000000000000000000000000000000000000000000181020000000000000000000000000000000000000000000000000000000000018102100000000000000000000000000000000000000000000000000000000001810220000000000000000000000000000000000000000000000000000000000181023000000000000000000000000000000000000000000000000000000000018102400000000000000000000000000000000000000000000000000000000001810250000000000000000000000000000000000000000000000000000000000181026000000000000000000000000000000000000000000000000000000000018102700000000000000000000000000000000000000000000000000000000001810280000000000000000000000000000000000000000000000000000000000181029000000000000000000000000000000000000000000000000000000000018102a000000000000000000000000000000000000000000000000000000000018102b000000000000000000000000000000000000000000000000000000000018102c000000000000000000000000000000000000000000000000000000000018102d000000000000000000000000000000000000000000000000000000000018102e000000000000000000000000000000000000000000000000000000000018102f0000000000000000000000000000000000000000000000000000000000181030000000000000000000000000000000000000000000000000000000000018103100000000000000000000000000000000000000000000000000000000001810320000000000000000000000000000000000000000000000000000000000181033000000000000000000000000000000000000000000000000000000000018103400000000000000000000000000000000000000000000000000000000001810350000000000000000000000000000000000000000000000000000000000181036000000000000000000000000000000000000000000000000000000000018103700000000000000000000000000000000000000000000000000000000001810380000000000000000000000000000000000000000000000000000000000181039000000000000000000000000000000000000000000000000000000000018103a000000000000000000000000000000000000000000000000000000000018103b000000000000000000000000000000000000000000000000000000000018103c000000000000000000000000000000000000000000000000000000000018103d000000000000000000000000000000000000000000000000000000000018103e000000000000000000000000000000000000000000000000000000000018103f3f0000000000000000000000000000000000000000000000000000000000181100000000000000000000000000000000000000000000000000000000000018110100000000000000000000000000000000000000000000000000000000001811020000000000000000000000000000000000000000000000000000000000181103000000000000000000000000000000000000000000000000000000000018110400000000000000000000000000000000000000000000000000000000001811050000000000000000000000000000000000000000000000000000000000181106000000000000000000000000000000000000000000000000000000000018110700000000000000000000000000000000000000000000000000000000001811080000000000000000000000000000000000000000000000000000000000181109000000000000000000000000000000000000000000000000000000000018110a000000000000000000000000000000000000000000000000000000000018110b000000000000000000000000000000000000000000000000000000000018110c000000000000000000000000000000000000000000000000000000000018110d000000000000000000000000000000000000000000000000000000000018110e000000000000000000000000000000000000000000000000000000000018110f0000000000000000000000000000000000000000000000000000000000181110000000000000000000000000000000000000000000000000000000000018111100000000000000000000000000000000000000000000000000000000001811120000000000000000000000000000000000000000000000000000000000181113000000000000000000000000000000000000000000000000000000000018111400000000000000000000000000000000000000000000000000000000001811150000000000000000000000000000000000000000000000000000000000181116000000000000000000000000000000000000000000000000000000000018111700000000000000000000000000000000000000000000000000000000001811180000000000000000000000000000000000000000000000000000000000181119000000000000000000000000000000000000000000000000000000000018111a000000000000000000000000000000000000000000000000000000000018111b000000000000000000000000000000000000000000000000000000000018111c000000000000000000000000000000000000000000000000000000000018111d000000000000000000000000000000000000000000000000000000000018111e000000000000000000000000000000000000000000000000000000000018111f0000000000000000000000000000000000000000000000000000000000181120000000000000000000000000000000000000000000000000000000000018112100000000000000000000000000000000000000000000000000000000001811220000000000000000000000000000000000000000000000000000000000181123000000000000000000000000000000000000000000000000000000000018112400000000000000000000000000000000000000000000000000000000001811250000000000000000000000000000000000000000000000000000000000181126000000000000000000000000000000000000000000000000000000000018112700000000000000000000000000000000000000000000000000000000001811280000000000000000000000000000000000000000000000000000000000181129000000000000000000000000000000000000000000000000000000000018112a000000000000000000000000000000000000000000000000000000000018112b000000000000000000000000000000000000000000000000000000000018112c000000000000000000000000000000000000000000000000000000000018112d000000000000000000000000000000000000000000000000000000000018112e000000000000000000000000000000000000000000000000000000000018112f0000000000000000000000000000000000000000000000000000000000181130000000000000000000000000000000000000000000000000000000000018113100000000000000000000000000000000000000000000000000000000001811320000000000000000000000000000000000000000000000000000000000181133000000000000000000000000000000000000000000000000000000000018113400000000000000000000000000000000000000000000000000000000001811350000000000000000000000000000000000000000000000000000000000181136000000000000000000000000000000000000000000000000000000000018113700000000000000000000000000000000000000000000000000000000001811380000000000000000000000000000000000000000000000000000000000181139000000000000000000000000000000000000000000000000000000000018113a000000000000000000000000000000000000000000000000000000000018113b000000000000000000000000000000000000000000000000000000000018113c000000000000000000000000000000000000000000000000000000000018113d000000000000000000000000000000000000000000000000000000000018113e0800f872eb9653f03af10f331da1361fa1524d3cd958cb72dacea1d424f19df3af00ffc548a17cd6ba1f2d228f30e4ddb19ecc46ad3b609977d52bb0f49e1206410032f8058bd779c520eabae2743b02ec4f71670428506fcceb2d4b69f26fb11800c0283e15fbf74ffa4eafb984030394f3c2ea6733cc0eacb0431a9475eff28f00b7f55314bfd9d441c1c624e241908228fe4da3d3a0a7fbd56814e1c8cd5d3e00f430f33a786675271736fd728c7bf7428b8c24ac948d7faf76ddb8783a496c0048fc235ead8d4b9d44929662a6384074fc4e5076bec5b7deb34f612393684300fd9b61cb1ad9b4b28f58399906e73933e3cccee8fc98a393f0eedb95b13ee63f0000000000000000000000000000000000000000000000000000000000182000000000000000000000000000000000000000000000000000000000000018200a0000000000000000000000000000000000000000000000000000000000182001000000000000000000000000000000000000000000000000000000000018200b0000000000000000000000000000000000000000000000000000000000182002000000000000000000000000000000000000000000000000000000000018200c0000000000000000000000000000000000000000000000000000000000182003000000000000000000000000000000000000000000000000000000000018200d0000000000000000000000000000000000000000000000000000000000182004000000000000000000000000000000000000000000000000000000000018200e0000000000000000000000000000000000000000000000000000000000182005000000000000000000000000000000000000000000000000000000000018200f00000000000000000000000000000000000000000000000000000000001820060000000000000000000000000000000000000000000000000000000000182010000000000000000000000000000000000000000000000000000000000018200700000000000000000000000000000000000000000000000000000000001820110000000000000000000000000000000000000000000000000000000000182008000000000000000000000000000000000000000000000000000000000018201200000000000000000000000000000000000000000000000000000000001820090000000000000000000000000000000000000000000000000000000000182013000000000000000000000000000000000000000000000000000000000018200a0000000000000000000000000000000000000000000000000000000000182014000000000000000000000000000000000000000000000000000000000018200b0000000000000000000000000000000000000000000000000000000000182015000000000000000000000000000000000000000000000000000000000018200c0000000000000000000000000000000000000000000000000000000000182016000000000000000000000000000000000000000000000000000000000018200d0000000000000000000000000000000000000000000000000000000000182017000000000000000000000000000000000000000000000000000000000018200e0000000000000000000000000000000000000000000000000000000000182018000000000000000000000000000000000000000000000000000000000018200f00000000000000000000000000000000000000000000000000000000001820190000000000000000000000000000000000000000000000000000000000182010000000000000000000000000000000000000000000000000000000000018201a0000000000000000000000000000000000000000000000000000000000182011000000000000000000000000000000000000000000000000000000000018201b0000000000000000000000000000000000000000000000000000000000182012000000000000000000000000000000000000000000000000000000000018201c0000000000000000000000000000000000000000000000000000000000182013000000000000000000000000000000000000000000000000000000000018201d0000000000000000000000000000000000000000000000000000000000182014000000000000000000000000000000000000000000000000000000000018201e0000000000000000000000000000000000000000000000000000000000182015000000000000000000000000000000000000000000000000000000000018201f00000000000000000000000000000000000000000000000000000000001820160000000000000000000000000000000000000000000000000000000000182020000000000000000000000000000000000000000000000000000000000018201700000000000000000000000000000000000000000000000000000000001820210000000000000000000000000000000000000000000000000000000000182018000000000000000000000000000000000000000000000000000000000018202200000000000000000000000000000000000000000000000000000000001820190000000000000000000000000000000000000000000000000000000000182023000000000000000000000000000000000000000000000000000000000018201a0000000000000000000000000000000000000000000000000000000000182024000000000000000000000000000000000000000000000000000000000018201b0000000000000000000000000000000000000000000000000000000000182025000000000000000000000000000000000000000000000000000000000018201c0000000000000000000000000000000000000000000000000000000000182026000000000000000000000000000000000000000000000000000000000018201d0000000000000000000000000000000000000000000000000000000000182027000000000000000000000000000000000000000000000000000000000018201e0000000000000000000000000000000000000000000000000000000000182028000000000000000000000000000000000000000000000000000000000018201f00000000000000000000000000000000000000000000000000000000001820290000000000000000000000000000000000000000000000000000000000182020000000000000000000000000000000000000000000000000000000000018202a0000000000000000000000000000000000000000000000000000000000182021000000000000000000000000000000000000000000000000000000000018202b0000000000000000000000000000000000000000000000000000000000182022000000000000000000000000000000000000000000000000000000000018202c0000000000000000000000000000000000000000000000000000000000182023000000000000000000000000000000000000000000000000000000000018202d0000000000000000000000000000000000000000000000000000000000182024000000000000000000000000000000000000000000000000000000000018202e0000000000000000000000000000000000000000000000000000000000182025000000000000000000000000000000000000000000000000000000000018202f00000000000000000000000000000000000000000000000000000000001820260000000000000000000000000000000000000000000000000000000000182030000000000000000000000000000000000000000000000000000000000018202700000000000000000000000000000000000000000000000000000000001820310000000000000000000000000000000000000000000000000000000000182028000000000000000000000000000000000000000000000000000000000018203200000000000000000000000000000000000000000000000000000000001820290000000000000000000000000000000000000000000000000000000000182033000000000000000000000000000000000000000000000000000000000018202a0000000000000000000000000000000000000000000000000000000000182034000000000000000000000000000000000000000000000000000000000018202b0000000000000000000000000000000000000000000000000000000000182035000000000000000000000000000000000000000000000000000000000018202c0000000000000000000000000000000000000000000000000000000000182036000000000000000000000000000000000000000000000000000000000018202d0000000000000000000000000000000000000000000000000000000000182037000000000000000000000000000000000000000000000000000000000018202e0000000000000000000000000000000000000000000000000000000000182038000000000000000000000000000000000000000000000000000000000018202f00000000000000000000000000000000000000000000000000000000001820390000000000000000000000000000000000000000000000000000000000182030000000000000000000000000000000000000000000000000000000000018203a0000000000000000000000000000000000000000000000000000000000182031000000000000000000000000000000000000000000000000000000000018203b0000000000000000000000000000000000000000000000000000000000182032000000000000000000000000000000000000000000000000000000000018203c0000000000000000000000000000000000000000000000000000000000182033000000000000000000000000000000000000000000000000000000000018203d0000000000000000000000000000000000000000000000000000000000182034000000000000000000000000000000000000000000000000000000000018203e0000000000000000000000000000000000000000000000000000000000182035000000000000000000000000000000000000000000000000000000000018203f00000000000000000000000000000000000000000000000000000000001820360000000000000000000000000000000000000000000000000000000000182040000000000000000000000000000000000000000000000000000000000018203700000000000000000000000000000000000000000000000000000000001820410000000000000000000000000000000000000000000000000000000000182038000000000000000000000000000000000000000000000000000000000018204200000000000000000000000000000000000000000000000000000000001820390000000000000000000000000000000000000000000000000000000000182043000000000000000000000000000000000000000000000000000000000018203a0000000000000000000000000000000000000000000000000000000000182044000000000000000000000000000000000000000000000000000000000018203b0000000000000000000000000000000000000000000000000000000000182045000000000000000000000000000000000000000000000000000000000018203c0000000000000000000000000000000000000000000000000000000000182046000000000000000000000000000000000000000000000000000000000018203d0000000000000000000000000000000000000000000000000000000000182047000000000000000000000000000000000000000000000000000000000018203e00000000000000000000000000000000000000000000000000000000001820480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c100100000000000000000000000000000000000000000000000000000000001c100200000000000000000000000000000000000000000000000000000000001c100300000000000000000000000000000000000000000000000000000000001c100400000000000000000000000000000000000000000000000000000000001c100500000000000000000000000000000000000000000000000000000000001c100600000000000000000000000000000000000000000000000000000000001c100700000000000000000000000000000000000000000000000000000000001c100800000000000000000000000000000000000000000000000000000000001c100900000000000000000000000000000000000000000000000000000000001c100a00000000000000000000000000000000000000000000000000000000001c100b00000000000000000000000000000000000000000000000000000000001c100c00000000000000000000000000000000000000000000000000000000001c100d00000000000000000000000000000000000000000000000000000000001c100e00000000000000000000000000000000000000000000000000000000001c100f00000000000000000000000000000000000000000000000000000000001c101000000000000000000000000000000000000000000000000000000000001c101100000000000000000000000000000000000000000000000000000000001c101200000000000000000000000000000000000000000000000000000000001c101300000000000000000000000000000000000000000000000000000000001c101400000000000000000000000000000000000000000000000000000000001c101500000000000000000000000000000000000000000000000000000000001c101600000000000000000000000000000000000000000000000000000000001c101700000000000000000000000000000000000000000000000000000000001c101800000000000000000000000000000000000000000000000000000000001c101900000000000000000000000000000000000000000000000000000000001c101a00000000000000000000000000000000000000000000000000000000001c101b00000000000000000000000000000000000000000000000000000000001c101c00000000000000000000000000000000000000000000000000000000001c101d00000000000000000000000000000000000000000000000000000000001c101e00000000000000000000000000000000000000000000000000000000001c101f00000000000000000000000000000000000000000000000000000000001c102000000000000000000000000000000000000000000000000000000000001c102100000000000000000000000000000000000000000000000000000000001c102200000000000000000000000000000000000000000000000000000000001c102300000000000000000000000000000000000000000000000000000000001c102400000000000000000000000000000000000000000000000000000000001c102500000000000000000000000000000000000000000000000000000000001c102600000000000000000000000000000000000000000000000000000000001c102700000000000000000000000000000000000000000000000000000000001c102800000000000000000000000000000000000000000000000000000000001c102900000000000000000000000000000000000000000000000000000000001c102a00000000000000000000000000000000000000000000000000000000001c102b00000000000000000000000000000000000000000000000000000000001c102c00000000000000000000000000000000000000000000000000000000001c102d00000000000000000000000000000000000000000000000000000000001c102e00000000000000000000000000000000000000000000000000000000001c102f00000000000000000000000000000000000000000000000000000000001c103000000000000000000000000000000000000000000000000000000000001c103100000000000000000000000000000000000000000000000000000000001c103200000000000000000000000000000000000000000000000000000000001c103300000000000000000000000000000000000000000000000000000000001c103400000000000000000000000000000000000000000000000000000000001c103500000000000000000000000000000000000000000000000000000000001c103600000000000000000000000000000000000000000000000000000000001c103700000000000000000000000000000000000000000000000000000000001c103800000000000000000000000000000000000000000000000000000000001c103900000000000000000000000000000000000000000000000000000000001c103a00000000000000000000000000000000000000000000000000000000001c103b00000000000000000000000000000000000000000000000000000000001c103c00000000000000000000000000000000000000000000000000000000001c103d00000000000000000000000000000000000000000000000000000000001c103e00000000000000000000000000000000000000000000000000000000001c103f3f00000000000000000000000000000000000000000000000000000000001c110000000000000000000000000000000000000000000000000000000000001c110100000000000000000000000000000000000000000000000000000000001c110200000000000000000000000000000000000000000000000000000000001c110300000000000000000000000000000000000000000000000000000000001c110400000000000000000000000000000000000000000000000000000000001c110500000000000000000000000000000000000000000000000000000000001c110600000000000000000000000000000000000000000000000000000000001c110700000000000000000000000000000000000000000000000000000000001c110800000000000000000000000000000000000000000000000000000000001c110900000000000000000000000000000000000000000000000000000000001c110a00000000000000000000000000000000000000000000000000000000001c110b00000000000000000000000000000000000000000000000000000000001c110c00000000000000000000000000000000000000000000000000000000001c110d00000000000000000000000000000000000000000000000000000000001c110e00000000000000000000000000000000000000000000000000000000001c110f00000000000000000000000000000000000000000000000000000000001c111000000000000000000000000000000000000000000000000000000000001c111100000000000000000000000000000000000000000000000000000000001c111200000000000000000000000000000000000000000000000000000000001c111300000000000000000000000000000000000000000000000000000000001c111400000000000000000000000000000000000000000000000000000000001c111500000000000000000000000000000000000000000000000000000000001c111600000000000000000000000000000000000000000000000000000000001c111700000000000000000000000000000000000000000000000000000000001c111800000000000000000000000000000000000000000000000000000000001c111900000000000000000000000000000000000000000000000000000000001c111a00000000000000000000000000000000000000000000000000000000001c111b00000000000000000000000000000000000000000000000000000000001c111c00000000000000000000000000000000000000000000000000000000001c111d00000000000000000000000000000000000000000000000000000000001c111e00000000000000000000000000000000000000000000000000000000001c111f00000000000000000000000000000000000000000000000000000000001c112000000000000000000000000000000000000000000000000000000000001c112100000000000000000000000000000000000000000000000000000000001c112200000000000000000000000000000000000000000000000000000000001c112300000000000000000000000000000000000000000000000000000000001c112400000000000000000000000000000000000000000000000000000000001c112500000000000000000000000000000000000000000000000000000000001c112600000000000000000000000000000000000000000000000000000000001c112700000000000000000000000000000000000000000000000000000000001c112800000000000000000000000000000000000000000000000000000000001c112900000000000000000000000000000000000000000000000000000000001c112a00000000000000000000000000000000000000000000000000000000001c112b00000000000000000000000000000000000000000000000000000000001c112c00000000000000000000000000000000000000000000000000000000001c112d00000000000000000000000000000000000000000000000000000000001c112e00000000000000000000000000000000000000000000000000000000001c112f00000000000000000000000000000000000000000000000000000000001c113000000000000000000000000000000000000000000000000000000000001c113100000000000000000000000000000000000000000000000000000000001c113200000000000000000000000000000000000000000000000000000000001c113300000000000000000000000000000000000000000000000000000000001c113400000000000000000000000000000000000000000000000000000000001c113500000000000000000000000000000000000000000000000000000000001c113600000000000000000000000000000000000000000000000000000000001c113700000000000000000000000000000000000000000000000000000000001c113800000000000000000000000000000000000000000000000000000000001c113900000000000000000000000000000000000000000000000000000000001c113a00000000000000000000000000000000000000000000000000000000001c113b00000000000000000000000000000000000000000000000000000000001c113c00000000000000000000000000000000000000000000000000000000001c113d00000000000000000000000000000000000000000000000000000000001c113e08006838aa99533bea0d4204cad17cb3c147e99c2f9089e54a4289d54733eeada2002ab314bd11ace2494a3fb0970d276da39f0fe7da19c9a2438b9c7c334d32470071703d79d8425a7eca52006df6a8f9728508a83639e3e1c2ebae2b853a087c00c9501ac04a78ac5413c9131b08708064ed2c2515b8893f12c2d1cda15a44f100a0955f93e109778d26f9e5b0d46e45c539e59b0941517bfa888eb2d7d2d8a6005adc3be9406cc5f102c6adb44746e8529a256e2396353a8659344cc3e914c4007a5fe572cf6af804f472dabf095c5eb6b30efc5fd627ad3245a8ef0f3f578c003dcaa91dfc9fdad7ba8da68a48fc662dfc0a995cbb0c1bc62099c8257d240d3f00000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c200a00000000000000000000000000000000000000000000000000000000001c200100000000000000000000000000000000000000000000000000000000001c200b00000000000000000000000000000000000000000000000000000000001c200200000000000000000000000000000000000000000000000000000000001c200c00000000000000000000000000000000000000000000000000000000001c200300000000000000000000000000000000000000000000000000000000001c200d00000000000000000000000000000000000000000000000000000000001c200400000000000000000000000000000000000000000000000000000000001c200e00000000000000000000000000000000000000000000000000000000001c200500000000000000000000000000000000000000000000000000000000001c200f00000000000000000000000000000000000000000000000000000000001c200600000000000000000000000000000000000000000000000000000000001c201000000000000000000000000000000000000000000000000000000000001c200700000000000000000000000000000000000000000000000000000000001c201100000000000000000000000000000000000000000000000000000000001c200800000000000000000000000000000000000000000000000000000000001c201200000000000000000000000000000000000000000000000000000000001c200900000000000000000000000000000000000000000000000000000000001c201300000000000000000000000000000000000000000000000000000000001c200a00000000000000000000000000000000000000000000000000000000001c201400000000000000000000000000000000000000000000000000000000001c200b00000000000000000000000000000000000000000000000000000000001c201500000000000000000000000000000000000000000000000000000000001c200c00000000000000000000000000000000000000000000000000000000001c201600000000000000000000000000000000000000000000000000000000001c200d00000000000000000000000000000000000000000000000000000000001c201700000000000000000000000000000000000000000000000000000000001c200e00000000000000000000000000000000000000000000000000000000001c201800000000000000000000000000000000000000000000000000000000001c200f00000000000000000000000000000000000000000000000000000000001c201900000000000000000000000000000000000000000000000000000000001c201000000000000000000000000000000000000000000000000000000000001c201a00000000000000000000000000000000000000000000000000000000001c201100000000000000000000000000000000000000000000000000000000001c201b00000000000000000000000000000000000000000000000000000000001c201200000000000000000000000000000000000000000000000000000000001c201c00000000000000000000000000000000000000000000000000000000001c201300000000000000000000000000000000000000000000000000000000001c201d00000000000000000000000000000000000000000000000000000000001c201400000000000000000000000000000000000000000000000000000000001c201e00000000000000000000000000000000000000000000000000000000001c201500000000000000000000000000000000000000000000000000000000001c201f00000000000000000000000000000000000000000000000000000000001c201600000000000000000000000000000000000000000000000000000000001c202000000000000000000000000000000000000000000000000000000000001c201700000000000000000000000000000000000000000000000000000000001c202100000000000000000000000000000000000000000000000000000000001c201800000000000000000000000000000000000000000000000000000000001c202200000000000000000000000000000000000000000000000000000000001c201900000000000000000000000000000000000000000000000000000000001c202300000000000000000000000000000000000000000000000000000000001c201a00000000000000000000000000000000000000000000000000000000001c202400000000000000000000000000000000000000000000000000000000001c201b00000000000000000000000000000000000000000000000000000000001c202500000000000000000000000000000000000000000000000000000000001c201c00000000000000000000000000000000000000000000000000000000001c202600000000000000000000000000000000000000000000000000000000001c201d00000000000000000000000000000000000000000000000000000000001c202700000000000000000000000000000000000000000000000000000000001c201e00000000000000000000000000000000000000000000000000000000001c202800000000000000000000000000000000000000000000000000000000001c201f00000000000000000000000000000000000000000000000000000000001c202900000000000000000000000000000000000000000000000000000000001c202000000000000000000000000000000000000000000000000000000000001c202a00000000000000000000000000000000000000000000000000000000001c202100000000000000000000000000000000000000000000000000000000001c202b00000000000000000000000000000000000000000000000000000000001c202200000000000000000000000000000000000000000000000000000000001c202c00000000000000000000000000000000000000000000000000000000001c202300000000000000000000000000000000000000000000000000000000001c202d00000000000000000000000000000000000000000000000000000000001c202400000000000000000000000000000000000000000000000000000000001c202e00000000000000000000000000000000000000000000000000000000001c202500000000000000000000000000000000000000000000000000000000001c202f00000000000000000000000000000000000000000000000000000000001c202600000000000000000000000000000000000000000000000000000000001c203000000000000000000000000000000000000000000000000000000000001c202700000000000000000000000000000000000000000000000000000000001c203100000000000000000000000000000000000000000000000000000000001c202800000000000000000000000000000000000000000000000000000000001c203200000000000000000000000000000000000000000000000000000000001c202900000000000000000000000000000000000000000000000000000000001c203300000000000000000000000000000000000000000000000000000000001c202a00000000000000000000000000000000000000000000000000000000001c203400000000000000000000000000000000000000000000000000000000001c202b00000000000000000000000000000000000000000000000000000000001c203500000000000000000000000000000000000000000000000000000000001c202c00000000000000000000000000000000000000000000000000000000001c203600000000000000000000000000000000000000000000000000000000001c202d00000000000000000000000000000000000000000000000000000000001c203700000000000000000000000000000000000000000000000000000000001c202e00000000000000000000000000000000000000000000000000000000001c203800000000000000000000000000000000000000000000000000000000001c202f00000000000000000000000000000000000000000000000000000000001c203900000000000000000000000000000000000000000000000000000000001c203000000000000000000000000000000000000000000000000000000000001c203a00000000000000000000000000000000000000000000000000000000001c203100000000000000000000000000000000000000000000000000000000001c203b00000000000000000000000000000000000000000000000000000000001c203200000000000000000000000000000000000000000000000000000000001c203c00000000000000000000000000000000000000000000000000000000001c203300000000000000000000000000000000000000000000000000000000001c203d00000000000000000000000000000000000000000000000000000000001c203400000000000000000000000000000000000000000000000000000000001c203e00000000000000000000000000000000000000000000000000000000001c203500000000000000000000000000000000000000000000000000000000001c203f00000000000000000000000000000000000000000000000000000000001c203600000000000000000000000000000000000000000000000000000000001c204000000000000000000000000000000000000000000000000000000000001c203700000000000000000000000000000000000000000000000000000000001c204100000000000000000000000000000000000000000000000000000000001c203800000000000000000000000000000000000000000000000000000000001c204200000000000000000000000000000000000000000000000000000000001c203900000000000000000000000000000000000000000000000000000000001c204300000000000000000000000000000000000000000000000000000000001c203a00000000000000000000000000000000000000000000000000000000001c204400000000000000000000000000000000000000000000000000000000001c203b00000000000000000000000000000000000000000000000000000000001c204500000000000000000000000000000000000000000000000000000000001c203c00000000000000000000000000000000000000000000000000000000001c204600000000000000000000000000000000000000000000000000000000001c203d00000000000000000000000000000000000000000000000000000000001c204700000000000000000000000000000000000000000000000000000000001c203e00000000000000000000000000000000000000000000000000000000001c2048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000201000000000000000000000000000000000000000000000000000000000000020100100000000000000000000000000000000000000000000000000000000002010020000000000000000000000000000000000000000000000000000000000201003000000000000000000000000000000000000000000000000000000000020100400000000000000000000000000000000000000000000000000000000002010050000000000000000000000000000000000000000000000000000000000201006000000000000000000000000000000000000000000000000000000000020100700000000000000000000000000000000000000000000000000000000002010080000000000000000000000000000000000000000000000000000000000201009000000000000000000000000000000000000000000000000000000000020100a000000000000000000000000000000000000000000000000000000000020100b000000000000000000000000000000000000000000000000000000000020100c000000000000000000000000000000000000000000000000000000000020100d000000000000000000000000000000000000000000000000000000000020100e000000000000000000000000000000000000000000000000000000000020100f0000000000000000000000000000000000000000000000000000000000201010000000000000000000000000000000000000000000000000000000000020101100000000000000000000000000000000000000000000000000000000002010120000000000000000000000000000000000000000000000000000000000201013000000000000000000000000000000000000000000000000000000000020101400000000000000000000000000000000000000000000000000000000002010150000000000000000000000000000000000000000000000000000000000201016000000000000000000000000000000000000000000000000000000000020101700000000000000000000000000000000000000000000000000000000002010180000000000000000000000000000000000000000000000000000000000201019000000000000000000000000000000000000000000000000000000000020101a000000000000000000000000000000000000000000000000000000000020101b000000000000000000000000000000000000000000000000000000000020101c000000000000000000000000000000000000000000000000000000000020101d000000000000000000000000000000000000000000000000000000000020101e000000000000000000000000000000000000000000000000000000000020101f0000000000000000000000000000000000000000000000000000000000201020000000000000000000000000000000000000000000000000000000000020102100000000000000000000000000000000000000000000000000000000002010220000000000000000000000000000000000000000000000000000000000201023000000000000000000000000000000000000000000000000000000000020102400000000000000000000000000000000000000000000000000000000002010250000000000000000000000000000000000000000000000000000000000201026000000000000000000000000000000000000000000000000000000000020102700000000000000000000000000000000000000000000000000000000002010280000000000000000000000000000000000000000000000000000000000201029000000000000000000000000000000000000000000000000000000000020102a000000000000000000000000000000000000000000000000000000000020102b000000000000000000000000000000000000000000000000000000000020102c000000000000000000000000000000000000000000000000000000000020102d000000000000000000000000000000000000000000000000000000000020102e000000000000000000000000000000000000000000000000000000000020102f0000000000000000000000000000000000000000000000000000000000201030000000000000000000000000000000000000000000000000000000000020103100000000000000000000000000000000000000000000000000000000002010320000000000000000000000000000000000000000000000000000000000201033000000000000000000000000000000000000000000000000000000000020103400000000000000000000000000000000000000000000000000000000002010350000000000000000000000000000000000000000000000000000000000201036000000000000000000000000000000000000000000000000000000000020103700000000000000000000000000000000000000000000000000000000002010380000000000000000000000000000000000000000000000000000000000201039000000000000000000000000000000000000000000000000000000000020103a000000000000000000000000000000000000000000000000000000000020103b000000000000000000000000000000000000000000000000000000000020103c000000000000000000000000000000000000000000000000000000000020103d000000000000000000000000000000000000000000000000000000000020103e000000000000000000000000000000000000000000000000000000000020103f3f0000000000000000000000000000000000000000000000000000000000201100000000000000000000000000000000000000000000000000000000000020110100000000000000000000000000000000000000000000000000000000002011020000000000000000000000000000000000000000000000000000000000201103000000000000000000000000000000000000000000000000000000000020110400000000000000000000000000000000000000000000000000000000002011050000000000000000000000000000000000000000000000000000000000201106000000000000000000000000000000000000000000000000000000000020110700000000000000000000000000000000000000000000000000000000002011080000000000000000000000000000000000000000000000000000000000201109000000000000000000000000000000000000000000000000000000000020110a000000000000000000000000000000000000000000000000000000000020110b000000000000000000000000000000000000000000000000000000000020110c000000000000000000000000000000000000000000000000000000000020110d000000000000000000000000000000000000000000000000000000000020110e000000000000000000000000000000000000000000000000000000000020110f0000000000000000000000000000000000000000000000000000000000201110000000000000000000000000000000000000000000000000000000000020111100000000000000000000000000000000000000000000000000000000002011120000000000000000000000000000000000000000000000000000000000201113000000000000000000000000000000000000000000000000000000000020111400000000000000000000000000000000000000000000000000000000002011150000000000000000000000000000000000000000000000000000000000201116000000000000000000000000000000000000000000000000000000000020111700000000000000000000000000000000000000000000000000000000002011180000000000000000000000000000000000000000000000000000000000201119000000000000000000000000000000000000000000000000000000000020111a000000000000000000000000000000000000000000000000000000000020111b000000000000000000000000000000000000000000000000000000000020111c000000000000000000000000000000000000000000000000000000000020111d000000000000000000000000000000000000000000000000000000000020111e000000000000000000000000000000000000000000000000000000000020111f0000000000000000000000000000000000000000000000000000000000201120000000000000000000000000000000000000000000000000000000000020112100000000000000000000000000000000000000000000000000000000002011220000000000000000000000000000000000000000000000000000000000201123000000000000000000000000000000000000000000000000000000000020112400000000000000000000000000000000000000000000000000000000002011250000000000000000000000000000000000000000000000000000000000201126000000000000000000000000000000000000000000000000000000000020112700000000000000000000000000000000000000000000000000000000002011280000000000000000000000000000000000000000000000000000000000201129000000000000000000000000000000000000000000000000000000000020112a000000000000000000000000000000000000000000000000000000000020112b000000000000000000000000000000000000000000000000000000000020112c000000000000000000000000000000000000000000000000000000000020112d000000000000000000000000000000000000000000000000000000000020112e000000000000000000000000000000000000000000000000000000000020112f0000000000000000000000000000000000000000000000000000000000201130000000000000000000000000000000000000000000000000000000000020113100000000000000000000000000000000000000000000000000000000002011320000000000000000000000000000000000000000000000000000000000201133000000000000000000000000000000000000000000000000000000000020113400000000000000000000000000000000000000000000000000000000002011350000000000000000000000000000000000000000000000000000000000201136000000000000000000000000000000000000000000000000000000000020113700000000000000000000000000000000000000000000000000000000002011380000000000000000000000000000000000000000000000000000000000201139000000000000000000000000000000000000000000000000000000000020113a000000000000000000000000000000000000000000000000000000000020113b000000000000000000000000000000000000000000000000000000000020113c000000000000000000000000000000000000000000000000000000000020113d000000000000000000000000000000000000000000000000000000000020113e0800e9805e8a4faa87fc419af08a6d956f18976c46ea694bbd4cf6946e6d02033200e0925a6b172b4b01bb76eb1d3f7dd2ced118bca70d223a6d61afa1b75915ae00383590492d2f99a0283d1de57015b4b6b0759a8023af2c68fb4929dee2f303007ed57100dd77e2b6405f780503ef61b7b53e13f344b6e6a6eff3e3c13de0d0001ab1b0c348c46184dbc86ff79f248e7da1b09d3f9c6a986e98fe45389f060d0023d134bc68d7efa25e255001069827dc0bee766c08c988d6300071ed27fe6c0031cbb780b07f632cbaf767dc80608cc0a8e1d1df3ecd6f5d8bc0ca6703e4f4002c7dc9e731fc5f6456b2a70b4e636ac17d5e0cd36d3a591116a9e124f735863f0000000000000000000000000000000000000000000000000000000000202000000000000000000000000000000000000000000000000000000000000020200a0000000000000000000000000000000000000000000000000000000000202001000000000000000000000000000000000000000000000000000000000020200b0000000000000000000000000000000000000000000000000000000000202002000000000000000000000000000000000000000000000000000000000020200c0000000000000000000000000000000000000000000000000000000000202003000000000000000000000000000000000000000000000000000000000020200d0000000000000000000000000000000000000000000000000000000000202004000000000000000000000000000000000000000000000000000000000020200e0000000000000000000000000000000000000000000000000000000000202005000000000000000000000000000000000000000000000000000000000020200f00000000000000000000000000000000000000000000000000000000002020060000000000000000000000000000000000000000000000000000000000202010000000000000000000000000000000000000000000000000000000000020200700000000000000000000000000000000000000000000000000000000002020110000000000000000000000000000000000000000000000000000000000202008000000000000000000000000000000000000000000000000000000000020201200000000000000000000000000000000000000000000000000000000002020090000000000000000000000000000000000000000000000000000000000202013000000000000000000000000000000000000000000000000000000000020200a0000000000000000000000000000000000000000000000000000000000202014000000000000000000000000000000000000000000000000000000000020200b0000000000000000000000000000000000000000000000000000000000202015000000000000000000000000000000000000000000000000000000000020200c0000000000000000000000000000000000000000000000000000000000202016000000000000000000000000000000000000000000000000000000000020200d0000000000000000000000000000000000000000000000000000000000202017000000000000000000000000000000000000000000000000000000000020200e0000000000000000000000000000000000000000000000000000000000202018000000000000000000000000000000000000000000000000000000000020200f00000000000000000000000000000000000000000000000000000000002020190000000000000000000000000000000000000000000000000000000000202010000000000000000000000000000000000000000000000000000000000020201a0000000000000000000000000000000000000000000000000000000000202011000000000000000000000000000000000000000000000000000000000020201b0000000000000000000000000000000000000000000000000000000000202012000000000000000000000000000000000000000000000000000000000020201c0000000000000000000000000000000000000000000000000000000000202013000000000000000000000000000000000000000000000000000000000020201d0000000000000000000000000000000000000000000000000000000000202014000000000000000000000000000000000000000000000000000000000020201e0000000000000000000000000000000000000000000000000000000000202015000000000000000000000000000000000000000000000000000000000020201f00000000000000000000000000000000000000000000000000000000002020160000000000000000000000000000000000000000000000000000000000202020000000000000000000000000000000000000000000000000000000000020201700000000000000000000000000000000000000000000000000000000002020210000000000000000000000000000000000000000000000000000000000202018000000000000000000000000000000000000000000000000000000000020202200000000000000000000000000000000000000000000000000000000002020190000000000000000000000000000000000000000000000000000000000202023000000000000000000000000000000000000000000000000000000000020201a0000000000000000000000000000000000000000000000000000000000202024000000000000000000000000000000000000000000000000000000000020201b0000000000000000000000000000000000000000000000000000000000202025000000000000000000000000000000000000000000000000000000000020201c0000000000000000000000000000000000000000000000000000000000202026000000000000000000000000000000000000000000000000000000000020201d0000000000000000000000000000000000000000000000000000000000202027000000000000000000000000000000000000000000000000000000000020201e0000000000000000000000000000000000000000000000000000000000202028000000000000000000000000000000000000000000000000000000000020201f00000000000000000000000000000000000000000000000000000000002020290000000000000000000000000000000000000000000000000000000000202020000000000000000000000000000000000000000000000000000000000020202a0000000000000000000000000000000000000000000000000000000000202021000000000000000000000000000000000000000000000000000000000020202b0000000000000000000000000000000000000000000000000000000000202022000000000000000000000000000000000000000000000000000000000020202c0000000000000000000000000000000000000000000000000000000000202023000000000000000000000000000000000000000000000000000000000020202d0000000000000000000000000000000000000000000000000000000000202024000000000000000000000000000000000000000000000000000000000020202e0000000000000000000000000000000000000000000000000000000000202025000000000000000000000000000000000000000000000000000000000020202f00000000000000000000000000000000000000000000000000000000002020260000000000000000000000000000000000000000000000000000000000202030000000000000000000000000000000000000000000000000000000000020202700000000000000000000000000000000000000000000000000000000002020310000000000000000000000000000000000000000000000000000000000202028000000000000000000000000000000000000000000000000000000000020203200000000000000000000000000000000000000000000000000000000002020290000000000000000000000000000000000000000000000000000000000202033000000000000000000000000000000000000000000000000000000000020202a0000000000000000000000000000000000000000000000000000000000202034000000000000000000000000000000000000000000000000000000000020202b0000000000000000000000000000000000000000000000000000000000202035000000000000000000000000000000000000000000000000000000000020202c0000000000000000000000000000000000000000000000000000000000202036000000000000000000000000000000000000000000000000000000000020202d0000000000000000000000000000000000000000000000000000000000202037000000000000000000000000000000000000000000000000000000000020202e0000000000000000000000000000000000000000000000000000000000202038000000000000000000000000000000000000000000000000000000000020202f00000000000000000000000000000000000000000000000000000000002020390000000000000000000000000000000000000000000000000000000000202030000000000000000000000000000000000000000000000000000000000020203a0000000000000000000000000000000000000000000000000000000000202031000000000000000000000000000000000000000000000000000000000020203b0000000000000000000000000000000000000000000000000000000000202032000000000000000000000000000000000000000000000000000000000020203c0000000000000000000000000000000000000000000000000000000000202033000000000000000000000000000000000000000000000000000000000020203d0000000000000000000000000000000000000000000000000000000000202034000000000000000000000000000000000000000000000000000000000020203e0000000000000000000000000000000000000000000000000000000000202035000000000000000000000000000000000000000000000000000000000020203f00000000000000000000000000000000000000000000000000000000002020360000000000000000000000000000000000000000000000000000000000202040000000000000000000000000000000000000000000000000000000000020203700000000000000000000000000000000000000000000000000000000002020410000000000000000000000000000000000000000000000000000000000202038000000000000000000000000000000000000000000000000000000000020204200000000000000000000000000000000000000000000000000000000002020390000000000000000000000000000000000000000000000000000000000202043000000000000000000000000000000000000000000000000000000000020203a0000000000000000000000000000000000000000000000000000000000202044000000000000000000000000000000000000000000000000000000000020203b0000000000000000000000000000000000000000000000000000000000202045000000000000000000000000000000000000000000000000000000000020203c0000000000000000000000000000000000000000000000000000000000202046000000000000000000000000000000000000000000000000000000000020203d0000000000000000000000000000000000000000000000000000000000202047000000000000000000000000000000000000000000000000000000000020203e0000000000000000000000000000000000000000000000000000000000202048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "txsEffectsHash": "0x00d2d12b4d0c6202124a7625c585097078920e09dd2c650401a91b564234a6b4", "decodedHeader": { "contentCommitment": { "inHash": "0x00e1371045bd7d2c3e1f19cba5f536f0e82042ba4bc257d4ba19c146215e8242", "outHash": "0x009514581058b2b6aae79574cc9129a801904407c6d869a5f168b02cebffecfe", "numTxs": 8, - "txsEffectsHash": "0x006355bc5a5a6353eca00eac5e4aede081b359a25bcf81604aacd84dd1947561" + "txsEffectsHash": "0x00d2d12b4d0c6202124a7625c585097078920e09dd2c650401a91b564234a6b4" }, "globalVariables": { "blockNumber": 2, "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000023", "chainId": 31337, - "timestamp": 1731106635, + "timestamp": 1731434221, "version": 1, - "coinbase": "0xe1b76c7e0eb80841fed024c0470d663250bdd96e", - "feeRecipient": "0x1f1730e56d57b24d909d5eae3094c83900c3fb2fa90e248dfddb825f2e4e55e8", + "coinbase": "0xa8f1a4313bc15dcd3681ed2b6fdd042f1ee1f823", + "feeRecipient": "0x2abdc96d2ec8465dfd2bb7401f90dd3af0db16c3cece57bd5de2b63a3d25140b", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -116,7 +116,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x0f5694321be22526e5a7e857ed9fc4afc006c5bc9052bea6449ec3adee9a2ba9" + "root": "0x13232b1c92fcfba5f94aee813d7e454764f93d6292215552b8c973ef42c8e396" }, "stateReference": { "l1ToL2MessageTree": { @@ -139,8 +139,8 @@ } } }, - "header": "0x0f5694321be22526e5a7e857ed9fc4afc006c5bc9052bea6449ec3adee9a2ba9000000020000000000000000000000000000000000000000000000000000000000000008006355bc5a5a6353eca00eac5e4aede081b359a25bcf81604aacd84dd194756100e1371045bd7d2c3e1f19cba5f536f0e82042ba4bc257d4ba19c146215e8242009514581058b2b6aae79574cc9129a801904407c6d869a5f168b02cebffecfe026efb6c2a517de2448119d0f1255757265dbec7cdd2952df929ede666e10944000000202494d2575971bca59a28ddc774d19136f4a294951ab67258c7e9c2d8f9805924000002002ed5c359f01d6a1cacfa324bc48b7fcc6fe75a95ad66bdb1a6e32d69075509570000028023a39db7c42fa47a6df2b9deea545155c39f6066cbbc2701a12c60af95b6cdf9000002800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000672e974be1b76c7e0eb80841fed024c0470d663250bdd96e1f1730e56d57b24d909d5eae3094c83900c3fb2fa90e248dfddb825f2e4e55e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00ea263f29ec2e0b891daece07ec0eff5ebfcf733ce126a50fc364b81c67f5ad", + "header": "0x13232b1c92fcfba5f94aee813d7e454764f93d6292215552b8c973ef42c8e39600000002000000000000000000000000000000000000000000000000000000000000000800d2d12b4d0c6202124a7625c585097078920e09dd2c650401a91b564234a6b400e1371045bd7d2c3e1f19cba5f536f0e82042ba4bc257d4ba19c146215e8242009514581058b2b6aae79574cc9129a801904407c6d869a5f168b02cebffecfe026efb6c2a517de2448119d0f1255757265dbec7cdd2952df929ede666e10944000000202494d2575971bca59a28ddc774d19136f4a294951ab67258c7e9c2d8f9805924000002002ed5c359f01d6a1cacfa324bc48b7fcc6fe75a95ad66bdb1a6e32d69075509570000028023a39db7c42fa47a6df2b9deea545155c39f6066cbbc2701a12c60af95b6cdf9000002800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000673396eda8f1a4313bc15dcd3681ed2b6fdd042f1ee1f8232abdc96d2ec8465dfd2bb7401f90dd3af0db16c3cece57bd5de2b63a3d25140b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x0010b7371af5e28ae8d1d0385e2ad3e28322dc403bfab0a6196947e5bb95143b", "numTxs": 8 } } \ No newline at end of file diff --git a/l1-contracts/test/portals/TokenPortal.sol b/l1-contracts/test/portals/TokenPortal.sol index 674b007ce95..115132e5234 100644 --- a/l1-contracts/test/portals/TokenPortal.sol +++ b/l1-contracts/test/portals/TokenPortal.sol @@ -22,11 +22,7 @@ contract TokenPortal { ); event DepositToAztecPrivate( - bytes32 secretHashForRedeemingMintedNotes, - uint256 amount, - bytes32 secretHashForL2MessageConsumption, - bytes32 key, - uint256 index + uint256 amount, bytes32 secretHashForL2MessageConsumption, bytes32 key, uint256 index ); IRegistry public registry; @@ -57,8 +53,10 @@ contract TokenPortal { DataStructures.L2Actor memory actor = DataStructures.L2Actor(l2Bridge, 1); // Hash the message content to be reconstructed in the receiving contract + // The purpose of including the function selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. bytes32 contentHash = - Hash.sha256ToField(abi.encodeWithSignature("mint_public(bytes32,uint256)", _to, _amount)); + Hash.sha256ToField(abi.encodeWithSignature("mint_to_public(bytes32,uint256)", _to, _amount)); // Hold the tokens in the portal underlying.safeTransferFrom(msg.sender, address(this), _amount); @@ -76,26 +74,22 @@ contract TokenPortal { // docs:start:deposit_private /** * @notice Deposit funds into the portal and adds an L2 message which can only be consumed privately on Aztec - * @param _secretHashForRedeemingMintedNotes - The hash of the secret to redeem minted notes privately on Aztec. The hash should be 254 bits (so it can fit in a Field element) * @param _amount - The amount to deposit * @param _secretHashForL2MessageConsumption - The hash of the secret consumable L1 to L2 message. The hash should be 254 bits (so it can fit in a Field element) * @return The key of the entry in the Inbox and its leaf index */ - function depositToAztecPrivate( - bytes32 _secretHashForRedeemingMintedNotes, - uint256 _amount, - bytes32 _secretHashForL2MessageConsumption - ) external returns (bytes32, uint256) { + function depositToAztecPrivate(uint256 _amount, bytes32 _secretHashForL2MessageConsumption) + external + returns (bytes32, uint256) + { // Preamble IInbox inbox = IRollup(registry.getRollup()).INBOX(); DataStructures.L2Actor memory actor = DataStructures.L2Actor(l2Bridge, 1); - // Hash the message content to be reconstructed in the receiving contract - bytes32 contentHash = Hash.sha256ToField( - abi.encodeWithSignature( - "mint_private(bytes32,uint256)", _secretHashForRedeemingMintedNotes, _amount - ) - ); + // Hash the message content to be reconstructed in the receiving contract - the signature below does not correspond + // to a real function. It's just an identifier of an action. + bytes32 contentHash = + Hash.sha256ToField(abi.encodeWithSignature("mint_to_private(uint256)", _amount)); // Hold the tokens in the portal underlying.safeTransferFrom(msg.sender, address(this), _amount); @@ -105,9 +99,7 @@ contract TokenPortal { inbox.sendL2Message(actor, contentHash, _secretHashForL2MessageConsumption); // Emit event - emit DepositToAztecPrivate( - _secretHashForRedeemingMintedNotes, _amount, _secretHashForL2MessageConsumption, key, index - ); + emit DepositToAztecPrivate(_amount, _secretHashForL2MessageConsumption, key, index); return (key, index); } @@ -133,6 +125,8 @@ contract TokenPortal { uint256 _leafIndex, bytes32[] calldata _path ) external { + // The purpose of including the function selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. DataStructures.L2ToL1Msg memory message = DataStructures.L2ToL1Msg({ sender: DataStructures.L2Actor(l2Bridge, 1), recipient: DataStructures.L1Actor(address(this), block.chainid), diff --git a/l1-contracts/test/portals/TokenPortal.t.sol b/l1-contracts/test/portals/TokenPortal.t.sol index 105de7afe29..da7af0eb534 100644 --- a/l1-contracts/test/portals/TokenPortal.t.sol +++ b/l1-contracts/test/portals/TokenPortal.t.sol @@ -49,9 +49,6 @@ contract TokenPortalTest is Test { // this hash is just a random 32 byte string bytes32 internal secretHashForL2MessageConsumption = 0x147e4fec49805c924e28150fc4b36824679bc17ecb1d7d9f6a9effb7fde6b6a0; - // this hash is just a random 32 byte string - bytes32 internal secretHashForRedeemingMintedNotes = - 0x157e4fec49805c924e28150fc4b36824679bc17ecb1d7d9f6a9effb7fde6b6a0; // params for withdraw: address internal recipient = address(0xdead); @@ -91,14 +88,12 @@ contract TokenPortalTest is Test { view returns (DataStructures.L1ToL2Msg memory) { + // The purpose of including the function selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. return DataStructures.L1ToL2Msg({ sender: DataStructures.L1Actor(address(tokenPortal), block.chainid), recipient: DataStructures.L2Actor(l2TokenAddress, 1), - content: Hash.sha256ToField( - abi.encodeWithSignature( - "mint_private(bytes32,uint256)", secretHashForRedeemingMintedNotes, amount - ) - ), + content: Hash.sha256ToField(abi.encodeWithSignature("mint_to_private(uint256)", amount)), secretHash: secretHashForL2MessageConsumption, index: _index }); @@ -109,10 +104,14 @@ contract TokenPortalTest is Test { view returns (DataStructures.L1ToL2Msg memory) { + // The purpose of including the function selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. return DataStructures.L1ToL2Msg({ sender: DataStructures.L1Actor(address(tokenPortal), block.chainid), recipient: DataStructures.L2Actor(l2TokenAddress, 1), - content: Hash.sha256ToField(abi.encodeWithSignature("mint_public(bytes32,uint256)", to, amount)), + content: Hash.sha256ToField( + abi.encodeWithSignature("mint_to_public(bytes32,uint256)", to, amount) + ), secretHash: secretHashForL2MessageConsumption, index: _index }); @@ -137,9 +136,8 @@ contract TokenPortalTest is Test { // event we will get // Perform op - (bytes32 leaf, uint256 index) = tokenPortal.depositToAztecPrivate( - secretHashForRedeemingMintedNotes, amount, secretHashForL2MessageConsumption - ); + (bytes32 leaf, uint256 index) = + tokenPortal.depositToAztecPrivate(amount, secretHashForL2MessageConsumption); assertEq(leaf, expectedLeaf, "returned leaf and calculated leaf should match"); assertEq(index, expectedIndex, "returned index and calculated index should match"); @@ -177,6 +175,8 @@ contract TokenPortalTest is Test { internal returns (bytes32, bytes32) { + // The purpose of including the function selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. bytes32 l2ToL1Message = Hash.sha256ToField( DataStructures.L2ToL1Msg({ sender: DataStructures.L2Actor({actor: l2TokenAddress, version: 1}), diff --git a/l1-contracts/test/portals/UniswapPortal.sol b/l1-contracts/test/portals/UniswapPortal.sol index fc6bebd74a4..37e02ee69bb 100644 --- a/l1-contracts/test/portals/UniswapPortal.sol +++ b/l1-contracts/test/portals/UniswapPortal.sol @@ -87,6 +87,8 @@ contract UniswapPortal { { // prevent stack too deep errors + // The purpose of including the function selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. vars.contentHash = Hash.sha256ToField( abi.encodeWithSignature( "swap_public(address,uint256,uint24,address,uint256,bytes32,bytes32,address)", @@ -158,7 +160,6 @@ contract UniswapPortal { * @param _uniswapFeeTier - The fee tier for the swap on UniswapV3 * @param _outputTokenPortal - The ethereum address of the output token portal * @param _amountOutMinimum - The minimum amount of output assets to receive from the swap (slippage protection) - * @param _secretHashForRedeemingMintedNotes - The hash of the secret to redeem minted notes privately on Aztec. The hash should be 254 bits (so it can fit in a Field element) * @param _secretHashForL1ToL2Message - The hash of the secret consumable message. The hash should be 254 bits (so it can fit in a Field element) * @param _withCaller - When true, using `msg.sender` as the caller, otherwise address(0) * @return A hash of the L1 to L2 message inserted in the Inbox @@ -169,7 +170,6 @@ contract UniswapPortal { uint24 _uniswapFeeTier, address _outputTokenPortal, uint256 _amountOutMinimum, - bytes32 _secretHashForRedeemingMintedNotes, bytes32 _secretHashForL1ToL2Message, bool _withCaller, // Avoiding stack too deep @@ -193,15 +193,16 @@ contract UniswapPortal { { // prevent stack too deep errors + // The purpose of including the function selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. vars.contentHash = Hash.sha256ToField( abi.encodeWithSignature( - "swap_private(address,uint256,uint24,address,uint256,bytes32,bytes32,address)", + "swap_private(address,uint256,uint24,address,uint256,bytes32,address)", _inputTokenPortal, _inAmount, _uniswapFeeTier, _outputTokenPortal, _amountOutMinimum, - _secretHashForRedeemingMintedNotes, _secretHashForL1ToL2Message, _withCaller ? msg.sender : address(0) ) @@ -247,9 +248,8 @@ contract UniswapPortal { vars.outputAsset.approve(address(_outputTokenPortal), amountOut); // Deposit the output asset to the L2 via its portal - return TokenPortal(_outputTokenPortal).depositToAztecPrivate( - _secretHashForRedeemingMintedNotes, amountOut, _secretHashForL1ToL2Message - ); + return + TokenPortal(_outputTokenPortal).depositToAztecPrivate(amountOut, _secretHashForL1ToL2Message); } } // docs:end:solidity_uniswap_swap_private diff --git a/l1-contracts/test/portals/UniswapPortal.t.sol b/l1-contracts/test/portals/UniswapPortal.t.sol index 84afe101e34..ac646e17bac 100644 --- a/l1-contracts/test/portals/UniswapPortal.t.sol +++ b/l1-contracts/test/portals/UniswapPortal.t.sol @@ -44,7 +44,6 @@ contract UniswapPortalTest is Test { uint24 internal uniswapFeePool = 3000; // 0.3% fee uint256 internal amountOutMinimum = 0; bytes32 internal aztecRecipient = bytes32(uint256(0x3)); - bytes32 internal secretHashForRedeemingMintedNotes = bytes32(uint256(0x4)); uint256 internal l2BlockNumber = 69; @@ -95,6 +94,8 @@ contract UniswapPortalTest is Test { view returns (bytes32 l2ToL1MessageHash) { + // The purpose of including the function selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. DataStructures.L2ToL1Msg memory message = DataStructures.L2ToL1Msg({ sender: DataStructures.L2Actor(l2TokenAddress, 1), recipient: DataStructures.L1Actor(address(daiTokenPortal), block.chainid), @@ -117,6 +118,8 @@ contract UniswapPortalTest is Test { view returns (bytes32 l2ToL1MessageHash) { + // The purpose of including the function selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. DataStructures.L2ToL1Msg memory message = DataStructures.L2ToL1Msg({ sender: DataStructures.L2Actor(l2UniswapAddress, 1), recipient: DataStructures.L1Actor(address(uniswapPortal), block.chainid), @@ -140,26 +143,23 @@ contract UniswapPortalTest is Test { /** * L2 to L1 message to be added to the outbox - - * @param _secretHashForRedeemingMintedNotes - The hash of the secret to redeem minted notes privately on Aztec * @param _caller - designated caller on L1 that will call the swap function - typically address(this) * Set to address(0) if anyone can call. */ - function _createUniswapSwapMessagePrivate( - bytes32 _secretHashForRedeemingMintedNotes, - address _caller - ) internal view returns (bytes32) { + function _createUniswapSwapMessagePrivate(address _caller) internal view returns (bytes32) { + // The purpose of including the function selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. DataStructures.L2ToL1Msg memory message = DataStructures.L2ToL1Msg({ sender: DataStructures.L2Actor(l2UniswapAddress, 1), recipient: DataStructures.L1Actor(address(uniswapPortal), block.chainid), content: Hash.sha256ToField( abi.encodeWithSignature( - "swap_private(address,uint256,uint24,address,uint256,bytes32,bytes32,address)", + "swap_private(address,uint256,uint24,address,uint256,bytes32,address)", address(daiTokenPortal), amount, uniswapFeePool, address(wethTokenPortal), amountOutMinimum, - _secretHashForRedeemingMintedNotes, secretHash, _caller ) @@ -572,8 +572,7 @@ contract UniswapPortalTest is Test { }) ]; - bytes32 messageHashPortalChecksAgainst = - _createUniswapSwapMessagePrivate(secretHashForRedeemingMintedNotes, address(this)); + bytes32 messageHashPortalChecksAgainst = _createUniswapSwapMessagePrivate(address(this)); bytes32 actualRoot; bytes32 consumedRoot; @@ -607,7 +606,6 @@ contract UniswapPortalTest is Test { uniswapFeePool, address(wethTokenPortal), amountOutMinimum, - secretHashForRedeemingMintedNotes, secretHash, true, outboxMessageMetadata diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index cc0d0428070..504278a7cb3 100644 --- a/noir-projects/aztec-nr/.gitrepo +++ b/noir-projects/aztec-nr/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/aztec-nr branch = master - commit = 530fb20e9d3e4bb2d946d18555d6b80f8149ae98 + commit = 8d7530b1cd40074c2820832f122f3ad605d57e16 method = merge cmdver = 0.4.6 - parent = cdb915ca7fcac4c5f8f019cc22d9f3b93b8086a5 + parent = 67f86c1feccdbbfd550147c4e1699bf120d848a2 diff --git a/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr b/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr index 0c730e54c57..2733c736842 100644 --- a/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr +++ b/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr @@ -50,7 +50,7 @@ impl AppPayload { } bytes.extend_from_array(self.nonce.to_be_bytes::<32>()); - bytes.storage + bytes.storage() } // Executes all private and public calls diff --git a/noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr b/noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr index d47df09572b..9647cf05067 100644 --- a/noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr +++ b/noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr @@ -51,7 +51,7 @@ impl FeePayload { bytes.extend_from_array(self.nonce.to_be_bytes::<32>()); bytes.push(self.is_fee_payer as u8); - bytes.storage + bytes.storage() } fn execute_calls(self, context: &mut PrivateContext) { diff --git a/noir-projects/aztec-nr/authwit/src/entrypoint/function_call.nr b/noir-projects/aztec-nr/authwit/src/entrypoint/function_call.nr index d146c8a488e..cd5a5730fb9 100644 --- a/noir-projects/aztec-nr/authwit/src/entrypoint/function_call.nr +++ b/noir-projects/aztec-nr/authwit/src/entrypoint/function_call.nr @@ -8,11 +8,11 @@ global FUNCTION_CALL_SIZE: u32 = 5; global FUNCTION_CALL_SIZE_IN_BYTES: u32 = 98; pub struct FunctionCall { - args_hash: Field, - function_selector: FunctionSelector, - target_address: AztecAddress, - is_public: bool, - is_static: bool, + pub args_hash: Field, + pub function_selector: FunctionSelector, + pub target_address: AztecAddress, + pub is_public: bool, + pub is_static: bool, } impl Serialize for FunctionCall { diff --git a/noir-projects/aztec-nr/authwit/src/lib.nr b/noir-projects/aztec-nr/authwit/src/lib.nr index c4d792a4a26..209aaf14606 100644 --- a/noir-projects/aztec-nr/authwit/src/lib.nr +++ b/noir-projects/aztec-nr/authwit/src/lib.nr @@ -1,5 +1,5 @@ -mod account; -mod auth_witness; -mod auth; -mod entrypoint; -mod cheatcodes; +pub mod account; +pub mod auth_witness; +pub mod auth; +pub mod entrypoint; +pub mod cheatcodes; diff --git a/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr b/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr index 7a98c56089c..4fdbdfce273 100644 --- a/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr +++ b/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr @@ -30,13 +30,13 @@ pub trait CallInterface { } pub struct PrivateCallInterface { - target_contract: AztecAddress, - selector: FunctionSelector, - name: str, - args_hash: Field, - args: [Field], - return_type: T, - is_static: bool, + pub target_contract: AztecAddress, + pub selector: FunctionSelector, + pub name: str, + pub args_hash: Field, + pub args: [Field], + pub return_type: T, + pub is_static: bool, } impl PrivateCallInterface { @@ -73,13 +73,13 @@ impl PrivateCallInterface { impl CallInterface for PrivateVoidCallInterface {} pub struct PrivateVoidCallInterface { - target_contract: AztecAddress, - selector: FunctionSelector, - name: str, - args_hash: Field, - args: [Field], - return_type: (), - is_static: bool, + pub target_contract: AztecAddress, + pub selector: FunctionSelector, + pub name: str, + pub args_hash: Field, + pub args: [Field], + pub return_type: (), + pub is_static: bool, } impl PrivateVoidCallInterface { @@ -111,13 +111,13 @@ impl PrivateVoidCallInterface { impl CallInterface for PrivateStaticCallInterface {} pub struct PrivateStaticCallInterface { - target_contract: AztecAddress, - selector: FunctionSelector, - name: str, - args_hash: Field, - args: [Field], - return_type: T, - is_static: bool, + pub target_contract: AztecAddress, + pub selector: FunctionSelector, + pub name: str, + pub args_hash: Field, + pub args: [Field], + pub return_type: T, + pub is_static: bool, } impl PrivateStaticCallInterface { @@ -139,13 +139,13 @@ impl PrivateStaticCallInterface { impl CallInterface for PrivateStaticVoidCallInterface {} pub struct PrivateStaticVoidCallInterface { - target_contract: AztecAddress, - selector: FunctionSelector, - name: str, - args_hash: Field, - args: [Field], - return_type: (), - is_static: bool, + pub target_contract: AztecAddress, + pub selector: FunctionSelector, + pub name: str, + pub args_hash: Field, + pub args: [Field], + pub return_type: (), + pub is_static: bool, } impl PrivateStaticVoidCallInterface { @@ -165,13 +165,13 @@ impl PrivateStaticVoidCallInterface { impl CallInterface for PublicCallInterface {} pub struct PublicCallInterface { - target_contract: AztecAddress, - selector: FunctionSelector, - name: str, - args: [Field], - gas_opts: GasOpts, - return_type: T, - is_static: bool, + pub target_contract: AztecAddress, + pub selector: FunctionSelector, + pub name: str, + pub args: [Field], + pub gas_opts: GasOpts, + pub return_type: T, + pub is_static: bool, } impl PublicCallInterface { @@ -234,13 +234,13 @@ impl PublicCallInterface { impl CallInterface for PublicVoidCallInterface {} pub struct PublicVoidCallInterface { - target_contract: AztecAddress, - selector: FunctionSelector, - name: str, - args: [Field], - return_type: (), - is_static: bool, - gas_opts: GasOpts, + pub target_contract: AztecAddress, + pub selector: FunctionSelector, + pub name: str, + pub args: [Field], + pub return_type: (), + pub is_static: bool, + pub gas_opts: GasOpts, } impl PublicVoidCallInterface { @@ -297,13 +297,13 @@ impl PublicVoidCallInterface { impl CallInterface for PublicStaticCallInterface {} pub struct PublicStaticCallInterface { - target_contract: AztecAddress, - selector: FunctionSelector, - name: str, - args: [Field], - return_type: T, - is_static: bool, - gas_opts: GasOpts, + pub target_contract: AztecAddress, + pub selector: FunctionSelector, + pub name: str, + pub args: [Field], + pub return_type: T, + pub is_static: bool, + pub gas_opts: GasOpts, } impl PublicStaticCallInterface { diff --git a/noir-projects/aztec-nr/aztec/src/context/gas.nr b/noir-projects/aztec-nr/aztec/src/context/gas.nr index 7080cac8f91..0200e90ce68 100644 --- a/noir-projects/aztec-nr/aztec/src/context/gas.nr +++ b/noir-projects/aztec-nr/aztec/src/context/gas.nr @@ -1,6 +1,6 @@ pub struct GasOpts { - l2_gas: Option, - da_gas: Option, + pub l2_gas: Option, + pub da_gas: Option, } impl GasOpts { diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index de5420b8600..ba902167bf4 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -33,12 +33,11 @@ use dep::protocol_types::{ }, address::{AztecAddress, EthAddress}, constants::{ - MAX_ENCRYPTED_LOGS_PER_CALL, MAX_ENQUEUED_CALLS_PER_CALL, + MAX_CONTRACT_CLASS_LOGS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_ENQUEUED_CALLS_PER_CALL, MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL, - MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, - PUBLIC_DISPATCH_SELECTOR, + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, PUBLIC_DISPATCH_SELECTOR, }, header::Header, messaging::l2_to_l1_message::L2ToL1Message, @@ -48,41 +47,41 @@ use dep::protocol_types::{ // When finished, one can call .finish() to convert back to the abi pub struct PrivateContext { // docs:start:private-context - inputs: PrivateContextInputs, - side_effect_counter: u32, + pub inputs: PrivateContextInputs, + pub side_effect_counter: u32, - min_revertible_side_effect_counter: u32, - is_fee_payer: bool, + pub min_revertible_side_effect_counter: u32, + pub is_fee_payer: bool, - args_hash: Field, - return_hash: Field, + pub args_hash: Field, + pub return_hash: Field, - max_block_number: MaxBlockNumber, + pub max_block_number: MaxBlockNumber, - note_hash_read_requests: BoundedVec, - nullifier_read_requests: BoundedVec, + pub note_hash_read_requests: BoundedVec, + pub nullifier_read_requests: BoundedVec, key_validation_requests_and_generators: BoundedVec, - note_hashes: BoundedVec, - nullifiers: BoundedVec, + pub note_hashes: BoundedVec, + pub nullifiers: BoundedVec, - private_call_requests: BoundedVec, - public_call_requests: BoundedVec, MAX_ENQUEUED_CALLS_PER_CALL>, - public_teardown_call_request: PublicCallRequest, - l2_to_l1_msgs: BoundedVec, + pub private_call_requests: BoundedVec, + pub public_call_requests: BoundedVec, MAX_ENQUEUED_CALLS_PER_CALL>, + pub public_teardown_call_request: PublicCallRequest, + pub l2_to_l1_msgs: BoundedVec, // docs:end:private-context // Header of a block whose state is used during private execution (not the block the transaction is included in). - historical_header: Header, + pub historical_header: Header, - note_encrypted_logs_hashes: BoundedVec, - encrypted_logs_hashes: BoundedVec, - unencrypted_logs_hashes: BoundedVec, + pub note_encrypted_logs_hashes: BoundedVec, + pub encrypted_logs_hashes: BoundedVec, + pub contract_class_logs_hashes: BoundedVec, // Contains the last key validation request for each key type. This is used to cache the last request and avoid // fetching the same request multiple times. // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging). - last_key_validation_requests: [Option; NUM_KEY_TYPES], + pub last_key_validation_requests: [Option; NUM_KEY_TYPES], } impl PrivateContext { @@ -107,7 +106,7 @@ impl PrivateContext { l2_to_l1_msgs: BoundedVec::new(), note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), - unencrypted_logs_hashes: BoundedVec::new(), + contract_class_logs_hashes: BoundedVec::new(), last_key_validation_requests: [Option::none(); NUM_KEY_TYPES], } } @@ -181,22 +180,22 @@ impl PrivateContext { min_revertible_side_effect_counter: self.min_revertible_side_effect_counter, is_fee_payer: self.is_fee_payer, max_block_number: self.max_block_number, - note_hash_read_requests: self.note_hash_read_requests.storage, - nullifier_read_requests: self.nullifier_read_requests.storage, + note_hash_read_requests: self.note_hash_read_requests.storage(), + nullifier_read_requests: self.nullifier_read_requests.storage(), key_validation_requests_and_generators: self .key_validation_requests_and_generators - .storage, - note_hashes: self.note_hashes.storage, - nullifiers: self.nullifiers.storage, - private_call_requests: self.private_call_requests.storage, - public_call_requests: self.public_call_requests.storage, + .storage(), + note_hashes: self.note_hashes.storage(), + nullifiers: self.nullifiers.storage(), + private_call_requests: self.private_call_requests.storage(), + public_call_requests: self.public_call_requests.storage(), public_teardown_call_request: self.public_teardown_call_request, - l2_to_l1_msgs: self.l2_to_l1_msgs.storage, + l2_to_l1_msgs: self.l2_to_l1_msgs.storage(), start_side_effect_counter: self.inputs.start_side_effect_counter, end_side_effect_counter: self.side_effect_counter, - note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage, - encrypted_logs_hashes: self.encrypted_logs_hashes.storage, - unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, + note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage(), + encrypted_logs_hashes: self.encrypted_logs_hashes.storage(), + contract_class_logs_hashes: self.contract_class_logs_hashes.storage(), historical_header: self.historical_header, tx_context: self.inputs.tx_context, } @@ -252,17 +251,21 @@ impl PrivateContext { // We get a match so the cached request is the latest one cached_request.sk_app } else { - // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct - // protocol circuits to validate them by storing the validation request in context. - let request = get_key_validation_request(pk_m_hash, key_index); - let request_and_generator = KeyValidationRequestAndGenerator { - request, - sk_app_generator: sk_generators[key_index], - }; - // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary - // valid key request and not the one corresponding to pk_m_hash). + // We didn't get a match meaning the cached result is stale + // Typically we'd validate keys by showing that they are the preimage of `pk_m_hash`, but that'd require + // the oracle returning the master secret keys, which could cause malicious contracts to leak it or learn + // about secrets from other contracts. We therefore silo secret keys, and rely on the private kernel to + // validate that we siloed secret key corresponds to correct siloing of the master secret key that hashes + // to `pk_m_hash`. + let request = unsafe { get_key_validation_request(pk_m_hash, key_index) }; assert(request.pk_m.hash() == pk_m_hash); - self.key_validation_requests_and_generators.push(request_and_generator); + + self.key_validation_requests_and_generators.push( + KeyValidationRequestAndGenerator { + request, + sk_app_generator: sk_generators[key_index], + }, + ); self.last_key_validation_requests[key_index] = Option::some(request); request.sk_app } @@ -389,15 +392,36 @@ impl PrivateContext { ) -> PackedReturns { let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call; let start_side_effect_counter = self.side_effect_counter; - let (end_side_effect_counter, returns_hash) = call_private_function_internal( - contract_address, - function_selector, - args_hash, - start_side_effect_counter, - is_static_call, - ); - self.side_effect_counter = end_side_effect_counter + 1; + // The oracle simulates the private call and returns the value of the side effects counter after execution of + // the call (which means that end_side_effect_counter - start_side_effect_counter is the number of side effects + // that took place), along with the hash of the return values. We validate these by requesting a private kernel + // iteration in which the return values are constrained to hash to `returns_hash` and the side effects counter + // to increment from start to end. + let (end_side_effect_counter, returns_hash) = unsafe { + call_private_function_internal( + contract_address, + function_selector, + args_hash, + start_side_effect_counter, + is_static_call, + ) + }; + + self.private_call_requests.push( + PrivateCallRequest { + call_context: CallContext { + msg_sender: self.this_address(), + contract_address, + function_selector, + is_static_call, + }, + args_hash, + returns_hash, + start_side_effect_counter, + end_side_effect_counter, + }, + ); // TODO (fees) figure out why this crashes the prover and enable it // we need this in order to pay fees inside child call contexts @@ -410,23 +434,7 @@ impl PrivateContext { // > self.min_revertible_side_effect_counter { // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter; // } - let call_context = CallContext { - msg_sender: self.this_address(), - contract_address, - function_selector, - is_static_call, - }; - - self.private_call_requests.push( - PrivateCallRequest { - call_context, - args_hash, - returns_hash, - start_side_effect_counter, - end_side_effect_counter, - }, - ); - + self.side_effect_counter = end_side_effect_counter + 1; PackedReturns::new(returns_hash) } @@ -596,7 +604,7 @@ impl Empty for PrivateContext { historical_header: Header::empty(), note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), - unencrypted_logs_hashes: BoundedVec::new(), + contract_class_logs_hashes: BoundedVec::new(), last_key_validation_requests: [Option::none(); NUM_KEY_TYPES], } } diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index 30d182dd884..2d0320b4da6 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -8,8 +8,8 @@ use dep::protocol_types::constants::MAX_FIELD_VALUE; use dep::protocol_types::traits::{Deserialize, Empty, Serialize}; pub struct PublicContext { - args_hash: Option, - compute_args_hash: fn() -> Field, + pub args_hash: Option, + pub compute_args_hash: fn() -> Field, } impl PublicContext { @@ -21,19 +21,23 @@ impl PublicContext { where T: Serialize, { - emit_unencrypted_log(Serialize::serialize(log).as_slice()); + // AVM opcodes are constrained by the AVM itself + unsafe { emit_unencrypted_log(Serialize::serialize(log).as_slice()) }; } pub fn note_hash_exists(_self: Self, note_hash: Field, leaf_index: Field) -> bool { - note_hash_exists(note_hash, leaf_index) == 1 + // AVM opcodes are constrained by the AVM itself + unsafe { note_hash_exists(note_hash, leaf_index) } == 1 } pub fn l1_to_l2_msg_exists(_self: Self, msg_hash: Field, msg_leaf_index: Field) -> bool { - l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1 + // AVM opcodes are constrained by the AVM itself + unsafe { l1_to_l2_msg_exists(msg_hash, msg_leaf_index) } == 1 } pub fn nullifier_exists(_self: Self, unsiloed_nullifier: Field, address: AztecAddress) -> bool { - nullifier_exists(unsiloed_nullifier, address.to_field()) == 1 + // AVM opcodes are constrained by the AVM itself + unsafe { nullifier_exists(unsiloed_nullifier, address.to_field()) } == 1 } pub fn consume_l1_to_l2_message( @@ -69,7 +73,8 @@ impl PublicContext { } pub fn message_portal(_self: &mut Self, recipient: EthAddress, content: Field) { - send_l2_to_l1_msg(recipient, content); + // AVM opcodes are constrained by the AVM itself + unsafe { send_l2_to_l1_msg(recipient, content) }; } pub unconstrained fn call_public_function( @@ -109,21 +114,30 @@ impl PublicContext { } pub fn push_note_hash(_self: &mut Self, note_hash: Field) { - emit_note_hash(note_hash); + // AVM opcodes are constrained by the AVM itself + unsafe { emit_note_hash(note_hash) }; } pub fn push_nullifier(_self: &mut Self, nullifier: Field) { - emit_nullifier(nullifier); + // AVM opcodes are constrained by the AVM itself + unsafe { emit_nullifier(nullifier) }; } pub fn this_address(_self: Self) -> AztecAddress { - address() + // AVM opcodes are constrained by the AVM itself + unsafe { + address() + } } pub fn msg_sender(_self: Self) -> AztecAddress { - sender() + // AVM opcodes are constrained by the AVM itself + unsafe { + sender() + } } pub fn selector(_self: Self) -> FunctionSelector { // The selector is the first element of the calldata when calling a public function through dispatch. - let raw_selector: [Field; 1] = calldata_copy(0, 1); + // AVM opcodes are constrained by the AVM itself. + let raw_selector: [Field; 1] = unsafe { calldata_copy(0, 1) }; FunctionSelector::from_field(raw_selector[0]) } pub fn get_args_hash(mut self) -> Field { @@ -134,42 +148,71 @@ impl PublicContext { self.args_hash.unwrap_unchecked() } pub fn transaction_fee(_self: Self) -> Field { - transaction_fee() + // AVM opcodes are constrained by the AVM itself + unsafe { + transaction_fee() + } } pub fn chain_id(_self: Self) -> Field { - chain_id() + // AVM opcodes are constrained by the AVM itself + unsafe { + chain_id() + } } pub fn version(_self: Self) -> Field { - version() + // AVM opcodes are constrained by the AVM itself + unsafe { + version() + } } pub fn block_number(_self: Self) -> Field { - block_number() + // AVM opcodes are constrained by the AVM itself + unsafe { + block_number() + } } pub fn timestamp(_self: Self) -> u64 { - timestamp() + // AVM opcodes are constrained by the AVM itself + unsafe { + timestamp() + } } pub fn fee_per_l2_gas(_self: Self) -> Field { - fee_per_l2_gas() + // AVM opcodes are constrained by the AVM itself + unsafe { + fee_per_l2_gas() + } } pub fn fee_per_da_gas(_self: Self) -> Field { - fee_per_da_gas() + // AVM opcodes are constrained by the AVM itself + unsafe { + fee_per_da_gas() + } } pub fn l2_gas_left(_self: Self) -> Field { - l2_gas_left() + // AVM opcodes are constrained by the AVM itself + unsafe { + l2_gas_left() + } } pub fn da_gas_left(_self: Self) -> Field { - da_gas_left() + // AVM opcodes are constrained by the AVM itself + unsafe { + da_gas_left() + } } pub fn is_static_call(_self: Self) -> bool { - is_static_call() == 1 + // AVM opcodes are constrained by the AVM itself + unsafe { is_static_call() } == 1 } pub fn raw_storage_read(_self: Self, storage_slot: Field) -> [Field; N] { let mut out = [0; N]; for i in 0..N { - out[i] = storage_read(storage_slot + i as Field); + // AVM opcodes are constrained by the AVM itself + out[i] = unsafe { storage_read(storage_slot + i as Field) }; } out } @@ -183,7 +226,8 @@ impl PublicContext { pub fn raw_storage_write(_self: Self, storage_slot: Field, values: [Field; N]) { for i in 0..N { - storage_write(storage_slot + i as Field, values[i]); + // AVM opcodes are constrained by the AVM itself + unsafe { storage_write(storage_slot + i as Field, values[i]) }; } } @@ -287,7 +331,7 @@ unconstrained fn returndata_copy(rdoffset: u32, copy_size: u32) -> [Field] { returndata_copy_opcode(rdoffset, copy_size) } -unconstrained fn avm_return(returndata: [Field; N]) { +pub unconstrained fn avm_return(returndata: [Field]) { return_opcode(returndata) } @@ -388,7 +432,7 @@ unconstrained fn returndata_size_opcode() -> u32 {} unconstrained fn returndata_copy_opcode(rdoffset: u32, copy_size: u32) -> [Field] {} #[oracle(avmOpcodeReturn)] -unconstrained fn return_opcode(returndata: [Field; N]) {} +unconstrained fn return_opcode(returndata: [Field]) {} // This opcode reverts using the exact data given. In general it should only be used // to do rethrows, where the revert data is the same as the original revert data. diff --git a/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr b/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr index 26b8531187d..5a2c5f765ab 100644 --- a/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr @@ -12,7 +12,7 @@ pub struct UnconstrainedContext { } impl UnconstrainedContext { - unconstrained fn new() -> Self { + pub unconstrained fn new() -> Self { // We could call these oracles on the getters instead of at creation, which makes sense given that they might // not even be accessed. However any performance gains are minimal, and we'd rather fail early if a user // incorrectly attempts to create an UnconstrainedContext in an environment in which these oracles are not @@ -24,40 +24,43 @@ impl UnconstrainedContext { Self { block_number, contract_address, version, chain_id } } - unconstrained fn at(contract_address: AztecAddress) -> Self { + pub unconstrained fn at(contract_address: AztecAddress) -> Self { let block_number = get_block_number(); let chain_id = get_chain_id(); let version = get_version(); Self { block_number, contract_address, version, chain_id } } - unconstrained fn at_historical(contract_address: AztecAddress, block_number: u32) -> Self { + pub unconstrained fn at_historical(contract_address: AztecAddress, block_number: u32) -> Self { let chain_id = get_chain_id(); let version = get_version(); Self { block_number, contract_address, version, chain_id } } - fn block_number(self) -> u32 { + pub fn block_number(self) -> u32 { self.block_number } - fn this_address(self) -> AztecAddress { + pub fn this_address(self) -> AztecAddress { self.contract_address } - fn version(self) -> Field { + pub fn version(self) -> Field { self.version } - fn chain_id(self) -> Field { + pub fn chain_id(self) -> Field { self.chain_id } - unconstrained fn raw_storage_read(self: Self, storage_slot: Field) -> [Field; N] { + pub unconstrained fn raw_storage_read( + self: Self, + storage_slot: Field, + ) -> [Field; N] { storage_read(self.this_address(), storage_slot, self.block_number()) } - unconstrained fn storage_read(self, storage_slot: Field) -> T + pub unconstrained fn storage_read(self, storage_slot: Field) -> T where T: Deserialize, { diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr index 2b7f58b41bb..c538adeddb2 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr @@ -26,7 +26,8 @@ where let storage_slot = note_header.storage_slot; // TODO(#8589): use typesystem to skip this check when not needed - let note_exists = context.note_hashes.storage.any(|n: NoteHash| n.counter == note_hash_counter); + let note_exists = + context.note_hashes.storage().any(|n: NoteHash| n.counter == note_hash_counter); assert(note_exists, "Can only emit a note log for an existing note."); let contract_address: AztecAddress = context.this_address(); diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr index 84bfc08e05c..be847797a8b 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr @@ -14,11 +14,11 @@ pub struct EncryptedLogHeader { } impl EncryptedLogHeader { - fn new(address: AztecAddress) -> Self { + pub fn new(address: AztecAddress) -> Self { EncryptedLogHeader { address } } - fn compute_ciphertext(self, secret: Scalar, pk: T) -> [u8; 48] + pub fn compute_ciphertext(self, secret: Scalar, pk: T) -> [u8; 48] where T: ToPoint, { diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr index 099a253e07f..264f2898ec8 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr @@ -14,7 +14,10 @@ use std::{ use crate::{ encrypted_logs::header::EncryptedLogHeader, keys::point_to_symmetric_key::point_to_symmetric_key, - oracle::{notes::{get_app_tag_bytes, increment_app_tagging_secret}, random::random}, + oracle::{ + notes::{get_app_tag_bytes_as_sender, increment_app_tagging_secret_index_as_sender}, + random::random, + }, utils::point::point_to_bytes, }; @@ -128,8 +131,8 @@ fn compute_encrypted_log( // We assume that the sender wants for the recipient to find the tagged note, and therefore that they will cooperate // and use the correct tag. Usage of a bad tag will result in the recipient not being able to find the note // automatically. - let tag_bytes = unsafe { get_app_tag_bytes(sender, recipient) }; - increment_app_tagging_secret(sender, recipient); + let tag_bytes = unsafe { get_app_tag_bytes_as_sender(sender, recipient) }; + increment_app_tagging_secret_index_as_sender(sender, recipient); for i in 0..32 { encrypted_bytes[offset + i] = tag_bytes[i]; @@ -331,13 +334,9 @@ mod test { 0x25afb798ea6d0b8c1618e50fdeafa463059415013d3b7c75d46abf5e242be70c, ); - let _ = OracleMock::mock("getAppTaggingSecret").returns([ - 69420, - 0x25afb798ea6d0b8c1618e50fdeafa463059415013d3b7c75d46abf5e242be70c, - 1337, - ]); + let _ = OracleMock::mock("getAppTaggingSecretAsSender").returns([69420, 1337]); - let _ = OracleMock::mock("incrementAppTaggingSecret"); + let _ = OracleMock::mock("incrementAppTaggingSecretIndexAsSender").returns(()); let log = compute_private_log_payload( contract_address, diff --git a/noir-projects/aztec-nr/aztec/src/event/mod.nr b/noir-projects/aztec-nr/aztec/src/event/mod.nr index e77edfe3735..00e48e01130 100644 --- a/noir-projects/aztec-nr/aztec/src/event/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/event/mod.nr @@ -1 +1 @@ -mod event_interface; +pub mod event_interface; diff --git a/noir-projects/aztec-nr/aztec/src/hash.nr b/noir-projects/aztec-nr/aztec/src/hash.nr index e60eb7d229c..b454547e3ab 100644 --- a/noir-projects/aztec-nr/aztec/src/hash.nr +++ b/noir-projects/aztec-nr/aztec/src/hash.nr @@ -78,7 +78,7 @@ pub fn compute_l1_to_l2_message_nullifier(message_hash: Field, secret: Field) -> } pub struct ArgsHasher { - fields: [Field], + pub fields: [Field], } impl Hash for ArgsHasher { diff --git a/noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr b/noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr index c94279a7095..d04a08baee2 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/getters/mod.nr @@ -24,13 +24,13 @@ pub unconstrained fn get_ovsk_app(ovpk_m_hash: Field) -> Field { // keys at once since the constraints for reading them all are actually fewer than if we read them one at a time - any // read keys that are not required by the caller can simply be discarded. pub fn get_public_keys(account: AztecAddress) -> PublicKeys { - let (hinted_canonical_public_keys, partial_address) = - unsafe { get_public_keys_and_partial_address(account) }; + // Public keys are constrained by showing their inclusion in the address's preimage. + let (public_keys, partial_address) = unsafe { get_public_keys_and_partial_address(account) }; assert_eq( account, - AztecAddress::compute(hinted_canonical_public_keys, partial_address), + AztecAddress::compute(public_keys, partial_address), "Invalid public keys hint for address", ); - hinted_canonical_public_keys + public_keys } diff --git a/noir-projects/aztec-nr/aztec/src/macros/dispatch/mod.nr b/noir-projects/aztec-nr/aztec/src/macros/dispatch/mod.nr index 200b743ede1..956f518c19f 100644 --- a/noir-projects/aztec-nr/aztec/src/macros/dispatch/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/macros/dispatch/mod.nr @@ -66,7 +66,7 @@ pub comptime fn generate_public_dispatch(m: Module) -> Quoted { } else { quote { let return_value = dep::aztec::protocol_types::traits::Serialize::serialize($call); - dep::aztec::context::public_context::avm_return(return_value); + dep::aztec::context::public_context::avm_return(return_value.as_slice()); } }; diff --git a/noir-projects/aztec-nr/aztec/src/macros/functions/interfaces.nr b/noir-projects/aztec-nr/aztec/src/macros/functions/interfaces.nr index 47b63af59da..ff768788fff 100644 --- a/noir-projects/aztec-nr/aztec/src/macros/functions/interfaces.nr +++ b/noir-projects/aztec-nr/aztec/src/macros/functions/interfaces.nr @@ -14,11 +14,11 @@ pub comptime mut global STUBS: UHashMap Quoted { let name = f.name(); let mut parameters = - f.parameters().map(|(name, typ): (Quoted, Type)| quote { $name: $typ }).join(quote {,}); + f.parameters().map(|(name, typ): (Quoted, Type)| quote { pub $name: $typ }).join(quote {,}); let parameters_struct_name = f"{name}_parameters".quoted_contents(); let parameters = quote { - struct $parameters_struct_name { + pub struct $parameters_struct_name { $parameters } }; diff --git a/noir-projects/aztec-nr/aztec/src/macros/functions/mod.nr b/noir-projects/aztec-nr/aztec/src/macros/functions/mod.nr index fbafae25c72..038fee01984 100644 --- a/noir-projects/aztec-nr/aztec/src/macros/functions/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/macros/functions/mod.nr @@ -141,7 +141,12 @@ pub comptime fn private(f: FunctionDefinition) -> Quoted { }; let storage_init = if module_has_storage { - quote { let storage = Storage::init(&mut context); } + quote { + // Some functions don't access storage, but it'd be quite difficult to only inject this variable if it is + // referenced. We instead ignore 'unused variable' warnings for it. + #[allow(unused_variables)] + let storage = Storage::init(&mut context); + } } else { quote {} }; @@ -247,11 +252,13 @@ comptime fn transform_public(f: FunctionDefinition) -> Quoted { .fold(0, |acc: u32, val: u32| acc + val); // Unlike in the private case, in public the `context` does not need to receive the hash of the original params. - let context_creation = quote { let mut context = dep::aztec::context::public_context::PublicContext::new(|| { + let context_creation = quote { + let mut context = dep::aztec::context::public_context::PublicContext::new(|| { // We start from 1 because we skip the selector for the dispatch function. let serialized_args : [Field; $args_len] = dep::aztec::context::public_context::calldata_copy(1, $args_len); dep::aztec::hash::hash_args_array(serialized_args) - }); }; + }); + }; // Modifications introduced by the different marker attributes. let internal_check = if is_fn_internal(f) { @@ -273,7 +280,12 @@ comptime fn transform_public(f: FunctionDefinition) -> Quoted { }; let storage_init = if module_has_storage { - quote { let storage = Storage::init(&mut context); } + // Some functions don't access storage, but it'd be quite difficult to only inject this variable if it is + // referenced. We instead ignore 'unused variable' warnings for it. + quote { + #[allow(unused_variables)] + let storage = Storage::init(&mut context); + } } else { quote {} }; diff --git a/noir-projects/aztec-nr/aztec/src/macros/mod.nr b/noir-projects/aztec-nr/aztec/src/macros/mod.nr index 04a63cf8910..924c5bcf8e0 100644 --- a/noir-projects/aztec-nr/aztec/src/macros/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/macros/mod.nr @@ -29,11 +29,13 @@ pub comptime fn aztec(m: Module) -> Quoted { generate_compute_note_hash_and_optionally_a_nullifier(); let note_exports = generate_note_exports(); let public_dispatch = generate_public_dispatch(m); + let sync_notes = generate_sync_notes(); quote { $note_exports $interface $compute_note_hash_and_optionally_a_nullifier $public_dispatch + $sync_notes } } @@ -68,7 +70,7 @@ comptime fn generate_contract_interface(m: Module) -> Quoted { }; quote { - struct $module_name { + pub struct $module_name { target_contract: dep::aztec::protocol_types::address::AztecAddress } @@ -173,3 +175,11 @@ comptime fn generate_note_exports() -> Quoted { }) .join(quote {}) } + +comptime fn generate_sync_notes() -> Quoted { + quote { + unconstrained fn sync_notes() { + aztec::oracle::notes::sync_notes(); + } + } +} diff --git a/noir-projects/aztec-nr/aztec/src/macros/notes/mod.nr b/noir-projects/aztec-nr/aztec/src/macros/notes/mod.nr index 7818a0a6378..4570d2ce571 100644 --- a/noir-projects/aztec-nr/aztec/src/macros/notes/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/macros/notes/mod.nr @@ -205,7 +205,7 @@ comptime fn generate_note_properties(s: StructDefinition) -> Quoted { let non_header_fields = s.fields().filter(|(_, typ): (Quoted, Type)| typ != note_header_type); let properties_types = non_header_fields - .map(|(name, _): (Quoted, Type)| quote { $name: $property_selector_type }) + .map(|(name, _): (Quoted, Type)| quote { pub $name: $property_selector_type }) .join(quote {,}); // TODO #8694: Properly handle non-field types https://github.com/AztecProtocol/aztec-packages/issues/8694 @@ -220,7 +220,7 @@ comptime fn generate_note_properties(s: StructDefinition) -> Quoted { let properties = properties_list.join(quote {,}); quote { - struct $struct_name { + pub struct $struct_name { $properties_types } @@ -284,8 +284,8 @@ pub(crate) comptime fn generate_note_export( let note_field_constructors = note_field_constructors.join(quote {,}); quote { - struct $note_fields_name { - $note_fields + pub struct $note_fields_name { + pub $note_fields } #[abi(notes)] @@ -448,13 +448,13 @@ comptime fn generate_setup_payload( ( quote { - struct $setup_payload_name { - log_plaintext: [u8; $log_plaintext_length], - hiding_point: aztec::protocol_types::point::Point + pub struct $setup_payload_name { + pub log_plaintext: [u8; $log_plaintext_length], + pub hiding_point: aztec::protocol_types::point::Point } impl $setup_payload_name { - fn new($new_args) -> $setup_payload_name { + pub fn new($new_args) -> $setup_payload_name { $new_aux_vars let hiding_point = std::embedded_curve_ops::multi_scalar_mul( [$new_generators], @@ -468,7 +468,7 @@ comptime fn generate_setup_payload( } } - fn encrypt_log(self, context: &mut PrivateContext, ovpk: aztec::protocol_types::public_keys::OvpkM, recipient: aztec::protocol_types::address::AztecAddress, sender: aztec::protocol_types::address::AztecAddress) -> [Field; $encrypted_log_field_length] { + pub fn encrypt_log(self, context: &mut PrivateContext, ovpk: aztec::protocol_types::public_keys::OvpkM, recipient: aztec::protocol_types::address::AztecAddress, sender: aztec::protocol_types::address::AztecAddress) -> [Field; $encrypted_log_field_length] { let ovsk_app: Field = context.request_ovsk_app(ovpk.hash()); let encrypted_log_bytes: [u8; $encrypted_log_byte_length] = aztec::encrypted_logs::payload::compute_partial_public_log_payload( @@ -674,15 +674,15 @@ comptime fn generate_finalization_payload( ( quote { - struct $finalization_payload_name { - context: &mut aztec::prelude::PublicContext, - hiding_point_slot: Field, - setup_log_slot: Field, - public_values: [Field; $public_values_length], + pub struct $finalization_payload_name { + pub context: &mut aztec::prelude::PublicContext, + pub hiding_point_slot: Field, + pub setup_log_slot: Field, + pub public_values: [Field; $public_values_length], } impl $finalization_payload_name { - fn new(mut self, context: &mut aztec::prelude::PublicContext, slot: Field, $args) -> $finalization_payload_name { + pub fn new(mut self, context: &mut aztec::prelude::PublicContext, slot: Field, $args) -> $finalization_payload_name { self.context = context; self.hiding_point_slot = slot; @@ -694,12 +694,12 @@ comptime fn generate_finalization_payload( self } - fn emit(self) { + pub fn emit(self) { self.emit_note_hash(); self.emit_log(); } - fn emit_note_hash(self) { + pub fn emit_note_hash(self) { // Read the hiding point from "transient" storage and check it's not empty to ensure the transfer was prepared let hiding_point: aztec::prelude::Point = self.context.storage_read(self.hiding_point_slot); assert(!aztec::protocol_types::traits::is_empty(hiding_point), "transfer not prepared"); @@ -720,7 +720,7 @@ comptime fn generate_finalization_payload( // self.context.storage_write(self.hiding_point_slot, [0; aztec::protocol_types::point::POINT_LENGTH]); } - fn emit_log(self) { + pub fn emit_log(self) { // We load the setup log from storage let setup_log_fields: [Field; $setup_log_field_length] = self.context.storage_read(self.setup_log_slot); @@ -730,7 +730,6 @@ comptime fn generate_finalization_payload( // We append the public value to the log and emit it as unencrypted log let mut finalization_log = [0; $finalization_log_byte_length]; - // Iterate over the partial log and copy it to the final log for i in 0..setup_log.len() { finalization_log[i + 1] = setup_log[i]; diff --git a/noir-projects/aztec-nr/aztec/src/macros/storage/mod.nr b/noir-projects/aztec-nr/aztec/src/macros/storage/mod.nr index 84c233ba877..c48fb8f5161 100644 --- a/noir-projects/aztec-nr/aztec/src/macros/storage/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/macros/storage/mod.nr @@ -69,17 +69,17 @@ pub comptime fn storage(s: StructDefinition) -> Quoted { quote { $storage_impl - struct StorageLayoutFields { + pub struct StorageLayoutFields { $storage_layout_fields } - struct StorageLayout { - contract_name: str, - fields: StorageLayoutFields + pub struct StorageLayout { + pub contract_name: str, + pub fields: StorageLayoutFields } #[abi(storage)] - global $storage_layout_name = StorageLayout { + pub global $storage_layout_name = StorageLayout { contract_name: $module_name_str, fields: StorageLayoutFields { $storage_layout_constructors } }; diff --git a/noir-projects/aztec-nr/aztec/src/note/constants.nr b/noir-projects/aztec-nr/aztec/src/note/constants.nr index f948e023f88..049cb73005b 100644 --- a/noir-projects/aztec-nr/aztec/src/note/constants.nr +++ b/noir-projects/aztec-nr/aztec/src/note/constants.nr @@ -1,6 +1,7 @@ -global MAX_NOTE_FIELDS_LENGTH: u32 = 20; +pub global MAX_NOTE_FIELDS_LENGTH: u32 = 20; // The plus 1 is 1 extra field for nonce. // + 2 for EXTRA_DATA: [number_of_return_notes, contract_address] -global GET_NOTE_ORACLE_RETURN_LENGTH: u32 = MAX_NOTE_FIELDS_LENGTH + 1 + 2; -global MAX_NOTES_PER_PAGE: u32 = 10; -global VIEW_NOTE_ORACLE_RETURN_LENGTH: u32 = MAX_NOTES_PER_PAGE * (MAX_NOTE_FIELDS_LENGTH + 1) + 2; +pub global GET_NOTE_ORACLE_RETURN_LENGTH: u32 = MAX_NOTE_FIELDS_LENGTH + 1 + 2; +pub global MAX_NOTES_PER_PAGE: u32 = 10; +pub global VIEW_NOTE_ORACLE_RETURN_LENGTH: u32 = + MAX_NOTES_PER_PAGE * (MAX_NOTE_FIELDS_LENGTH + 1) + 2; diff --git a/noir-projects/aztec-nr/aztec/src/note/note_emission.nr b/noir-projects/aztec-nr/aztec/src/note/note_emission.nr index a9f9ee13fbd..d6ac26bc2a9 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_emission.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_emission.nr @@ -3,7 +3,7 @@ * The exact `emit` logic is passed in by the application code */ pub struct NoteEmission { - note: Note, + pub note: Note, } impl NoteEmission { diff --git a/noir-projects/aztec-nr/aztec/src/note/note_field.nr b/noir-projects/aztec-nr/aztec/src/note/note_field.nr index f5c740a1e5c..99e7a2c3f90 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_field.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_field.nr @@ -1,5 +1,5 @@ // Used by macros when generating note export. pub struct NoteField { - index: u32, - nullable: bool, + pub index: u32, + pub nullable: bool, } diff --git a/noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr b/noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr index 52e8a14b64b..99efea10032 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr @@ -51,7 +51,7 @@ fn check_note_fields( serialized_note: [Field; N], selects: BoundedVec, N>, ) { - for i in 0..selects.len { + for i in 0..selects.len() { let select = selects.get_unchecked(i).unwrap_unchecked(); let value_field = extract_property_value_from_selector(serialized_note, select.property_selector); @@ -68,7 +68,7 @@ fn check_notes_order( fields_1: [Field; N], sorts: BoundedVec, N>, ) { - for i in 0..sorts.len { + for i in 0..sorts.len() { let sort = sorts.get_unchecked(i).unwrap_unchecked(); let field_0 = extract_property_value_from_selector(fields_0, sort.property_selector); let field_1 = extract_property_value_from_selector(fields_1, sort.property_selector); @@ -293,7 +293,7 @@ unconstrained fn flatten_options( let mut select_values = [0; N]; let mut select_comparators = [0; N]; - for i in 0..selects.len { + for i in 0..selects.len() { let select = selects.get(i); if select.is_some() { select_by_indexes[num_selects] = select.unwrap_unchecked().property_selector.index; @@ -309,7 +309,7 @@ unconstrained fn flatten_options( let mut sort_by_offsets = [0; N]; let mut sort_by_lengths = [0; N]; let mut sort_order = [0; N]; - for i in 0..sorts.len { + for i in 0..sorts.len() { let sort = sorts.get(i); if sort.is_some() { sort_by_indexes[i] = sort.unwrap_unchecked().property_selector.index; diff --git a/noir-projects/aztec-nr/aztec/src/note/note_getter_options.nr b/noir-projects/aztec-nr/aztec/src/note/note_getter_options.nr index c4a5eb0f742..00de16117cc 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_getter_options.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_getter_options.nr @@ -3,15 +3,15 @@ use dep::protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, trait use std::option::Option; pub struct PropertySelector { - index: u8, // index of the field in the serialized note array - offset: u8, // offset in the byte representation of the field (selected with index above) from which to reading - length: u8, // number of bytes to read after the offset + pub(crate) index: u8, // index of the field in the serialized note array + pub(crate) offset: u8, // offset in the byte representation of the field (selected with index above) from which to reading + pub(crate) length: u8, // number of bytes to read after the offset } pub struct Select { - property_selector: PropertySelector, - comparator: u8, - value: Field, + pub(crate) property_selector: PropertySelector, + pub(crate) comparator: u8, + pub(crate) value: Field, } impl Select { @@ -23,15 +23,15 @@ impl Select { } pub struct SortOrderEnum { - DESC: u8, - ASC: u8, + pub DESC: u8, + pub ASC: u8, } -global SortOrder = SortOrderEnum { DESC: 1, ASC: 2 }; +pub global SortOrder = SortOrderEnum { DESC: 1, ASC: 2 }; pub struct Sort { - property_selector: PropertySelector, - order: u8, + pub(crate) property_selector: PropertySelector, + pub(crate) order: u8, } impl Sort { @@ -41,11 +41,11 @@ impl Sort { } pub struct NoteStatusEnum { - ACTIVE: u8, - ACTIVE_OR_NULLIFIED: u8, + pub ACTIVE: u8, + pub ACTIVE_OR_NULLIFIED: u8, } -global NoteStatus = NoteStatusEnum { +pub global NoteStatus = NoteStatusEnum { ACTIVE: 1, ACTIVE_OR_NULLIFIED: 2, // TODO 4217: add 'NULLIFIED' @@ -61,17 +61,17 @@ fn return_all_notes( // docs:start:NoteGetterOptions pub struct NoteGetterOptions { - selects: BoundedVec, N>, - sorts: BoundedVec, N>, - limit: u32, - offset: u32, + pub selects: BoundedVec, N>, + pub sorts: BoundedVec, N>, + pub limit: u32, + pub offset: u32, // Preprocessor and filter functions are used to filter notes. The preprocessor is applied before the filter and // unlike filter it is applied in an unconstrained context. - preprocessor: fn([Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], PREPROCESSOR_ARGS) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], - preprocessor_args: PREPROCESSOR_ARGS, - filter: fn([Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], FILTER_ARGS) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], - filter_args: FILTER_ARGS, - status: u8, + pub preprocessor: fn([Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], PREPROCESSOR_ARGS) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], + pub preprocessor_args: PREPROCESSOR_ARGS, + pub filter: fn([Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], FILTER_ARGS) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], + pub filter_args: FILTER_ARGS, + pub status: u8, } // docs:end:NoteGetterOptions diff --git a/noir-projects/aztec-nr/aztec/src/note/note_viewer_options.nr b/noir-projects/aztec-nr/aztec/src/note/note_viewer_options.nr index e4d64104b14..c131195d69e 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_viewer_options.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_viewer_options.nr @@ -6,11 +6,11 @@ use std::option::Option; // docs:start:NoteViewerOptions pub struct NoteViewerOptions { - selects: BoundedVec, N>, - sorts: BoundedVec, N>, - limit: u32, - offset: u32, - status: u8, + pub selects: BoundedVec, N>, + pub sorts: BoundedVec, N>, + pub limit: u32, + pub offset: u32, + pub status: u8, } // docs:end:NoteViewerOptions diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_membership_witness.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_membership_witness.nr index fed4c3b66b7..b1783ddea14 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_membership_witness.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_membership_witness.nr @@ -14,8 +14,8 @@ global ARCHIVE_TREE_ID = 4; // Another way to do it would be to add "type_hint: [Field; T]" as argument to `get_membership_witness` but that's // a bit too boilerplatey for my taste. pub struct MembershipWitness { - index: Field, - path: [Field; N], + pub index: Field, + pub path: [Field; N], } #[oracle(getMembershipWitness)] diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr index abdca0865c8..e5f87124753 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr @@ -8,9 +8,9 @@ use dep::protocol_types::{ global NULLIFIER_MEMBERSHIP_WITNESS: u32 = 44; pub struct NullifierMembershipWitness { - index: Field, - leaf_preimage: NullifierLeafPreimage, - path: [Field; NULLIFIER_TREE_HEIGHT], + pub index: Field, + pub leaf_preimage: NullifierLeafPreimage, + pub path: [Field; NULLIFIER_TREE_HEIGHT], } impl NullifierMembershipWitness { diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr index f37a79a3875..517a8e2d59a 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr @@ -6,9 +6,9 @@ global LEAF_PREIMAGE_LENGTH: u32 = 4; global PUBLIC_DATA_WITNESS: u32 = 45; pub struct PublicDataWitness { - index: Field, - leaf_preimage: PublicDataTreeLeafPreimage, - path: [Field; PUBLIC_DATA_TREE_HEIGHT], + pub index: Field, + pub leaf_preimage: PublicDataTreeLeafPreimage, + pub path: [Field; PUBLIC_DATA_TREE_HEIGHT], } #[oracle(getPublicDataTreeWitness)] diff --git a/noir-projects/aztec-nr/aztec/src/oracle/logs.nr b/noir-projects/aztec-nr/aztec/src/oracle/logs.nr index 85e54210bf4..3db99d00902 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/logs.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/logs.nr @@ -32,15 +32,6 @@ pub fn emit_encrypted_event_log( } } -/// Informs the simulator that an unencrypted log has been emitted, helping it keep track of side-effects and easing -/// debugging. -pub fn emit_unencrypted_log_private(contract_address: AztecAddress, message: T, counter: u32) { - // This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to call. - unsafe { - emit_unencrypted_log_private_oracle_wrapper(contract_address, message, counter) - } -} - unconstrained fn emit_encrypted_note_log_oracle_wrapper( note_hash_counter: u32, encrypted_note: [u8; M], @@ -58,15 +49,7 @@ unconstrained fn emit_encrypted_event_log_oracle_wrapper( emit_encrypted_event_log_oracle(contract_address, randomness, encrypted_event, counter) } -unconstrained fn emit_unencrypted_log_private_oracle_wrapper( - contract_address: AztecAddress, - message: T, - counter: u32, -) { - let _ = emit_unencrypted_log_private_oracle(contract_address, message, counter); -} - -/// Temporary substitute for `emit_unencrypted_log_private` that is used for handling contract class registration. This +/// Temporary substitute that is used for handling contract class registration. This /// variant returns the log hash, which would be too large to compute inside a circuit. pub unconstrained fn emit_contract_class_unencrypted_log_private( contract_address: AztecAddress, @@ -92,14 +75,7 @@ unconstrained fn emit_encrypted_event_log_oracle( _counter: u32, ) {} -#[oracle(emitUnencryptedLog)] -unconstrained fn emit_unencrypted_log_private_oracle( - _contract_address: AztecAddress, - _message: T, - _counter: u32, -) -> Field {} - -#[oracle(emitContractClassUnencryptedLog)] +#[oracle(emitContractClassLog)] unconstrained fn emit_contract_class_unencrypted_log_private_oracle( contract_address: AztecAddress, message: [Field; N], diff --git a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr index c94c8a3ef7a..4bbc97be9f9 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr @@ -155,6 +155,7 @@ pub unconstrained fn get_notes, { + sync_notes_oracle_wrapper(); let fields = get_notes_oracle_wrapper( storage_slot, num_selects, @@ -203,27 +204,30 @@ pub unconstrained fn check_nullifier_exists(inner_nullifier: Field) -> bool { #[oracle(checkNullifierExists)] unconstrained fn check_nullifier_exists_oracle(_inner_nullifier: Field) -> Field {} -/// Same as `get_app_tagging_secret`, except it returns the derived tag as an array of bytes, ready to be included in a +/// Same as `get_app_tagging_secret_as_sender`, except it returns the derived tag as an array of bytes, ready to be included in a /// log. -pub unconstrained fn get_app_tag_bytes(sender: AztecAddress, recipient: AztecAddress) -> [u8; 32] { - let tag = get_app_tagging_secret(sender, recipient).compute_tag(); +pub unconstrained fn get_app_tag_bytes_as_sender( + sender: AztecAddress, + recipient: AztecAddress, +) -> [u8; 32] { + let tag = get_app_tagging_secret_as_sender(sender, recipient).compute_tag(recipient); tag.to_be_bytes() } /// Returns the tagging secret for a given sender and recipient pair, siloed for the current contract address. -/// Includes the last known index used for tagging with this secret. +/// Includes the last known index used to send a note tagged with this secret. /// For this to work, PXE must know the ivpsk_m of the sender. /// For the recipient's side, only the address is needed. -pub unconstrained fn get_app_tagging_secret( +pub unconstrained fn get_app_tagging_secret_as_sender( sender: AztecAddress, recipient: AztecAddress, ) -> IndexedTaggingSecret { - let result = get_app_tagging_secret_oracle(sender, recipient); + let result = get_app_tagging_secret_as_sender_oracle(sender, recipient); IndexedTaggingSecret::deserialize(result) } -#[oracle(getAppTaggingSecret)] -unconstrained fn get_app_tagging_secret_oracle( +#[oracle(getAppTaggingSecretAsSender)] +unconstrained fn get_app_tagging_secret_as_sender_oracle( _sender: AztecAddress, _recipient: AztecAddress, ) -> [Field; INDEXED_TAGGING_SECRET_LENGTH] {} @@ -233,38 +237,38 @@ unconstrained fn get_app_tagging_secret_oracle( /// This change should only be persisted in a non-volatile database if the tagged log is found in an actual block - /// otherwise e.g. a reverting transaction can cause the sender to accidentally skip indices and later produce notes /// that are not found by the recipient. -pub fn increment_app_tagging_secret(sender: AztecAddress, recipient: AztecAddress) { +pub fn increment_app_tagging_secret_index_as_sender(sender: AztecAddress, recipient: AztecAddress) { // This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to call. unsafe { - increment_app_tagging_secret_wrapper(sender, recipient); + increment_app_tagging_secret_index_as_sender_wrapper(sender, recipient); } } -unconstrained fn increment_app_tagging_secret_wrapper( +unconstrained fn increment_app_tagging_secret_index_as_sender_wrapper( sender: AztecAddress, recipient: AztecAddress, ) { - increment_app_tagging_secret_oracle(sender, recipient); + increment_app_tagging_secret_index_as_sender_oracle(sender, recipient); } -#[oracle(incrementAppTaggingSecret)] -unconstrained fn increment_app_tagging_secret_oracle( +#[oracle(incrementAppTaggingSecretIndexAsSender)] +unconstrained fn increment_app_tagging_secret_index_as_sender_oracle( _sender: AztecAddress, _recipient: AztecAddress, ) {} -/// Finds new notes that may have been sent to `recipient` in the current contract and makes them available +/// Finds new notes that may have been sent to all registered accounts in PXE in the current contract and makes them available /// for later querying via the `get_notes` oracle. -pub fn sync_notes(recipient: AztecAddress) { +pub fn sync_notes() { // This oracle call returns nothing: we only call it for its side effects. It is therefore always safe to call. unsafe { - sync_notes_oracle_wrapper(recipient); + sync_notes_oracle_wrapper(); } } -unconstrained fn sync_notes_oracle_wrapper(recipient: AztecAddress) { - sync_notes_oracle(recipient); +unconstrained fn sync_notes_oracle_wrapper() { + sync_notes_oracle(); } #[oracle(syncNotes)] -unconstrained fn sync_notes_oracle(_recipient: AztecAddress) {} +unconstrained fn sync_notes_oracle() {} diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/mod.nr b/noir-projects/aztec-nr/aztec/src/state_vars/mod.nr index 72d00c2ac17..609cf778506 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/mod.nr @@ -1,12 +1,12 @@ -mod map; -mod private_immutable; -mod private_mutable; -mod public_immutable; -mod public_mutable; -mod private_set; -mod shared_immutable; -mod shared_mutable; -mod storage; +pub mod map; +pub mod private_immutable; +pub mod private_mutable; +pub mod public_immutable; +pub mod public_mutable; +pub mod private_set; +pub mod shared_immutable; +pub mod shared_mutable; +pub mod storage; pub use crate::state_vars::map::Map; pub use crate::state_vars::private_immutable::PrivateImmutable; diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr index 7e94bdd8b0c..471ede3d9d5 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_set.nr @@ -18,8 +18,8 @@ use dep::protocol_types::{ // docs:start:struct pub struct PrivateSet { - context: Context, - storage_slot: Field, + pub context: Context, + pub storage_slot: Field, } // docs:end:struct @@ -41,6 +41,8 @@ impl PrivateSet where Note: NoteInterface + NullifiableNote, { + // TODO: This function is still around because of a stale blacklist token. It should most likely be nuked. If you + // need this functionality use partial notes instead. // docs:start:insert_from_public pub fn insert_from_public(self, note: &mut Note) { create_note_hash_from_public(self.context, self.storage_slot, note); diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr index afcfc4795ac..8b8cde20948 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr @@ -1,5 +1,5 @@ -mod shared_mutable; -mod scheduled_delay_change; -mod scheduled_value_change; +pub mod shared_mutable; +pub(crate) mod scheduled_delay_change; +pub(crate) mod scheduled_value_change; pub use shared_mutable::SharedMutable; diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/storage.nr b/noir-projects/aztec-nr/aztec/src/state_vars/storage.nr index be7d986eaf5..a48c7de3749 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/storage.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/storage.nr @@ -13,5 +13,5 @@ where // Every entry in the storage struct will be exported in the compilation artifact as a // Storable entity, containing the storage slot pub struct Storable { - slot: Field, + pub slot: Field, } diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/mod.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/mod.nr index 93eb11040c8..4ba8dbc620e 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/mod.nr @@ -1,3 +1,3 @@ -mod test_environment; -mod cheatcodes; -mod utils; +pub mod test_environment; +pub mod cheatcodes; +pub mod utils; diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr index 2bf3b5ed989..1ab5a63f863 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr @@ -1,9 +1,8 @@ use dep::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}; -use crate::context::{call_interfaces::CallInterface, packed_returns::PackedReturns}; -use crate::context::inputs::PrivateContextInputs; - -use crate::context::{PrivateContext, PublicContext, UnconstrainedContext}; +use crate::context::{ + call_interfaces::CallInterface, PrivateContext, PublicContext, UnconstrainedContext, +}; use crate::hash::hash_args; use crate::test::helpers::{cheatcodes, utils::Deployer}; @@ -17,52 +16,52 @@ use protocol_types::constants::PUBLIC_DISPATCH_SELECTOR; pub struct TestEnvironment {} impl TestEnvironment { - unconstrained fn new() -> Self { + pub unconstrained fn new() -> Self { cheatcodes::reset(); Self {} } - unconstrained fn block_number(_self: Self) -> u32 { + pub unconstrained fn block_number(_self: Self) -> u32 { get_block_number() } - unconstrained fn contract_address(_self: Self) -> AztecAddress { + pub unconstrained fn contract_address(_self: Self) -> AztecAddress { get_contract_address() } - unconstrained fn impersonate(_self: Self, address: AztecAddress) { + pub unconstrained fn impersonate(_self: Self, address: AztecAddress) { cheatcodes::set_contract_address(address) } - unconstrained fn advance_block_to(&mut self, block_number: u32) { + pub unconstrained fn advance_block_to(&mut self, block_number: u32) { let difference = block_number - get_block_number(); self.advance_block_by(difference); } - unconstrained fn advance_block_by(_self: &mut Self, blocks: u32) { + pub unconstrained fn advance_block_by(_self: &mut Self, blocks: u32) { cheatcodes::advance_blocks_by(blocks); } - unconstrained fn public(_self: Self) -> PublicContext { + pub unconstrained fn public(_self: Self) -> PublicContext { PublicContext::new(|| 0) } - unconstrained fn public_with_args_hash(_self: Self, args: [Field]) -> PublicContext { + pub unconstrained fn public_with_args_hash(_self: Self, args: [Field]) -> PublicContext { let mut context = PublicContext::new(|| panic(f"Provide args hash manually")); context.args_hash = Option::some(hash_args(args)); context } - unconstrained fn private(&mut self) -> PrivateContext { + pub unconstrained fn private(&mut self) -> PrivateContext { self.private_at(get_block_number() - 1) } // unconstrained is a key word, so we mis-spell purposefully here, like we do with contrakt - unconstrained fn unkonstrained(_self: Self) -> UnconstrainedContext { + pub unconstrained fn unkonstrained(_self: Self) -> UnconstrainedContext { UnconstrainedContext::new() } - unconstrained fn private_at(&mut self, historical_block_number: u32) -> PrivateContext { + pub unconstrained fn private_at(&mut self, historical_block_number: u32) -> PrivateContext { if historical_block_number >= get_block_number() { self.advance_block_to(historical_block_number + 1); } @@ -72,12 +71,12 @@ impl TestEnvironment { PrivateContext::new(inputs, 0) } - unconstrained fn create_account(_self: Self) -> AztecAddress { + pub unconstrained fn create_account(_self: Self) -> AztecAddress { let test_account = cheatcodes::create_account(); test_account.address } - unconstrained fn create_account_contract(&mut self, secret: Field) -> AztecAddress { + pub unconstrained fn create_account_contract(&mut self, secret: Field) -> AztecAddress { let test_account = cheatcodes::add_account(secret); let address = test_account.address; cheatcodes::advance_blocks_by(1); @@ -91,7 +90,7 @@ impl TestEnvironment { address } - unconstrained fn deploy( + pub unconstrained fn deploy( _self: Self, path: str, name: str, @@ -99,11 +98,11 @@ impl TestEnvironment { Deployer { path, name, public_keys_hash: 0 } } - unconstrained fn deploy_self(_self: Self, name: str) -> Deployer<0, M> { + pub unconstrained fn deploy_self(_self: Self, name: str) -> Deployer<0, M> { Deployer { path: "", name, public_keys_hash: 0 } } - unconstrained fn assert_public_call_fails(_self: Self, call_interface: C) + pub unconstrained fn assert_public_call_fails(_self: Self, call_interface: C) where C: CallInterface, { @@ -118,7 +117,7 @@ impl TestEnvironment { ); } - unconstrained fn assert_private_call_fails(_self: Self, call_interface: C) + pub unconstrained fn assert_private_call_fails(_self: Self, call_interface: C) where C: CallInterface, { diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr index 6417053d353..cb48749b1f2 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr @@ -15,9 +15,9 @@ use crate::oracle::arguments::pack_arguments; use crate::oracle::execution::get_block_number; pub struct Deployer { - path: str, - name: str, - public_keys_hash: Field, + pub path: str, + pub name: str, + pub public_keys_hash: Field, } impl Deployer { @@ -118,8 +118,8 @@ impl Deployer { global TEST_ACCOUNT_LENGTH = PUBLIC_KEYS_LENGTH + 1; pub struct TestAccount { - address: AztecAddress, - keys: PublicKeys, + pub address: AztecAddress, + pub keys: PublicKeys, } impl Serialize for TestAccount { diff --git a/noir-projects/aztec-nr/aztec/src/test/mocks/mock_note.nr b/noir-projects/aztec-nr/aztec/src/test/mocks/mock_note.nr index 299204688a0..9f371ce0054 100644 --- a/noir-projects/aztec-nr/aztec/src/test/mocks/mock_note.nr +++ b/noir-projects/aztec-nr/aztec/src/test/mocks/mock_note.nr @@ -17,8 +17,8 @@ use dep::std::{embedded_curve_ops::multi_scalar_mul, hash::from_field_unsafe}; global MOCK_NOTE_LENGTH: u32 = 1; pub(crate) struct MockNote { - header: NoteHeader, - value: Field, + pub(crate) header: NoteHeader, + pub(crate) value: Field, } impl NullifiableNote for MockNote { @@ -107,28 +107,28 @@ impl Eq for MockNote { } } -pub struct MockNoteBuilder { +pub(crate) struct MockNoteBuilder { value: Field, contract_address: Option, storage_slot: Option, } impl MockNoteBuilder { - fn new(value: Field) -> Self { + pub(crate) fn new(value: Field) -> Self { MockNoteBuilder { value, contract_address: Option::none(), storage_slot: Option::none() } } - fn contract_address(&mut self, contract_address: AztecAddress) -> &mut Self { + pub(crate) fn contract_address(&mut self, contract_address: AztecAddress) -> &mut Self { self.contract_address = Option::some(contract_address); self } - fn storage_slot(&mut self, storage_slot: Field) -> &mut Self { + pub(crate) fn storage_slot(&mut self, storage_slot: Field) -> &mut Self { self.storage_slot = Option::some(storage_slot); self } - fn build(self) -> MockNote { + pub(crate) fn build(self) -> MockNote { let mut header = NoteHeader::empty(); if self.contract_address.is_some() { @@ -144,7 +144,7 @@ impl MockNoteBuilder { } impl MockNote { - pub fn new(value: Field) -> MockNoteBuilder { + pub(crate) fn new(value: Field) -> MockNoteBuilder { MockNoteBuilder::new(value) } } diff --git a/noir-projects/aztec-nr/aztec/src/test/mocks/mock_struct.nr b/noir-projects/aztec-nr/aztec/src/test/mocks/mock_struct.nr index 87015947beb..7c48a73260f 100644 --- a/noir-projects/aztec-nr/aztec/src/test/mocks/mock_struct.nr +++ b/noir-projects/aztec-nr/aztec/src/test/mocks/mock_struct.nr @@ -1,8 +1,8 @@ use dep::protocol_types::traits::{Deserialize, Serialize}; pub(crate) struct MockStruct { - a: Field, - b: Field, + pub(crate) a: Field, + pub(crate) b: Field, } impl MockStruct { diff --git a/noir-projects/aztec-nr/aztec/src/utils/comparison.nr b/noir-projects/aztec-nr/aztec/src/utils/comparison.nr index 2da17acce73..bbb54221c73 100644 --- a/noir-projects/aztec-nr/aztec/src/utils/comparison.nr +++ b/noir-projects/aztec-nr/aztec/src/utils/comparison.nr @@ -1,13 +1,13 @@ struct ComparatorEnum { - EQ: u8, - NEQ: u8, - LT: u8, - LTE: u8, - GT: u8, - GTE: u8, + pub EQ: u8, + pub NEQ: u8, + pub LT: u8, + pub LTE: u8, + pub GT: u8, + pub GTE: u8, } -global Comparator = ComparatorEnum { EQ: 1, NEQ: 2, LT: 3, LTE: 4, GT: 5, GTE: 6 }; +pub global Comparator = ComparatorEnum { EQ: 1, NEQ: 2, LT: 3, LTE: 4, GT: 5, GTE: 6 }; pub fn compare(lhs: Field, operation: u8, rhs: Field) -> bool { // Values are computed ahead of time because circuits evaluate all branches diff --git a/noir-projects/aztec-nr/aztec/src/utils/test.nr b/noir-projects/aztec-nr/aztec/src/utils/test.nr index c201e480a07..644a6baeafe 100644 --- a/noir-projects/aztec-nr/aztec/src/utils/test.nr +++ b/noir-projects/aztec-nr/aztec/src/utils/test.nr @@ -118,7 +118,8 @@ unconstrained fn verify_collapse_hints_dirty_storage() { let original = [Option::some(7), Option::none(), Option::some(3)]; let mut collapsed: BoundedVec = BoundedVec::from_array([7, 3]); - collapsed.storage[2] = 1; + // We have to use the unchecked setter as we're knowingly writing past the length, breaking its invariants. + collapsed.set_unchecked(2, 1); let collapsed_to_input_index_mapping = BoundedVec::from_array([0, 2]); diff --git a/noir-projects/mock-protocol-circuits/crates/mock-types/src/lib.nr b/noir-projects/mock-protocol-circuits/crates/mock-types/src/lib.nr index f9cecca0a4a..55155921155 100644 --- a/noir-projects/mock-protocol-circuits/crates/mock-types/src/lib.nr +++ b/noir-projects/mock-protocol-circuits/crates/mock-types/src/lib.nr @@ -90,8 +90,8 @@ impl PrivateKernelPublicInputsBuilder { fn finish(self) -> PrivateKernelPublicInputs { PrivateKernelPublicInputs { remaining_calls: self.remaining_calls, - commitments: self.commitments.storage, - read_requests: self.read_requests.storage, + commitments: self.commitments.storage(), + read_requests: self.read_requests.storage(), } } } diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/dapp_payload.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/dapp_payload.nr index 933fdcb6f2f..00e01f9b70d 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/dapp_payload.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/dapp_payload.nr @@ -49,7 +49,7 @@ impl DAppPayload { } bytes.extend_from_array(self.nonce.to_be_bytes::<32>()); - bytes.storage + bytes.storage() } // Executes all private and public calls diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr index fd11c9a9c5d..d188ebe78db 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr @@ -96,7 +96,7 @@ contract AppSubscription { assert(tx_count as u64 <= SUBSCRIPTION_TXS as u64); Token::at(storage.subscription_token_address.read_private()) - .transfer_from( + .transfer_in_private( context.msg_sender(), storage.subscription_recipient_address.read_private(), storage.subscription_price.read_private(), diff --git a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr index e80df65b8a3..bf1382bc773 100644 --- a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -640,9 +640,9 @@ contract AvmTest { let _ = l1_to_l2_msg_exists(1, 2); dep::aztec::oracle::debug_log::debug_log("send_l2_to_l1_msg"); let _ = send_l2_to_l1_msg(EthAddress::from_field(0x2020), 1); - dep::aztec::oracle::debug_log::debug_log("nested_call_to_add"); - let _ = nested_call_to_add(1, 2); - dep::aztec::oracle::debug_log::debug_log("nested_static_call_to_add"); - let _ = nested_static_call_to_add(1, 2); + //dep::aztec::oracle::debug_log::debug_log("nested_call_to_add"); + //let _ = nested_call_to_add(1, 2); + //dep::aztec::oracle::debug_log::debug_log("nested_static_call_to_add"); + //let _ = nested_static_call_to_add(1, 2); } } diff --git a/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr b/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr index 668c2c86e31..edaf81c7cc4 100644 --- a/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr @@ -52,7 +52,7 @@ contract Claim { // 4) Finally we mint the reward token to the sender of the transaction Token::at(storage.reward_token.read_private()) - .mint_public(recipient, proof_note.value) + .mint_to_public(recipient, proof_note.value) .enqueue(&mut context); } } diff --git a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr index 58122d06881..8464b960fb0 100644 --- a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr @@ -100,7 +100,7 @@ contract ContractClassRegisterer { public_bytecode_commitment, ], ); - emit_contract_class_unencrypted_log(&mut context, event.serialize()); + emit_contract_class_log(&mut context, event.serialize()); } #[private] @@ -143,7 +143,7 @@ contract ContractClassRegisterer { function_data.metadata_hash, ], ); - emit_contract_class_unencrypted_log(&mut context, event.serialize()); + emit_contract_class_log(&mut context, event.serialize()); } #[private] @@ -179,14 +179,11 @@ contract ContractClassRegisterer { function_data.metadata_hash, ], ); - emit_contract_class_unencrypted_log(&mut context, event.serialize()); + emit_contract_class_log(&mut context, event.serialize()); } #[contract_library_method] - fn emit_contract_class_unencrypted_log( - context: &mut PrivateContext, - log: [Field; N], - ) { + fn emit_contract_class_log(context: &mut PrivateContext, log: [Field; N]) { let contract_address = context.this_address(); let counter = context.next_counter(); @@ -203,7 +200,7 @@ contract ContractClassRegisterer { let log_hash = emit_contract_class_unencrypted_log_private(contract_address, log, counter); // 40 = addr (32) + raw log len (4) + processed log len (4) - context.unencrypted_logs_hashes.push( + context.contract_class_logs_hashes.push( LogHash { value: log_hash, counter, length: 40 + (N as Field) * 32 }, ); } diff --git a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr index 4ce03ebb6e1..44c129f8710 100644 --- a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr @@ -3,16 +3,14 @@ use dep::aztec::macros::aztec; #[aztec] contract ContractInstanceDeployer { use dep::aztec::{ - hash::compute_unencrypted_log_hash, macros::{events::event, functions::private}, - oracle::logs::emit_unencrypted_log_private, utils::to_bytes::arr_to_be_bytes_arr, }; use dep::aztec::protocol_types::{ - abis::log_hash::LogHash, address::{AztecAddress, PartialAddress, PublicKeysHash}, constants::DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE, contract_class_id::ContractClassId, + hash::sha256_to_field, public_keys::PublicKeys, traits::Serialize, }; @@ -119,20 +117,14 @@ contract ContractInstanceDeployer { let payload = event.serialize(); dep::aztec::oracle::debug_log::debug_log_format("ContractInstanceDeployed: {}", payload); - let contract_address = context.this_address(); - let counter = context.next_counter(); - // @todo This is very inefficient, we are doing a lot of back and forth conversions. let serialized_log = arr_to_be_bytes_arr(payload); - let log_hash = compute_unencrypted_log_hash(contract_address, serialized_log); - // 40 = addr (32) + raw log len (4) + processed log len (4) - let len = 40 + serialized_log.len().to_field(); - let side_effect = LogHash { value: log_hash, counter, length: len }; + let log_hash = sha256_to_field(serialized_log); - // We manually push the unencrypted log to the context and inform the execution environment about this because - // PrivateContext does not expose an `emit_unencrypted_log` method - this mechanism is considered error-prone - // and only some canonical contracts use it. - context.unencrypted_logs_hashes.push(side_effect); - emit_unencrypted_log_private(contract_address, payload, counter); + // Note: we are cheating a bit here because this is actually not encrypted + // but needs to be emitted from private, where we have removed unencrypted_logs, + // and has 15 fields (the max enc log len is 8). + // TODO(Miranda): split into 2 logs + context.emit_raw_event_log_with_masked_address(0, serialized_log, log_hash); } } diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index 92e89729e74..991b10c40a4 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -77,7 +77,7 @@ contract Crowdfunding { // 2) Transfer the donation tokens from donor to this contract let donor = context.msg_sender(); Token::at(storage.donation_token.read_private()) - .transfer_from(donor, context.this_address(), amount as Field, 0) + .transfer_in_private(donor, context.this_address(), amount as Field, 0) .call(&mut context); // docs:end:do-transfer // 3) Create a value note for the donor so that he can later on claim a rewards token in the Claim diff --git a/noir-projects/noir-contracts/contracts/fee_juice_contract/src/lib.nr b/noir-projects/noir-contracts/contracts/fee_juice_contract/src/lib.nr index 6f77d74b16e..35179d962e1 100644 --- a/noir-projects/noir-contracts/contracts/fee_juice_contract/src/lib.nr +++ b/noir-projects/noir-contracts/contracts/fee_juice_contract/src/lib.nr @@ -11,17 +11,19 @@ pub fn get_bridge_gas_msg_hash(owner: AztecAddress, amount: Field) -> Field { let recipient_bytes: [u8; 32] = owner.to_field().to_be_bytes(); let amount_bytes: [u8; 32] = amount.to_be_bytes(); + // The purpose of including the following selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. + let selector = comptime { std::hash::keccak256("claim(bytes32,uint256)".as_bytes(), 22) }; + + for i in 0..4 { + hash_bytes[i] = selector[i]; + } + for i in 0..32 { hash_bytes[i + 4] = recipient_bytes[i]; hash_bytes[i + 36] = amount_bytes[i]; } - // Function selector: 0x63f44968 keccak256('claim(bytes32,uint256)') - hash_bytes[0] = 0x63; - hash_bytes[1] = 0xf4; - hash_bytes[2] = 0x49; - hash_bytes[3] = 0x68; - let content_hash = sha256_to_field(hash_bytes); content_hash } diff --git a/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr index 9a9376abfc9..ab1ffdc4753 100644 --- a/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr @@ -58,7 +58,7 @@ contract FPC { #[internal] fn prepare_fee(from: AztecAddress, amount: Field, asset: AztecAddress, nonce: Field) { // docs:start:public_call - Token::at(asset).transfer_public(from, context.this_address(), amount, nonce).call( + Token::at(asset).transfer_in_public(from, context.this_address(), amount, nonce).call( &mut context, ); // docs:end:public_call @@ -69,7 +69,7 @@ contract FPC { fn pay_refund(refund_address: AztecAddress, amount: Field, asset: AztecAddress) { // Just do public refunds for the present let refund = compute_rebate(context, amount); - Token::at(asset).transfer_public(context.this_address(), refund_address, refund, 0).call( + Token::at(asset).transfer_in_public(context.this_address(), refund_address, refund, 0).call( &mut context, ); } diff --git a/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr b/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr index 938d403c803..b5781af3b20 100644 --- a/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr @@ -129,7 +129,7 @@ contract Lending { collateral_asset: AztecAddress, ) { let _ = Token::at(collateral_asset) - .transfer_public(context.msg_sender(), context.this_address(), amount, nonce) + .transfer_in_public(context.msg_sender(), context.this_address(), amount, nonce) .call(&mut context); let _ = Lending::at(context.this_address()) ._deposit(AztecAddress::from_field(on_behalf_of), amount, collateral_asset) @@ -199,7 +199,7 @@ contract Lending { // @todo @LHerskind Support both shielding and transfers (for now just transfer) let collateral_asset = storage.collateral_asset.read(); let _ = Token::at(collateral_asset) - .transfer_public(context.this_address(), recipient, amount, 0) + .transfer_in_public(context.this_address(), recipient, amount, 0) .call(&mut context); } @@ -248,7 +248,7 @@ contract Lending { // @todo @LHerskind Need to support both private and public minting. let stable_coin = storage.stable_coin.read(); - let _ = Token::at(stable_coin).mint_public(to, amount).call(&mut context); + let _ = Token::at(stable_coin).mint_to_public(to, amount).call(&mut context); } #[private] @@ -263,7 +263,7 @@ contract Lending { let on_behalf_of = compute_identifier(secret, on_behalf_of, context.msg_sender().to_field()); // docs:start:private_call - let _ = Token::at(stable_coin).burn(from, amount, nonce).call(&mut context); + let _ = Token::at(stable_coin).burn_private(from, amount, nonce).call(&mut context); // docs:end:private_call let _ = Lending::at(context.this_address()) ._repay(AztecAddress::from_field(on_behalf_of), amount, stable_coin) diff --git a/noir-projects/noir-contracts/contracts/nft_contract/src/main.nr b/noir-projects/noir-contracts/contracts/nft_contract/src/main.nr index 401e5b015ed..ccefcbef97f 100644 --- a/noir-projects/noir-contracts/contracts/nft_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/nft_contract/src/main.nr @@ -150,8 +150,8 @@ contract NFT { let nft = NFT::at(context.this_address()); - // We prepare the transfer. - let hiding_point_slot = _prepare_transfer_to_private(to, &mut context, storage); + // We prepare the private balance increase. + let hiding_point_slot = _prepare_private_balance_increase(to, &mut context, storage); // At last we finalize the transfer. Usafe of the `unsafe` method here is safe because we set the `from` // function argument to a message sender, guaranteeing that he can transfer only his own NFTs. @@ -160,20 +160,20 @@ contract NFT { ); } - /// Prepares a transfer to a private balance of `to`. The transfer then needs to be - /// finalized by calling `finalize_transfer_to_private`. Returns a hiding point slot. + /// Prepares an increase of private balance of `to` (partial note). The increase needs to be finalized by calling + /// `finalize_transfer_to_private. Returns a hiding point slot. #[private] - fn prepare_transfer_to_private(to: AztecAddress) -> Field { - _prepare_transfer_to_private(to, &mut context, storage) + fn prepare_private_balance_increase(to: AztecAddress) -> Field { + _prepare_private_balance_increase(to, &mut context, storage) } - /// This function exists separately from `prepare_transfer_to_private` solely as an optimization as it allows + /// This function exists separately from `prepare_private_balance_increase` solely as an optimization as it allows /// us to have it inlined in the `transfer_to_private` function which results in one less kernel iteration. /// /// TODO(#9180): Consider adding macro support for functions callable both as an entrypoint and as an internal /// function. #[contract_library_method] - fn _prepare_transfer_to_private( + fn _prepare_private_balance_increase( to: AztecAddress, context: &mut PrivateContext, storage: Storage<&mut PrivateContext>, @@ -235,7 +235,7 @@ contract NFT { } /// Finalizes a transfer of NFT with `token_id` from public balance of `from` to a private balance of `to`. - /// The transfer must be prepared by calling `prepare_transfer_to_private` first and the resulting + /// The transfer must be prepared by calling `prepare_private_balance_increase` first and the resulting /// `hiding_point_slot` must be passed as an argument to this function. #[public] fn finalize_transfer_to_private(token_id: Field, hiding_point_slot: Field) { diff --git a/noir-projects/noir-contracts/contracts/nft_contract/src/test/transfer_to_private.nr b/noir-projects/noir-contracts/contracts/nft_contract/src/test/transfer_to_private.nr index 742109682dc..03f59109aec 100644 --- a/noir-projects/noir-contracts/contracts/nft_contract/src/test/transfer_to_private.nr +++ b/noir-projects/noir-contracts/contracts/nft_contract/src/test/transfer_to_private.nr @@ -6,7 +6,7 @@ use dep::aztec::{ }; use std::test::OracleMock; -/// Internal orchestration means that the calls to `prepare_transfer_to_private` +/// Internal orchestration means that the calls to `prepare_private_balance_increase` /// and `finalize_transfer_to_private` are done by the NFT contract itself. /// In this test's case this is done by the `NFT::transfer_to_private(...)` function called /// in `utils::setup_mint_and_transfer_to_private`. @@ -40,7 +40,7 @@ unconstrained fn transfer_to_private_external_orchestration() { // We prepare the transfer let hiding_point_slot: Field = NFT::at(nft_contract_address) - .prepare_transfer_to_private(recipient) + .prepare_private_balance_increase(recipient) .call(&mut env.private()); // Finalize the transfer of the NFT (message sender owns the NFT in public) @@ -96,7 +96,7 @@ unconstrained fn transfer_to_private_failure_not_an_owner() { // as the NFT owner check is before we use the value but that would made the test less robust against changes // in the contract.) let hiding_point_slot: Field = NFT::at(nft_contract_address) - .prepare_transfer_to_private(not_owner) + .prepare_private_balance_increase(not_owner) .call(&mut env.private()); // Try transferring someone else's public NFT diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index 8b745370265..8a8091e6422 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -34,7 +34,7 @@ contract Test { utils::comparison::Comparator, }; use dep::token_portal_content_hash_lib::{ - get_mint_private_content_hash, get_mint_public_content_hash, + get_mint_to_private_content_hash, get_mint_to_public_content_hash, }; use dep::value_note::value_note::ValueNote; // TODO investigate why the macros require EmbeddedCurvePoint and EmbeddedCurveScalar @@ -372,29 +372,27 @@ contract Test { } #[public] - fn consume_mint_public_message( + fn consume_mint_to_public_message( to: AztecAddress, amount: Field, secret: Field, message_leaf_index: Field, portal_address: EthAddress, ) { - let content_hash = get_mint_public_content_hash(to, amount); + let content_hash = get_mint_to_public_content_hash(to, amount); // Consume message and emit nullifier context.consume_l1_to_l2_message(content_hash, secret, portal_address, message_leaf_index); } #[private] - fn consume_mint_private_message( - secret_hash_for_redeeming_minted_notes: Field, + fn consume_mint_to_private_message( amount: Field, secret_for_L1_to_L2_message_consumption: Field, portal_address: EthAddress, message_leaf_index: Field, ) { // Consume L1 to L2 message and emit nullifier - let content_hash = - get_mint_private_content_hash(secret_hash_for_redeeming_minted_notes, amount); + let content_hash = get_mint_to_private_content_hash(amount); context.consume_l1_to_l2_message( content_hash, secret_for_L1_to_L2_message_consumption, diff --git a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr index 4ef9953c938..0c20ba05832 100644 --- a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr @@ -9,10 +9,11 @@ use dep::aztec::macros::aztec; #[aztec] contract TokenBridge { - use dep::aztec::prelude::{AztecAddress, EthAddress, PublicMutable, SharedImmutable}; + use dep::aztec::prelude::{AztecAddress, EthAddress, SharedImmutable}; use dep::token_portal_content_hash_lib::{ - get_mint_private_content_hash, get_mint_public_content_hash, get_withdraw_content_hash, + get_mint_to_private_content_hash, get_mint_to_public_content_hash, + get_withdraw_content_hash, }; use dep::token::Token; @@ -27,7 +28,7 @@ contract TokenBridge { // Storage structure, containing all storage, and specifying what slots they use. #[storage] struct Storage { - token: PublicMutable, + token: SharedImmutable, portal_address: SharedImmutable, } @@ -35,7 +36,7 @@ contract TokenBridge { #[public] #[initializer] fn constructor(token: AztecAddress, portal_address: EthAddress) { - storage.token.write(token); + storage.token.initialize(token); storage.portal_address.initialize(portal_address); } // docs:end:token_bridge_storage_and_constructor @@ -54,7 +55,7 @@ contract TokenBridge { // Consumes a L1->L2 message and calls the token contract to mint the appropriate amount publicly #[public] fn claim_public(to: AztecAddress, amount: Field, secret: Field, message_leaf_index: Field) { - let content_hash = get_mint_public_content_hash(to, amount); + let content_hash = get_mint_to_public_content_hash(to, amount); // Consume message and emit nullifier context.consume_l1_to_l2_message( @@ -65,7 +66,7 @@ contract TokenBridge { ); // Mint tokens - Token::at(storage.token.read()).mint_public(to, amount).call(&mut context); + Token::at(storage.token.read_public()).mint_to_public(to, amount).call(&mut context); } // docs:end:claim_public @@ -84,25 +85,26 @@ contract TokenBridge { context.message_portal(storage.portal_address.read_public(), content); // Burn tokens - Token::at(storage.token.read()).burn_public(context.msg_sender(), amount, nonce).call( - &mut context, - ); + Token::at(storage.token.read_public()) + .burn_public(context.msg_sender(), amount, nonce) + .call(&mut context); } // docs:end:exit_to_l1_public + // docs:start:claim_private - // Consumes a L1->L2 message and calls the token contract to mint the appropriate amount in private assets - // User needs to call token.redeem_shield() to get the private assets - // TODO(#8416): Consider creating a truly private claim flow. + /// Claims the bridged tokens and makes them accessible in private. Note that recipient's address is not revealed + /// but the amount is. Hence it's most likely possible to determine to which L1 deposit this claim corresponds to + /// (unless there are multiple pending deposits of the same amount). + /// TODO(#8416): Consider creating a truly private claim flow. #[private] fn claim_private( - secret_hash_for_redeeming_minted_notes: Field, // secret hash used to redeem minted notes at a later time. This enables anyone to call this function and mint tokens to a user on their behalf + recipient: AztecAddress, // recipient of the bridged tokens amount: Field, secret_for_L1_to_L2_message_consumption: Field, // secret used to consume the L1 to L2 message message_leaf_index: Field, ) { // Consume L1 to L2 message and emit nullifier - let content_hash = - get_mint_private_content_hash(secret_hash_for_redeeming_minted_notes, amount); + let content_hash = get_mint_to_private_content_hash(amount); context.consume_l1_to_l2_message( content_hash, secret_for_L1_to_L2_message_consumption, @@ -110,13 +112,15 @@ contract TokenBridge { message_leaf_index, ); - // Mint tokens on L2 - // `mint_private` on token is public. So we call an internal public function - // which then calls the public method on the token contract. - // Since the secret_hash is passed, no secret is leaked. - TokenBridge::at(context.this_address()) - ._call_mint_on_token(amount, secret_hash_for_redeeming_minted_notes) - .enqueue(&mut context); + // Read the token address from storage + let token_address = storage.token.read_private(); + + // At last we mint the tokens + // docs:start:call_mint_on_token + Token::at(token_address).mint_to_private(context.msg_sender(), recipient, amount).call( + &mut context, + ); + // docs:end:call_mint_on_token } // docs:end:claim_private @@ -140,33 +144,25 @@ contract TokenBridge { TokenBridge::at(context.this_address())._assert_token_is_same(token).enqueue(&mut context); // docs:end:call_assert_token_is_same // Burn tokens - Token::at(token).burn(context.msg_sender(), amount, nonce).call(&mut context); + Token::at(token).burn_private(context.msg_sender(), amount, nonce).call(&mut context); } /// docs:end:exit_to_l1_private // docs:start:get_token #[public] #[view] fn get_token() -> AztecAddress { - storage.token.read() + storage.token.read_public() } // docs:end:get_token - // docs:start:call_mint_on_token - // This is a public call as we need to read from public storage. - // Also, note that user hashes their secret in private and only sends the hash in public - // meaning only user can `redeem_shield` at a later time with their secret. - #[public] - #[internal] - fn _call_mint_on_token(amount: Field, secret_hash: Field) { - Token::at(storage.token.read()).mint_private_old(amount, secret_hash).call(&mut context); - } - // docs:end:call_mint_on_token - // docs:start:assert_token_is_same #[public] #[internal] fn _assert_token_is_same(token: AztecAddress) { - assert(storage.token.read().eq(token), "Token address is not the same as seen in storage"); + assert( + storage.token.read_public().eq(token), + "Token address is not the same as seen in storage", + ); } // docs:end:assert_token_is_same } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr index 4492b78f1e8..e327690b2f1 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -22,11 +22,8 @@ contract Token { context::{PrivateCallInterface, PrivateContext}, encrypted_logs::{ encrypted_event_emission::encode_and_encrypt_event_unconstrained, - encrypted_note_emission::{ - encode_and_encrypt_note, encode_and_encrypt_note_unconstrained, - }, + encrypted_note_emission::encode_and_encrypt_note_unconstrained, }, - hash::compute_secret_hash, keys::getters::get_public_keys, macros::{ events::event, @@ -35,11 +32,9 @@ contract Token { }, oracle::random::random, prelude::{ - AztecAddress, FunctionSelector, Map, NoteGetterOptions, PrivateSet, PublicContext, - PublicMutable, SharedImmutable, + AztecAddress, FunctionSelector, Map, PublicContext, PublicMutable, SharedImmutable, }, protocol_types::{point::Point, traits::Serialize}, - utils::comparison::Comparator, }; use dep::uint_note::uint_note::UintNote; @@ -51,7 +46,7 @@ contract Token { }; // docs:end:import_authwit - use crate::types::{balance_set::BalanceSet, transparent_note::TransparentNote}; + use crate::types::balance_set::BalanceSet; // docs:end::imports @@ -85,9 +80,6 @@ contract Token { balances: Map, Context>, // docs:end:storage_balances total_supply: PublicMutable, - // docs:start:storage_pending_shields - pending_shields: PrivateSet, - // docs:end:storage_pending_shields public_balances: Map, Context>, symbol: SharedImmutable, name: SharedImmutable, @@ -111,6 +103,7 @@ contract Token { // docs:end:initialize_decimals } // docs:end:constructor + // docs:start:set_admin #[public] fn set_admin(new_admin: AztecAddress) { @@ -120,6 +113,7 @@ contract Token { // docs:end:write_admin } // docs:end:set_admin + #[public] #[view] fn public_get_name() -> FieldCompressedString { @@ -131,16 +125,19 @@ contract Token { fn private_get_name() -> FieldCompressedString { storage.name.read_private() } + #[public] #[view] fn public_get_symbol() -> pub FieldCompressedString { storage.symbol.read_public() } + #[private] #[view] fn private_get_symbol() -> pub FieldCompressedString { storage.symbol.read_private() } + #[public] #[view] fn public_get_decimals() -> pub u8 { @@ -155,6 +152,7 @@ contract Token { storage.decimals.read_private() // docs:end:read_decimals_private } + // docs:start:admin #[public] #[view] @@ -162,6 +160,7 @@ contract Token { storage.admin.read().to_field() } // docs:end:admin + // docs:start:is_minter #[public] #[view] @@ -169,6 +168,7 @@ contract Token { storage.minters.at(minter).read() } // docs:end:is_minter + // docs:start:total_supply #[public] #[view] @@ -176,6 +176,7 @@ contract Token { storage.total_supply.read().to_integer() } // docs:end:total_supply + // docs:start:balance_of_public #[public] #[view] @@ -183,6 +184,7 @@ contract Token { storage.public_balances.at(owner).read().to_integer() } // docs:end:balance_of_public + // docs:start:set_minter #[public] fn set_minter(minter: AztecAddress, approve: bool) { @@ -194,9 +196,10 @@ contract Token { // docs:end:write_minter } // docs:end:set_minter - // docs:start:mint_public + + // docs:start:mint_to_public #[public] - fn mint_public(to: AztecAddress, amount: Field) { + fn mint_to_public(to: AztecAddress, amount: Field) { // docs:start:read_minter assert(storage.minters.at(context.msg_sender()).read(), "caller is not minter"); // docs:end:read_minter @@ -206,41 +209,11 @@ contract Token { storage.public_balances.at(to).write(new_balance); storage.total_supply.write(supply); } - // docs:end:mint_public - // docs:start:mint_private - // TODO(benesjan): To be nuked in a followup PR. - #[public] - fn mint_private_old(amount: Field, secret_hash: Field) { - assert(storage.minters.at(context.msg_sender()).read(), "caller is not minter"); - let pending_shields = storage.pending_shields; - let mut note = TransparentNote::new(amount, secret_hash); - let supply = storage.total_supply.read().add(U128::from_integer(amount)); - storage.total_supply.write(supply); - // docs:start:insert_from_public - pending_shields.insert_from_public(&mut note); - // docs:end:insert_from_public - } - // docs:end:mint_private - // docs:start:shield - #[public] - fn shield(from: AztecAddress, amount: Field, secret_hash: Field, nonce: Field) { - if (!from.eq(context.msg_sender())) { - // The redeem is only spendable once, so we need to ensure that you cannot insert multiple shields from the same message. - assert_current_call_valid_authwit_public(&mut context, from); - } else { - assert(nonce == 0, "invalid nonce"); - } - let amount = U128::from_integer(amount); - let from_balance = storage.public_balances.at(from).read().sub(amount); - let pending_shields = storage.pending_shields; - let mut note = TransparentNote::new(amount.to_field(), secret_hash); - storage.public_balances.at(from).write(from_balance); - pending_shields.insert_from_public(&mut note); - } - // docs:end:shield - // docs:start:transfer_public + // docs:end:mint_to_public + + // docs:start:transfer_in_public #[public] - fn transfer_public(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { + fn transfer_in_public(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { if (!from.eq(context.msg_sender())) { assert_current_call_valid_authwit_public(&mut context, from); } else { @@ -252,7 +225,8 @@ contract Token { let to_balance = storage.public_balances.at(to).read().add(amount); storage.public_balances.at(to).write(to_balance); } - // docs:end:transfer_public + // docs:end:transfer_in_public + // docs:start:burn_public #[public] fn burn_public(from: AztecAddress, amount: Field, nonce: Field) { @@ -270,32 +244,7 @@ contract Token { storage.total_supply.write(new_supply); } // docs:end:burn_public - // docs:start:redeem_shield - #[private] - fn redeem_shield(to: AztecAddress, amount: Field, secret: Field) { - let secret_hash = compute_secret_hash(secret); - // Pop 1 note (set_limit(1)) which has an amount stored in a field with index 0 (select(0, amount)) and - // a secret_hash stored in a field with index 1 (select(1, secret_hash)). - let mut options = NoteGetterOptions::new(); - options = options - .select(TransparentNote::properties().amount, Comparator.EQ, amount) - .select(TransparentNote::properties().secret_hash, Comparator.EQ, secret_hash) - .set_limit(1); - let notes = storage.pending_shields.pop_notes(options); - assert(notes.len() == 1, "note not popped"); - // Add the token note to user's balances set - // Note: Using context.msg_sender() as a sender below makes this incompatible with escrows because we send - // outgoing logs to that address and to send outgoing logs you need to get a hold of ovsk_m. - let from = context.msg_sender(); - let from_ovpk_m = get_public_keys(from).ovpk_m; - storage.balances.at(to).add(to, U128::from_integer(amount)).emit(encode_and_encrypt_note( - &mut context, - from_ovpk_m, - to, - context.msg_sender(), - )); - } - // docs:end:redeem_shield + // docs:start:transfer_to_public #[private] fn transfer_to_public(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { @@ -314,6 +263,7 @@ contract Token { Token::at(context.this_address())._increase_public_balance(to, amount).enqueue(&mut context); } // docs:end:transfer_to_public + // docs:start:transfer #[private] fn transfer(to: AztecAddress, amount: Field) { @@ -347,7 +297,7 @@ contract Token { to, from, )); - // We don't constrain encryption of the note log in `transfer` (unlike in `transfer_from`) because the transfer + // We don't constrain encryption of the note log in `transfer` (unlike in `transfer_in_private`) because the transfer // function is only designed to be used in situations where the event is not strictly necessary (e.g. payment to // another person where the payment is considered to be successful when the other party successfully decrypts a // note). @@ -356,6 +306,7 @@ contract Token { ); } // docs:end:transfer + #[contract_library_method] fn subtract_balance( context: &mut PrivateContext, @@ -380,6 +331,7 @@ contract Token { compute_recurse_subtract_balance_call(*context, account, remaining).call(context) } } + // TODO(#7729): apply no_predicates to the contract interface method directly instead of having to use a wrapper // like we do here. #[no_predicates] @@ -391,6 +343,7 @@ contract Token { ) -> PrivateCallInterface<25, U128> { Token::at(context.this_address())._recurse_subtract_balance(account, remaining.to_field()) } + // TODO(#7728): even though the amount should be a U128, we can't have that type in a contract interface due to // serialization issues. #[internal] @@ -404,6 +357,7 @@ contract Token { RECURSIVE_TRANSFER_CALL_MAX_NOTES, ) } + /** * Cancel a private authentication witness. * @param inner_hash The inner hash of the authwit to cancel. @@ -416,9 +370,10 @@ contract Token { context.push_nullifier(nullifier); } // docs:end:cancel_authwit - // docs:start:transfer_from + + // docs:start:transfer_in_private #[private] - fn transfer_from(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { + fn transfer_in_private(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { // docs:start:assert_current_call_valid_authwit if (!from.eq(context.msg_sender())) { assert_current_call_valid_authwit(&mut context, from); @@ -450,10 +405,11 @@ contract Token { from, )); } - // docs:end:transfer_from - // docs:start:burn + // docs:end:transfer_in_private + + // docs:start:burn_private #[private] - fn burn(from: AztecAddress, amount: Field, nonce: Field) { + fn burn_private(from: AztecAddress, amount: Field, nonce: Field) { if (!from.eq(context.msg_sender())) { assert_current_call_valid_authwit(&mut context, from); } else { @@ -467,18 +423,18 @@ contract Token { ); Token::at(context.this_address())._reduce_total_supply(amount).enqueue(&mut context); } - // docs:end:burn + // docs:end:burn_private + // docs:start:transfer_to_private // Transfers token `amount` from public balance of message sender to a private balance of `to`. #[private] fn transfer_to_private(to: AztecAddress, amount: Field) { - // We check the minter permissions in the enqueued call as that allows us to avoid the need for `SharedMutable` - // which is less efficient. + // `from` is the owner of the public balance from which we'll subtract the `amount`. let from = context.msg_sender(); let token = Token::at(context.this_address()); - // We prepare the transfer. - let hiding_point_slot = _prepare_transfer_to_private(to, &mut context, storage); + // We prepare the private balance increase (the partial note). + let hiding_point_slot = _prepare_private_balance_increase(from, to, &mut context, storage); // At last we finalize the transfer. Usage of the `unsafe` method here is safe because we set the `from` // function argument to a message sender, guaranteeing that he can transfer only his own tokens. @@ -486,21 +442,25 @@ contract Token { &mut context, ); } + // docs:end:transfer_to_private - /// Prepares a transfer to a private balance of `to`. The transfer then needs to be - /// finalized by calling `finalize_transfer_to_private`. Returns a hiding point slot. + /// Prepares an increase of private balance of `to` (partial note). The increase needs to be finalized by calling + /// some of the finalization functions (`finalize_transfer_to_private`, `finalize_mint_to_private`). + /// Returns a hiding point slot. #[private] - fn prepare_transfer_to_private(to: AztecAddress) -> Field { - _prepare_transfer_to_private(to, &mut context, storage) + fn prepare_private_balance_increase(to: AztecAddress) -> Field { + let from = context.msg_sender(); + _prepare_private_balance_increase(from, to, &mut context, storage) } - /// This function exists separately from `prepare_transfer_to_private` solely as an optimization as it allows + /// This function exists separately from `prepare_private_balance_increase` solely as an optimization as it allows /// us to have it inlined in the `transfer_to_private` function which results in one less kernel iteration. /// /// TODO(#9180): Consider adding macro support for functions callable both as an entrypoint and as an internal /// function. #[contract_library_method] - fn _prepare_transfer_to_private( + fn _prepare_private_balance_increase( + from: AztecAddress, // recipient of the outgoing: TODO(#9887): this is not great? to: AztecAddress, context: &mut PrivateContext, storage: Storage<&mut PrivateContext>, @@ -513,10 +473,9 @@ contract Token { let note_randomness = unsafe { random() }; let note_setup_payload = UintNote::setup_payload().new(to, note_randomness, to_note_slot); - // We set the ovpk to the message sender's ovpk and we encrypt the log. - let from_ovpk = get_public_keys(context.msg_sender()).ovpk_m; - let setup_log = - note_setup_payload.encrypt_log(context, from_ovpk, to, context.msg_sender()); + // We get the keys and encrypt the log of the note + let from_ovpk = get_public_keys(from).ovpk_m; + let setup_log = note_setup_payload.encrypt_log(context, from_ovpk, to, from); // Using the x-coordinate as a hiding point slot is safe against someone else interfering with it because // we have a guarantee that the public functions of the transaction are executed right after the private ones @@ -546,7 +505,7 @@ contract Token { } /// Finalizes a transfer of token `amount` from public balance of `from` to a private balance of `to`. - /// The transfer must be prepared by calling `prepare_transfer_to_private` first and the resulting + /// The transfer must be prepared by calling `prepare_private_balance_increase` first and the resulting /// `hiding_point_slot` must be passed as an argument to this function. #[public] fn finalize_transfer_to_private(amount: Field, hiding_point_slot: Field) { @@ -587,27 +546,34 @@ contract Token { finalization_payload.emit(); } + // docs:start:mint_to_private /// Mints token `amount` to a private balance of `to`. Message sender has to have minter permissions (checked /// in the enqueud call). #[private] - fn mint_to_private(to: AztecAddress, amount: Field) { - let from = context.msg_sender(); + fn mint_to_private( + from: AztecAddress, // recipient of the outgoing: TODO(#9887): this is not great? + to: AztecAddress, + amount: Field, + ) { let token = Token::at(context.this_address()); - // We prepare the transfer. - let hiding_point_slot = _prepare_transfer_to_private(to, &mut context, storage); + // We prepare the partial note to which we'll "send" the minted amount. + let hiding_point_slot = _prepare_private_balance_increase(from, to, &mut context, storage); // At last we finalize the mint. Usage of the `unsafe` method here is safe because we set the `from` // function argument to a message sender, guaranteeing that only a message sender with minter permissions // can successfully execute the function. - token._finalize_mint_to_private_unsafe(from, amount, hiding_point_slot).enqueue(&mut context); + token + ._finalize_mint_to_private_unsafe(context.msg_sender(), amount, hiding_point_slot) + .enqueue(&mut context); } + // docs:end:mint_to_private /// Finalizes a mint of token `amount` to a private balance of `to`. The mint must be prepared by calling - /// `prepare_transfer_to_private` first and the resulting + /// `prepare_private_balance_increase` first and the resulting /// `hiding_point_slot` must be passed as an argument to this function. /// - /// Note: This function is only an optimization as it could be replaced by a combination of `mint_public` + /// Note: This function is only an optimization as it could be replaced by a combination of `mint_to_public` /// and `finalize_transfer_to_private`. It is however used very commonly so it makes sense to optimize it /// (e.g. used during token bridging, in AMM liquidity token etc.). #[public] @@ -701,62 +667,14 @@ contract Token { user, )); - // 4. Now we get the partial payloads - // TODO(#7775): Manually fetching the randomness here is not great. If we decide to include randomness in all - // notes we could just inject it in macros. - let fee_payer_randomness = unsafe { random() }; - let user_randomness = unsafe { random() }; - - let fee_payer_setup_payload = UintNote::setup_payload().new( - fee_payer, - fee_payer_randomness, - storage.balances.at(fee_payer).set.storage_slot, - ); - - let user_setup_payload = UintNote::setup_payload().new( - user, - user_randomness, - storage.balances.at(user).set.storage_slot, - ); - - // 5. We get transient storage slots - // Using the x-coordinate as a hiding point slot is safe against someone else interfering with it because - // we have a guarantee that the public functions of the transaction are executed right after the private ones - // and for this reason the protocol guarantees that nobody can front-run us in consuming the hiding point. - // This guarantee would break if `finalize_transfer_to_private` was not called in the same transaction. This - // however is not the flow we are currently concerned with. To support the multi-transaction flow we could - // introduce a `from` function argument, hash the x-coordinate with it and then repeat the hashing in - // `finalize_transfer_to_private`. - // - // We can also be sure that the `hiding_point_slot` will not overwrite any other value in the storage because - // in our state variables we derive slots using a different hash function from multi scalar multiplication - // (MSM). - let fee_payer_point_slot = fee_payer_setup_payload.hiding_point.x; - let user_point_slot = user_setup_payload.hiding_point.x; - - // 6. We compute setup logs - let fee_payer_setup_log = - fee_payer_setup_payload.encrypt_log(&mut context, user_ovpk, fee_payer, fee_payer); - let user_setup_log = - user_setup_payload.encrypt_log(&mut context, user_ovpk, user, fee_payer); - - // 7. We store the hiding points an logs in transients storage - Token::at(context.this_address()) - ._store_payload_in_transient_storage_unsafe( - fee_payer_point_slot, - fee_payer_setup_payload.hiding_point, - fee_payer_setup_log, - ) - .enqueue(&mut context); - Token::at(context.this_address()) - ._store_payload_in_transient_storage_unsafe( - user_point_slot, - user_setup_payload.hiding_point, - user_setup_log, - ) - .enqueue(&mut context); + // 4. We prepare the partial notes + // TODO(#9887): In each `_prepare_private_balance_increase` call we fetch the user's ovpk_m 2 more times. This is + // very inefficient. + let fee_payer_point_slot = + _prepare_private_balance_increase(user, fee_payer, &mut context, storage); + let user_point_slot = _prepare_private_balance_increase(user, user, &mut context, storage); - // 8. Set the public teardown function to `complete_refund(...)`. Public teardown is the only time when a public + // 5. Set the public teardown function to `complete_refund(...)`. Public teardown is the only time when a public // function has access to the final transaction fee, which is needed to compute the actual refund amount. context.set_public_teardown_function( context.this_address(), @@ -822,6 +740,7 @@ contract Token { storage.public_balances.at(to).write(new_balance); } // docs:end:increase_public_balance + // docs:start:reduce_total_supply #[public] #[internal] @@ -831,6 +750,7 @@ contract Token { storage.total_supply.write(new_supply); } // docs:end:reduce_total_supply + /// Unconstrained /// // docs:start:balance_of_private pub(crate) unconstrained fn balance_of_private(owner: AztecAddress) -> pub Field { diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test.nr index 35a4c1f1aff..1ed2b177ced 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test.nr @@ -1,11 +1,12 @@ mod access_control; -mod burn; -mod utils; -mod transfer_public; -mod transfer_private; +mod burn_private; +mod burn_public; +mod mint_to_public; +mod reading_constants; +mod refunds; +mod transfer; +mod transfer_in_private; +mod transfer_in_public; mod transfer_to_private; mod transfer_to_public; -mod refunds; -mod minting; -mod reading_constants; -mod shielding; +mod utils; diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/burn.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/burn.nr deleted file mode 100644 index 151ef95a506..00000000000 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/burn.nr +++ /dev/null @@ -1,188 +0,0 @@ -use crate::test::utils; -use crate::Token; -use dep::authwit::cheatcodes as authwit_cheatcodes; -use dep::aztec::oracle::random::random; - -#[test] -unconstrained fn burn_public_success() { - let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ false); - let burn_amount = mint_amount / 10; - - // Burn less than balance - Token::at(token_contract_address).burn_public(owner, burn_amount, 0).call(&mut env.public()); - utils::check_public_balance(token_contract_address, owner, mint_amount - burn_amount); -} - -#[test] -unconstrained fn burn_public_on_behalf_of_other() { - let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); - let burn_amount = mint_amount / 10; - - // Burn on behalf of other - let burn_call_interface = - Token::at(token_contract_address).burn_public(owner, burn_amount, random()); - authwit_cheatcodes::add_public_authwit_from_call_interface( - owner, - recipient, - burn_call_interface, - ); - // Impersonate recipient to perform the call - env.impersonate(recipient); - // Burn tokens - burn_call_interface.call(&mut env.public()); - utils::check_public_balance(token_contract_address, owner, mint_amount - burn_amount); -} - -#[test(should_fail_with = "attempt to subtract with underflow")] -unconstrained fn burn_public_failure_more_than_balance() { - let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ false); - - // Burn more than balance - let burn_amount = mint_amount * 10; - // Try to burn - Token::at(token_contract_address).burn_public(owner, burn_amount, 0).call(&mut env.public()); -} - -#[test(should_fail_with = "invalid nonce")] -unconstrained fn burn_public_failure_on_behalf_of_self_non_zero_nonce() { - let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ false); - - // Burn on behalf of self with non-zero nonce - let burn_amount = mint_amount / 10; - // Try to burn - Token::at(token_contract_address).burn_public(owner, burn_amount, random()).call( - &mut env.public(), - ); -} - -#[test(should_fail_with = "unauthorized")] -unconstrained fn burn_public_failure_on_behalf_of_other_without_approval() { - let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); - - // Burn on behalf of other without approval - let burn_amount = mint_amount / 10; - let burn_call_interface = - Token::at(token_contract_address).burn_public(owner, burn_amount, random()); - // Impersonate recipient to perform the call - env.impersonate(recipient); - burn_call_interface.call(&mut env.public()); -} - -#[test(should_fail_with = "unauthorized")] -unconstrained fn burn_public_failure_on_behalf_of_other_wrong_caller() { - let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); - - // Burn on behalf of other, wrong designated caller - let burn_amount = mint_amount / 10; - let burn_call_interface = - Token::at(token_contract_address).burn_public(owner, burn_amount, random()); - authwit_cheatcodes::add_public_authwit_from_call_interface(owner, owner, burn_call_interface); - // Impersonate recipient to perform the call - env.impersonate(recipient); - burn_call_interface.call(&mut env.public()); -} - -#[test] -unconstrained fn burn_private_on_behalf_of_self() { - let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ false); - let burn_amount = mint_amount / 10; - - // Burn less than balance - Token::at(token_contract_address).burn(owner, burn_amount, 0).call(&mut env.private()); - utils::check_private_balance(token_contract_address, owner, mint_amount - burn_amount); -} - -#[test] -unconstrained fn burn_private_on_behalf_of_other() { - let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ true); - let burn_amount = mint_amount / 10; - - // Burn on behalf of other - let burn_call_interface = Token::at(token_contract_address).burn(owner, burn_amount, random()); - authwit_cheatcodes::add_private_authwit_from_call_interface( - owner, - recipient, - burn_call_interface, - ); - // Impersonate recipient to perform the call - env.impersonate(recipient); - // Burn tokens - burn_call_interface.call(&mut env.private()); - utils::check_private_balance(token_contract_address, owner, mint_amount - burn_amount); -} - -#[test(should_fail_with = "Balance too low")] -unconstrained fn burn_private_failure_more_than_balance() { - let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ false); - - // Burn more than balance - let burn_amount = mint_amount * 10; - Token::at(token_contract_address).burn(owner, burn_amount, 0).call(&mut env.private()); -} - -#[test(should_fail_with = "invalid nonce")] -unconstrained fn burn_private_failure_on_behalf_of_self_non_zero_nonce() { - let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ false); - - // Burn more than balance - let burn_amount = mint_amount / 10; - Token::at(token_contract_address).burn(owner, burn_amount, random()).call(&mut env.private()); -} - -#[test(should_fail_with = "Balance too low")] -unconstrained fn burn_private_failure_on_behalf_of_other_more_than_balance() { - let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); - - // Burn more than balance - let burn_amount = mint_amount * 10; - // Burn on behalf of other - let burn_call_interface = Token::at(token_contract_address).burn(owner, burn_amount, random()); - authwit_cheatcodes::add_private_authwit_from_call_interface( - owner, - recipient, - burn_call_interface, - ); - // Impersonate recipient to perform the call - env.impersonate(recipient); - burn_call_interface.call(&mut env.private()); -} - -#[test(should_fail_with = "Authorization not found for message hash")] -unconstrained fn burn_private_failure_on_behalf_of_other_without_approval() { - let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); - - // Burn more than balance - let burn_amount = mint_amount / 10; - // Burn on behalf of other - let burn_call_interface = Token::at(token_contract_address).burn(owner, burn_amount, 3); - // Impersonate recipient to perform the call - env.impersonate(recipient); - burn_call_interface.call(&mut env.private()); -} - -#[test(should_fail_with = "Authorization not found for message hash")] -unconstrained fn burn_private_failure_on_behalf_of_other_wrong_designated_caller() { - let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); - - // Burn more than balance - let burn_amount = mint_amount / 10; - // Burn on behalf of other - let burn_call_interface = Token::at(token_contract_address).burn(owner, burn_amount, 3); - authwit_cheatcodes::add_private_authwit_from_call_interface(owner, owner, burn_call_interface); - // Impersonate recipient to perform the call - env.impersonate(recipient); - burn_call_interface.call(&mut env.private()); -} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/burn_private.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/burn_private.nr new file mode 100644 index 00000000000..a3ac58f79a1 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/burn_private.nr @@ -0,0 +1,107 @@ +use crate::test::utils; +use crate::Token; +use dep::authwit::cheatcodes as authwit_cheatcodes; +use dep::aztec::oracle::random::random; + +#[test] +unconstrained fn burn_private_on_behalf_of_self() { + let (env, token_contract_address, owner, _, mint_amount) = + utils::setup_and_mint_to_private(/* with_account_contracts */ false); + let burn_amount = mint_amount / 10; + + // Burn less than balance + Token::at(token_contract_address).burn_private(owner, burn_amount, 0).call(&mut env.private()); + utils::check_private_balance(token_contract_address, owner, mint_amount - burn_amount); +} + +#[test] +unconstrained fn burn_private_on_behalf_of_other() { + let (env, token_contract_address, owner, recipient, mint_amount) = + utils::setup_and_mint_to_private(/* with_account_contracts */ true); + let burn_amount = mint_amount / 10; + + // Burn on behalf of other + let burn_call_interface = + Token::at(token_contract_address).burn_private(owner, burn_amount, random()); + authwit_cheatcodes::add_private_authwit_from_call_interface( + owner, + recipient, + burn_call_interface, + ); + // Impersonate recipient to perform the call + env.impersonate(recipient); + // Burn tokens + burn_call_interface.call(&mut env.private()); + utils::check_private_balance(token_contract_address, owner, mint_amount - burn_amount); +} + +#[test(should_fail_with = "Balance too low")] +unconstrained fn burn_private_failure_more_than_balance() { + let (env, token_contract_address, owner, _, mint_amount) = + utils::setup_and_mint_to_public(/* with_account_contracts */ false); + + // Burn more than balance + let burn_amount = mint_amount * 10; + Token::at(token_contract_address).burn_private(owner, burn_amount, 0).call(&mut env.private()); +} + +#[test(should_fail_with = "invalid nonce")] +unconstrained fn burn_private_failure_on_behalf_of_self_non_zero_nonce() { + let (env, token_contract_address, owner, _, mint_amount) = + utils::setup_and_mint_to_public(/* with_account_contracts */ false); + + // Burn more than balance + let burn_amount = mint_amount / 10; + Token::at(token_contract_address).burn_private(owner, burn_amount, random()).call( + &mut env.private(), + ); +} + +#[test(should_fail_with = "Balance too low")] +unconstrained fn burn_private_failure_on_behalf_of_other_more_than_balance() { + let (env, token_contract_address, owner, recipient, mint_amount) = + utils::setup_and_mint_to_public(/* with_account_contracts */ true); + + // Burn more than balance + let burn_amount = mint_amount * 10; + // Burn on behalf of other + let burn_call_interface = + Token::at(token_contract_address).burn_private(owner, burn_amount, random()); + authwit_cheatcodes::add_private_authwit_from_call_interface( + owner, + recipient, + burn_call_interface, + ); + // Impersonate recipient to perform the call + env.impersonate(recipient); + burn_call_interface.call(&mut env.private()); +} + +#[test(should_fail_with = "Authorization not found for message hash")] +unconstrained fn burn_private_failure_on_behalf_of_other_without_approval() { + let (env, token_contract_address, owner, recipient, mint_amount) = + utils::setup_and_mint_to_public(/* with_account_contracts */ true); + + // Burn more than balance + let burn_amount = mint_amount / 10; + // Burn on behalf of other + let burn_call_interface = Token::at(token_contract_address).burn_private(owner, burn_amount, 3); + // Impersonate recipient to perform the call + env.impersonate(recipient); + burn_call_interface.call(&mut env.private()); +} + +#[test(should_fail_with = "Authorization not found for message hash")] +unconstrained fn burn_private_failure_on_behalf_of_other_wrong_designated_caller() { + let (env, token_contract_address, owner, recipient, mint_amount) = + utils::setup_and_mint_to_public(/* with_account_contracts */ true); + + // Burn more than balance + let burn_amount = mint_amount / 10; + // Burn on behalf of other + let burn_call_interface = Token::at(token_contract_address).burn_private(owner, burn_amount, 3); + authwit_cheatcodes::add_private_authwit_from_call_interface(owner, owner, burn_call_interface); + // Impersonate recipient to perform the call + env.impersonate(recipient); + burn_call_interface.call(&mut env.private()); +} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/burn_public.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/burn_public.nr new file mode 100644 index 00000000000..1d427ff30ff --- /dev/null +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/burn_public.nr @@ -0,0 +1,89 @@ +use crate::test::utils; +use crate::Token; +use dep::authwit::cheatcodes as authwit_cheatcodes; +use dep::aztec::oracle::random::random; + +#[test] +unconstrained fn burn_public_success() { + let (env, token_contract_address, owner, recipient, mint_amount) = + utils::setup_and_mint_to_public(/* with_account_contracts */ false); + let burn_amount = mint_amount / 10; + + // Burn less than balance + Token::at(token_contract_address).burn_public(owner, burn_amount, 0).call(&mut env.public()); + utils::check_public_balance(token_contract_address, owner, mint_amount - burn_amount); +} + +#[test] +unconstrained fn burn_public_on_behalf_of_other() { + let (env, token_contract_address, owner, recipient, mint_amount) = + utils::setup_and_mint_to_public(/* with_account_contracts */ true); + let burn_amount = mint_amount / 10; + + // Burn on behalf of other + let burn_call_interface = + Token::at(token_contract_address).burn_public(owner, burn_amount, random()); + authwit_cheatcodes::add_public_authwit_from_call_interface( + owner, + recipient, + burn_call_interface, + ); + // Impersonate recipient to perform the call + env.impersonate(recipient); + // Burn tokens + burn_call_interface.call(&mut env.public()); + utils::check_public_balance(token_contract_address, owner, mint_amount - burn_amount); +} + +#[test(should_fail_with = "attempt to subtract with underflow")] +unconstrained fn burn_public_failure_more_than_balance() { + let (env, token_contract_address, owner, _, mint_amount) = + utils::setup_and_mint_to_public(/* with_account_contracts */ false); + + // Burn more than balance + let burn_amount = mint_amount * 10; + // Try to burn + Token::at(token_contract_address).burn_public(owner, burn_amount, 0).call(&mut env.public()); +} + +#[test(should_fail_with = "invalid nonce")] +unconstrained fn burn_public_failure_on_behalf_of_self_non_zero_nonce() { + let (env, token_contract_address, owner, _, mint_amount) = + utils::setup_and_mint_to_public(/* with_account_contracts */ false); + + // Burn on behalf of self with non-zero nonce + let burn_amount = mint_amount / 10; + // Try to burn + Token::at(token_contract_address).burn_public(owner, burn_amount, random()).call( + &mut env.public(), + ); +} + +#[test(should_fail_with = "unauthorized")] +unconstrained fn burn_public_failure_on_behalf_of_other_without_approval() { + let (env, token_contract_address, owner, recipient, mint_amount) = + utils::setup_and_mint_to_public(/* with_account_contracts */ true); + + // Burn on behalf of other without approval + let burn_amount = mint_amount / 10; + let burn_call_interface = + Token::at(token_contract_address).burn_public(owner, burn_amount, random()); + // Impersonate recipient to perform the call + env.impersonate(recipient); + burn_call_interface.call(&mut env.public()); +} + +#[test(should_fail_with = "unauthorized")] +unconstrained fn burn_public_failure_on_behalf_of_other_wrong_caller() { + let (env, token_contract_address, owner, recipient, mint_amount) = + utils::setup_and_mint_to_public(/* with_account_contracts */ true); + + // Burn on behalf of other, wrong designated caller + let burn_amount = mint_amount / 10; + let burn_call_interface = + Token::at(token_contract_address).burn_public(owner, burn_amount, random()); + authwit_cheatcodes::add_public_authwit_from_call_interface(owner, owner, burn_call_interface); + // Impersonate recipient to perform the call + env.impersonate(recipient); + burn_call_interface.call(&mut env.public()); +} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/minting.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/mint_to_public.nr similarity index 58% rename from noir-projects/noir-contracts/contracts/token_contract/src/test/minting.nr rename to noir-projects/noir-contracts/contracts/token_contract/src/test/mint_to_public.nr index bc4f877d2a3..c4cb9055ac0 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/minting.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/mint_to_public.nr @@ -1,14 +1,12 @@ -use crate::test::utils; -use crate::{Token, types::transparent_note::TransparentNote}; -use dep::aztec::{oracle::random::random, test::helpers::cheatcodes}; +use crate::{test::utils, Token}; #[test] -unconstrained fn mint_public_success() { +unconstrained fn mint_to_public_success() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, _) = utils::setup(/* with_account_contracts */ false); let mint_amount = 10000; - Token::at(token_contract_address).mint_public(owner, mint_amount).call(&mut env.public()); + Token::at(token_contract_address).mint_to_public(owner, mint_amount).call(&mut env.public()); utils::check_public_balance(token_contract_address, owner, mint_amount); @@ -17,7 +15,7 @@ unconstrained fn mint_public_success() { } #[test] -unconstrained fn mint_public_failures() { +unconstrained fn mint_to_public_failures() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, recipient) = utils::setup(/* with_account_contracts */ false); @@ -25,9 +23,9 @@ unconstrained fn mint_public_failures() { // As non-minter let mint_amount = 10000; env.impersonate(recipient); - let mint_public_call_interface = - Token::at(token_contract_address).mint_public(owner, mint_amount); - env.assert_public_call_fails(mint_public_call_interface); + let mint_to_public_call_interface = + Token::at(token_contract_address).mint_to_public(owner, mint_amount); + env.assert_public_call_fails(mint_to_public_call_interface); utils::check_public_balance(token_contract_address, owner, 0); @@ -35,23 +33,23 @@ unconstrained fn mint_public_failures() { // Overflow recipient let mint_amount = 2.pow_32(128); - let mint_public_call_interface = - Token::at(token_contract_address).mint_public(owner, mint_amount); - env.assert_public_call_fails(mint_public_call_interface); + let mint_to_public_call_interface = + Token::at(token_contract_address).mint_to_public(owner, mint_amount); + env.assert_public_call_fails(mint_to_public_call_interface); utils::check_public_balance(token_contract_address, owner, 0); // Overflow total supply let mint_for_recipient_amount = 1000; - Token::at(token_contract_address).mint_public(recipient, mint_for_recipient_amount).call( + Token::at(token_contract_address).mint_to_public(recipient, mint_for_recipient_amount).call( &mut env.public(), ); let mint_amount = 2.pow_32(128) - mint_for_recipient_amount; - let mint_public_call_interface = - Token::at(token_contract_address).mint_public(owner, mint_amount); - env.assert_public_call_fails(mint_public_call_interface); + let mint_to_public_call_interface = + Token::at(token_contract_address).mint_to_public(owner, mint_amount); + env.assert_public_call_fails(mint_to_public_call_interface); utils::check_public_balance(token_contract_address, recipient, mint_for_recipient_amount); utils::check_public_balance(token_contract_address, owner, 0); diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/refunds.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/refunds.nr index 2990163baae..d326fe250be 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/refunds.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/refunds.nr @@ -7,7 +7,7 @@ use std::test::OracleMock; #[test] unconstrained fn setup_refund_success() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_private(true); + utils::setup_and_mint_to_private(true); // Renaming owner and recipient to match naming in Token let user = owner; @@ -65,7 +65,7 @@ unconstrained fn setup_refund_success() { #[test(should_fail_with = "Balance too low")] unconstrained fn setup_refund_insufficient_funded_amount() { let (env, token_contract_address, owner, recipient, _mint_amount) = - utils::setup_and_mint_private(true); + utils::setup_and_mint_to_private(true); // Renaming owner and recipient to match naming in Token let user = owner; diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/shielding.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/shielding.nr deleted file mode 100644 index aef1d98f9cc..00000000000 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/shielding.nr +++ /dev/null @@ -1,179 +0,0 @@ -use crate::test::utils; -use crate::{Token, types::transparent_note::TransparentNote}; -use dep::authwit::cheatcodes as authwit_cheatcodes; -use dep::aztec::{hash::compute_secret_hash, oracle::random::random}; - -#[test] -unconstrained fn shielding_on_behalf_of_self() { - // Setup without account contracts. We are not using authwits here, so dummy accounts are enough - let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ false); - let secret = random(); - let secret_hash = compute_secret_hash(secret); - // Shield tokens - let shield_amount = mint_amount / 10; - Token::at(token_contract_address).shield(owner, shield_amount, secret_hash, 0).call( - &mut env.public(), - ); - - // We need to manually add the note to TXE because `TransparentNote` does not support automatic note log delivery. - env.add_note( - &mut TransparentNote::new(shield_amount, secret_hash), - Token::storage_layout().pending_shields.slot, - token_contract_address, - ); - - // Redeem our shielded tokens - Token::at(token_contract_address).redeem_shield(owner, shield_amount, secret).call( - &mut env.private(), - ); - - // Check balances - utils::check_public_balance(token_contract_address, owner, mint_amount - shield_amount); - utils::check_private_balance(token_contract_address, owner, shield_amount); -} - -#[test] -unconstrained fn shielding_on_behalf_of_other() { - let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); - let secret = random(); - let secret_hash = compute_secret_hash(secret); - - // Shield tokens on behalf of owner - let shield_amount = 1000; - let shield_call_interface = - Token::at(token_contract_address).shield(owner, shield_amount, secret_hash, 0); - authwit_cheatcodes::add_public_authwit_from_call_interface( - owner, - recipient, - shield_call_interface, - ); - // Impersonate recipient to perform the call - env.impersonate(recipient); - // Shield tokens - shield_call_interface.call(&mut env.public()); - - // Become owner again - env.impersonate(owner); - // We need to manually add the note to TXE because `TransparentNote` does not support automatic note log delivery. - env.add_note( - &mut TransparentNote::new(shield_amount, secret_hash), - Token::storage_layout().pending_shields.slot, - token_contract_address, - ); - - // Redeem our shielded tokens - Token::at(token_contract_address).redeem_shield(owner, shield_amount, secret).call( - &mut env.private(), - ); - - // Check balances - utils::check_public_balance(token_contract_address, owner, mint_amount - shield_amount); - utils::check_private_balance(token_contract_address, owner, shield_amount); -} - -#[test] -unconstrained fn shielding_failure_on_behalf_of_self_more_than_balance() { - // Setup without account contracts. We are not using authwits here, so dummy accounts are enough - let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); - let secret = random(); - let secret_hash = compute_secret_hash(secret); - // Shield tokens - let shield_amount = mint_amount + 1; - let shield_call_interface = - Token::at(token_contract_address).shield(owner, shield_amount, secret_hash, 0); - env.assert_public_call_fails(shield_call_interface); - - // Check balances - utils::check_public_balance(token_contract_address, owner, mint_amount); - utils::check_private_balance(token_contract_address, owner, 0); -} - -#[test] -unconstrained fn shielding_failure_on_behalf_of_self_invalid_nonce() { - // Setup without account contracts. We are not using authwits here, so dummy accounts are enough - let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); - let secret = random(); - let secret_hash = compute_secret_hash(secret); - // Shield tokens - let shield_amount = mint_amount / 10; - let shield_call_interface = - Token::at(token_contract_address).shield(owner, shield_amount, secret_hash, random()); - env.assert_public_call_fails(shield_call_interface); - - // Check balances - utils::check_public_balance(token_contract_address, owner, mint_amount); - utils::check_private_balance(token_contract_address, owner, 0); -} - -#[test] -unconstrained fn shielding_failure_on_behalf_of_other_more_than_balance() { - // Setup without account contracts. We are not using authwits here, so dummy accounts are enough - let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); - let secret = random(); - let secret_hash = compute_secret_hash(secret); - // Shield tokens on behalf of owner - let shield_amount = mint_amount + 1; - let shield_call_interface = - Token::at(token_contract_address).shield(owner, shield_amount, secret_hash, 0); - authwit_cheatcodes::add_public_authwit_from_call_interface( - owner, - recipient, - shield_call_interface, - ); - // Impersonate recipient to perform the call - env.impersonate(recipient); - // Shield tokens - env.assert_public_call_fails(shield_call_interface); - - // Check balances - utils::check_public_balance(token_contract_address, owner, mint_amount); - utils::check_private_balance(token_contract_address, owner, 0); -} - -#[test] -unconstrained fn shielding_failure_on_behalf_of_other_wrong_caller() { - // Setup without account contracts. We are not using authwits here, so dummy accounts are enough - let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); - let secret = random(); - let secret_hash = compute_secret_hash(secret); - // Shield tokens on behalf of owner - let shield_amount = mint_amount + 1; - let shield_call_interface = - Token::at(token_contract_address).shield(owner, shield_amount, secret_hash, 0); - authwit_cheatcodes::add_public_authwit_from_call_interface(owner, owner, shield_call_interface); - // Impersonate recipient to perform the call - env.impersonate(recipient); - // Shield tokens - env.assert_public_call_fails(shield_call_interface); - - // Check balances - utils::check_public_balance(token_contract_address, owner, mint_amount); - utils::check_private_balance(token_contract_address, owner, 0); -} - -#[test] -unconstrained fn shielding_failure_on_behalf_of_other_without_approval() { - // Setup without account contracts. We are not using authwits here, so dummy accounts are enough - let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); - let secret = random(); - let secret_hash = compute_secret_hash(secret); - // Shield tokens on behalf of owner - let shield_amount = mint_amount + 1; - let shield_call_interface = - Token::at(token_contract_address).shield(owner, shield_amount, secret_hash, 0); - // Impersonate recipient to perform the call - env.impersonate(recipient); - // Shield tokens - env.assert_public_call_fails(shield_call_interface); - - // Check balances - utils::check_public_balance(token_contract_address, owner, mint_amount); - utils::check_private_balance(token_contract_address, owner, 0); -} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer.nr new file mode 100644 index 00000000000..24015869d66 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer.nr @@ -0,0 +1,64 @@ +use crate::test::utils; +use crate::Token; +use dep::authwit::cheatcodes as authwit_cheatcodes; +use dep::aztec::test::helpers::cheatcodes; + +#[test] +unconstrained fn transfer_private() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, recipient, mint_amount) = + utils::setup_and_mint_to_private(/* with_account_contracts */ false); + + // docs:start:txe_test_transfer_private + // Transfer tokens + let transfer_amount = 1000; + Token::at(token_contract_address).transfer(recipient, transfer_amount).call(&mut env.private()); + // docs:end:txe_test_transfer_private + // Check balances + utils::check_private_balance(token_contract_address, owner, mint_amount - transfer_amount); + utils::check_private_balance(token_contract_address, recipient, transfer_amount); +} + +#[test] +unconstrained fn transfer_private_to_self() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, _, mint_amount) = + utils::setup_and_mint_to_private(/* with_account_contracts */ false); + // Transfer tokens + let transfer_amount = 1000; + Token::at(token_contract_address).transfer(owner, transfer_amount).call(&mut env.private()); + + // Check balances + utils::check_private_balance(token_contract_address, owner, mint_amount); +} + +#[test] +unconstrained fn transfer_private_to_non_deployed_account() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, _, mint_amount) = + utils::setup_and_mint_to_private(/* with_account_contracts */ false); + let not_deployed = cheatcodes::create_account(); + // Transfer tokens + let transfer_amount = 1000; + Token::at(token_contract_address).transfer(not_deployed.address, transfer_amount).call( + &mut env.private(), + ); + + // Check balances + utils::check_private_balance(token_contract_address, owner, mint_amount - transfer_amount); + utils::check_private_balance( + token_contract_address, + not_deployed.address, + transfer_amount, + ); +} + +#[test(should_fail_with = "Balance too low")] +unconstrained fn transfer_private_failure_more_than_balance() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, _, recipient, mint_amount) = + utils::setup_and_mint_to_private(/* with_account_contracts */ false); + // Transfer tokens + let transfer_amount = mint_amount + 1; + Token::at(token_contract_address).transfer(recipient, transfer_amount).call(&mut env.private()); +} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_private.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_in_private.nr similarity index 51% rename from noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_private.nr rename to noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_in_private.nr index 11f32bba6ec..e7113a7aa44 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_private.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_in_private.nr @@ -1,68 +1,17 @@ use crate::test::utils; use crate::Token; use dep::authwit::cheatcodes as authwit_cheatcodes; -use dep::aztec::test::helpers::cheatcodes; - -#[test] -unconstrained fn transfer_private() { - // Setup without account contracts. We are not using authwits here, so dummy accounts are enough - let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ false); - - // docs:start:txe_test_transfer_private - // Transfer tokens - let transfer_amount = 1000; - Token::at(token_contract_address).transfer(recipient, transfer_amount).call(&mut env.private()); - // docs:end:txe_test_transfer_private - // Check balances - utils::check_private_balance(token_contract_address, owner, mint_amount - transfer_amount); - utils::check_private_balance(token_contract_address, recipient, transfer_amount); -} - -#[test] -unconstrained fn transfer_private_to_self() { - // Setup without account contracts. We are not using authwits here, so dummy accounts are enough - let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ false); - // Transfer tokens - let transfer_amount = 1000; - Token::at(token_contract_address).transfer(owner, transfer_amount).call(&mut env.private()); - - // Check balances - utils::check_private_balance(token_contract_address, owner, mint_amount); -} - -#[test] -unconstrained fn transfer_private_to_non_deployed_account() { - // Setup without account contracts. We are not using authwits here, so dummy accounts are enough - let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ false); - let not_deployed = cheatcodes::create_account(); - // Transfer tokens - let transfer_amount = 1000; - Token::at(token_contract_address).transfer(not_deployed.address, transfer_amount).call( - &mut env.private(), - ); - - // Check balances - utils::check_private_balance(token_contract_address, owner, mint_amount - transfer_amount); - utils::check_private_balance( - token_contract_address, - not_deployed.address, - transfer_amount, - ); -} #[test] unconstrained fn transfer_private_on_behalf_of_other() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ true); + utils::setup_and_mint_to_private(/* with_account_contracts */ true); // Add authwit // docs:start:private_authwit let transfer_amount = 1000; let transfer_private_from_call_interface = - Token::at(token_contract_address).transfer_from(owner, recipient, transfer_amount, 1); + Token::at(token_contract_address).transfer_in_private(owner, recipient, transfer_amount, 1); authwit_cheatcodes::add_private_authwit_from_call_interface( owner, recipient, @@ -78,26 +27,16 @@ unconstrained fn transfer_private_on_behalf_of_other() { utils::check_private_balance(token_contract_address, recipient, transfer_amount); } -#[test(should_fail_with = "Balance too low")] -unconstrained fn transfer_private_failure_more_than_balance() { - // Setup without account contracts. We are not using authwits here, so dummy accounts are enough - let (env, token_contract_address, _, recipient, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ false); - // Transfer tokens - let transfer_amount = mint_amount + 1; - Token::at(token_contract_address).transfer(recipient, transfer_amount).call(&mut env.private()); -} - // docs:start:fail_with_message #[test(should_fail_with = "invalid nonce")] unconstrained fn transfer_private_failure_on_behalf_of_self_non_zero_nonce() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, recipient, _) = - utils::setup_and_mint_private(/* with_account_contracts */ false); + utils::setup_and_mint_to_private(/* with_account_contracts */ false); // Add authwit let transfer_amount = 1000; let transfer_private_from_call_interface = - Token::at(token_contract_address).transfer_from(owner, recipient, transfer_amount, 1); + Token::at(token_contract_address).transfer_in_private(owner, recipient, transfer_amount, 1); authwit_cheatcodes::add_private_authwit_from_call_interface( owner, recipient, @@ -112,11 +51,11 @@ unconstrained fn transfer_private_failure_on_behalf_of_self_non_zero_nonce() { unconstrained fn transfer_private_failure_on_behalf_of_more_than_balance() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ true); + utils::setup_and_mint_to_private(/* with_account_contracts */ true); // Add authwit let transfer_amount = mint_amount + 1; let transfer_private_from_call_interface = - Token::at(token_contract_address).transfer_from(owner, recipient, transfer_amount, 1); + Token::at(token_contract_address).transfer_in_private(owner, recipient, transfer_amount, 1); authwit_cheatcodes::add_private_authwit_from_call_interface( owner, recipient, @@ -132,11 +71,11 @@ unconstrained fn transfer_private_failure_on_behalf_of_more_than_balance() { unconstrained fn transfer_private_failure_on_behalf_of_other_without_approval() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, _) = - utils::setup_and_mint_private(/* with_account_contracts */ true); + utils::setup_and_mint_to_private(/* with_account_contracts */ true); // Add authwit let transfer_amount = 1000; let transfer_private_from_call_interface = - Token::at(token_contract_address).transfer_from(owner, recipient, transfer_amount, 1); + Token::at(token_contract_address).transfer_in_private(owner, recipient, transfer_amount, 1); // Impersonate recipient to perform the call env.impersonate(recipient); // Transfer tokens @@ -147,11 +86,11 @@ unconstrained fn transfer_private_failure_on_behalf_of_other_without_approval() unconstrained fn transfer_private_failure_on_behalf_of_other_wrong_caller() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, _) = - utils::setup_and_mint_private(/* with_account_contracts */ true); + utils::setup_and_mint_to_private(/* with_account_contracts */ true); // Add authwit let transfer_amount = 1000; let transfer_private_from_call_interface = - Token::at(token_contract_address).transfer_from(owner, recipient, transfer_amount, 1); + Token::at(token_contract_address).transfer_in_private(owner, recipient, transfer_amount, 1); authwit_cheatcodes::add_private_authwit_from_call_interface( owner, owner, diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_public.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_in_public.nr similarity index 70% rename from noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_public.nr rename to noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_in_public.nr index 5dddac32573..aa8ba0376fb 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_public.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_in_public.nr @@ -7,10 +7,10 @@ use dep::aztec::oracle::random::random; unconstrained fn public_transfer() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ false); + utils::setup_and_mint_to_public(/* with_account_contracts */ false); // Transfer tokens let transfer_amount = mint_amount / 10; - Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 0).call( + Token::at(token_contract_address).transfer_in_public(owner, recipient, transfer_amount, 0).call( &mut env.public(), ); @@ -23,11 +23,11 @@ unconstrained fn public_transfer() { unconstrained fn public_transfer_to_self() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ false); + utils::setup_and_mint_to_public(/* with_account_contracts */ false); // Transfer tokens let transfer_amount = mint_amount / 10; // docs:start:call_public - Token::at(token_contract_address).transfer_public(owner, owner, transfer_amount, 0).call( + Token::at(token_contract_address).transfer_in_public(owner, owner, transfer_amount, 0).call( &mut env.public(), ); // docs:end:call_public @@ -39,19 +39,19 @@ unconstrained fn public_transfer_to_self() { unconstrained fn public_transfer_on_behalf_of_other() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); + utils::setup_and_mint_to_public(/* with_account_contracts */ true); let transfer_amount = mint_amount / 10; - let public_transfer_from_call_interface = - Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 1); + let public_transfer_in_private_call_interface = + Token::at(token_contract_address).transfer_in_public(owner, recipient, transfer_amount, 1); authwit_cheatcodes::add_public_authwit_from_call_interface( owner, recipient, - public_transfer_from_call_interface, + public_transfer_in_private_call_interface, ); // Impersonate recipient to perform the call env.impersonate(recipient); // Transfer tokens - public_transfer_from_call_interface.call(&mut env.public()); + public_transfer_in_private_call_interface.call(&mut env.public()); // Check balances utils::check_public_balance(token_contract_address, owner, mint_amount - transfer_amount); utils::check_public_balance(token_contract_address, recipient, transfer_amount); @@ -61,11 +61,11 @@ unconstrained fn public_transfer_on_behalf_of_other() { unconstrained fn public_transfer_failure_more_than_balance() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ false); + utils::setup_and_mint_to_public(/* with_account_contracts */ false); // Transfer tokens let transfer_amount = mint_amount + 1; let public_transfer_call_interface = - Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 0); + Token::at(token_contract_address).transfer_in_public(owner, recipient, transfer_amount, 0); // Try to transfer tokens public_transfer_call_interface.call(&mut env.public()); } @@ -74,10 +74,10 @@ unconstrained fn public_transfer_failure_more_than_balance() { unconstrained fn public_transfer_failure_on_behalf_of_self_non_zero_nonce() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ false); + utils::setup_and_mint_to_public(/* with_account_contracts */ false); // Transfer tokens let transfer_amount = mint_amount / 10; - let public_transfer_call_interface = Token::at(token_contract_address).transfer_public( + let public_transfer_call_interface = Token::at(token_contract_address).transfer_in_public( owner, recipient, transfer_amount, @@ -96,52 +96,52 @@ unconstrained fn public_transfer_failure_on_behalf_of_self_non_zero_nonce() { unconstrained fn public_transfer_failure_on_behalf_of_other_without_approval() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); + utils::setup_and_mint_to_public(/* with_account_contracts */ true); let transfer_amount = mint_amount / 10; - let public_transfer_from_call_interface = - Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 1); + let public_transfer_in_private_call_interface = + Token::at(token_contract_address).transfer_in_public(owner, recipient, transfer_amount, 1); // Impersonate recipient to perform the call env.impersonate(recipient); // Try to transfer tokens - public_transfer_from_call_interface.call(&mut env.public()); + public_transfer_in_private_call_interface.call(&mut env.public()); } #[test(should_fail_with = "attempt to subtract with underflow")] unconstrained fn public_transfer_failure_on_behalf_of_other_more_than_balance() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); + utils::setup_and_mint_to_public(/* with_account_contracts */ true); let transfer_amount = mint_amount + 1; // docs:start:public_authwit - let public_transfer_from_call_interface = - Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 1); + let public_transfer_in_private_call_interface = + Token::at(token_contract_address).transfer_in_public(owner, recipient, transfer_amount, 1); authwit_cheatcodes::add_public_authwit_from_call_interface( owner, recipient, - public_transfer_from_call_interface, + public_transfer_in_private_call_interface, ); // docs:end:public_authwit // Impersonate recipient to perform the call env.impersonate(recipient); // Try to transfer tokens - public_transfer_from_call_interface.call(&mut env.public()); + public_transfer_in_private_call_interface.call(&mut env.public()); } #[test(should_fail_with = "unauthorized")] unconstrained fn public_transfer_failure_on_behalf_of_other_wrong_caller() { // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_public(/* with_account_contracts */ true); + utils::setup_and_mint_to_public(/* with_account_contracts */ true); let transfer_amount = mint_amount / 10; - let public_transfer_from_call_interface = - Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 1); + let public_transfer_in_private_call_interface = + Token::at(token_contract_address).transfer_in_public(owner, recipient, transfer_amount, 1); authwit_cheatcodes::add_public_authwit_from_call_interface( owner, owner, - public_transfer_from_call_interface, + public_transfer_in_private_call_interface, ); // Impersonate recipient to perform the call env.impersonate(recipient); // Try to transfer tokens - public_transfer_from_call_interface.call(&mut env.public()); + public_transfer_in_private_call_interface.call(&mut env.public()); } diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_to_private.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_to_private.nr index a02f4f3d4a2..f48bfb6127e 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_to_private.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_to_private.nr @@ -1,21 +1,18 @@ use crate::{test::utils, Token}; -use dep::aztec::{ - keys::getters::get_public_keys, oracle::random::random, - protocol_types::storage::map::derive_storage_slot_in_map, -}; +use dep::aztec::oracle::random::random; use std::test::OracleMock; -/// Internal orchestration means that the calls to `prepare_transfer_to_private` +/// Internal orchestration means that the calls to `prepare_private_balance_increase` /// and `finalize_transfer_to_private` are done by the TOKEN contract itself. /// In this test's case this is done by the `Token::transfer_to_private(...)` function called /// in `utils::setup_mint_and_transfer_to_private`. #[test] unconstrained fn transfer_to_private_internal_orchestration() { - // The transfer to private is done in `utils::setup_and_mint_private` and for this reason + // The transfer to private is done in `utils::setup_and_mint_to_private` and for this reason // in this test we just call it and check the outcome. // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (_, token_contract_address, user, _, amount) = - utils::setup_and_mint_private(/* with_account_contracts */ false); + utils::setup_and_mint_to_private(/* with_account_contracts */ false); // User's private balance should be equal to the amount utils::check_private_balance(token_contract_address, user, amount); @@ -27,7 +24,7 @@ unconstrained fn transfer_to_private_internal_orchestration() { unconstrained fn transfer_to_private_external_orchestration() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, _, recipient, amount) = - utils::setup_and_mint_public(/* with_account_contracts */ false); + utils::setup_and_mint_to_public(/* with_account_contracts */ false); let note_randomness = random(); @@ -36,7 +33,7 @@ unconstrained fn transfer_to_private_external_orchestration() { // We prepare the transfer let hiding_point_slot: Field = Token::at(token_contract_address) - .prepare_transfer_to_private(recipient) + .prepare_private_balance_increase(recipient) .call(&mut env.private()); // Finalize the transfer of the tokens (message sender owns the tokens in public) @@ -61,7 +58,7 @@ unconstrained fn transfer_to_private_external_orchestration() { unconstrained fn transfer_to_private_transfer_not_prepared() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, _, _, amount) = - utils::setup_and_mint_public(/* with_account_contracts */ false); + utils::setup_and_mint_to_public(/* with_account_contracts */ false); // Transfer was not prepared so we can use random value for the hiding point slot let hiding_point_slot = random(); @@ -76,13 +73,13 @@ unconstrained fn transfer_to_private_transfer_not_prepared() { unconstrained fn transfer_to_private_failure_not_an_owner() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, _, not_owner, amount) = - utils::setup_and_mint_public(/* with_account_contracts */ false); + utils::setup_and_mint_to_public(/* with_account_contracts */ false); // (For this specific test we could set a random value for the commitment and not do the call to `prepare...` // as the token balance check is before we use the value but that would made the test less robust against changes // in the contract.) let hiding_point_slot: Field = Token::at(token_contract_address) - .prepare_transfer_to_private(not_owner) + .prepare_private_balance_increase(not_owner) .call(&mut env.private()); // Try transferring someone else's token balance diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_to_public.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_to_public.nr index 63f84481c74..7789bf8aeb4 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_to_public.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_to_public.nr @@ -7,7 +7,7 @@ use dep::aztec::oracle::random::random; unconstrained fn transfer_to_public_on_behalf_of_self() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ false); + utils::setup_and_mint_to_private(/* with_account_contracts */ false); let transfer_to_public_amount = mint_amount / 10; Token::at(token_contract_address) @@ -24,7 +24,7 @@ unconstrained fn transfer_to_public_on_behalf_of_self() { #[test] unconstrained fn transfer_to_public_on_behalf_of_other() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ true); + utils::setup_and_mint_to_private(/* with_account_contracts */ true); let transfer_to_public_amount = mint_amount / 10; let transfer_to_public_call_interface = Token::at(token_contract_address).transfer_to_public( @@ -54,7 +54,7 @@ unconstrained fn transfer_to_public_on_behalf_of_other() { unconstrained fn transfer_to_public_failure_more_than_balance() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ false); + utils::setup_and_mint_to_private(/* with_account_contracts */ false); let transfer_to_public_amount = mint_amount + 1; Token::at(token_contract_address) @@ -66,7 +66,7 @@ unconstrained fn transfer_to_public_failure_more_than_balance() { unconstrained fn transfer_to_public_failure_on_behalf_of_self_non_zero_nonce() { // Setup without account contracts. We are not using authwits here, so dummy accounts are enough let (env, token_contract_address, owner, _, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ false); + utils::setup_and_mint_to_private(/* with_account_contracts */ false); let transfer_to_public_amount = mint_amount + 1; Token::at(token_contract_address) @@ -77,7 +77,7 @@ unconstrained fn transfer_to_public_failure_on_behalf_of_self_non_zero_nonce() { #[test(should_fail_with = "Balance too low")] unconstrained fn transfer_to_public_failure_on_behalf_of_other_more_than_balance() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ true); + utils::setup_and_mint_to_private(/* with_account_contracts */ true); let transfer_to_public_amount = mint_amount + 1; let transfer_to_public_call_interface = Token::at(token_contract_address).transfer_to_public( @@ -100,7 +100,7 @@ unconstrained fn transfer_to_public_failure_on_behalf_of_other_more_than_balance #[test(should_fail_with = "Authorization not found for message hash")] unconstrained fn transfer_to_public_failure_on_behalf_of_other_invalid_designated_caller() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ true); + utils::setup_and_mint_to_private(/* with_account_contracts */ true); let transfer_to_public_amount = mint_amount + 1; let transfer_to_public_call_interface = Token::at(token_contract_address).transfer_to_public( @@ -123,7 +123,7 @@ unconstrained fn transfer_to_public_failure_on_behalf_of_other_invalid_designate #[test(should_fail_with = "Authorization not found for message hash")] unconstrained fn transfer_to_public_failure_on_behalf_of_other_no_approval() { let (env, token_contract_address, owner, recipient, mint_amount) = - utils::setup_and_mint_private(/* with_account_contracts */ true); + utils::setup_and_mint_to_private(/* with_account_contracts */ true); let transfer_to_public_amount = mint_amount + 1; let transfer_to_public_call_interface = Token::at(token_contract_address).transfer_to_public( diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr index 53f894c85b5..9ccc8ed6b7b 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr @@ -44,19 +44,19 @@ pub unconstrained fn setup( (&mut env, token_contract_address, owner, recipient) } -pub unconstrained fn setup_and_mint_public( +pub unconstrained fn setup_and_mint_to_public( with_account_contracts: bool, ) -> (&mut TestEnvironment, AztecAddress, AztecAddress, AztecAddress, Field) { // Setup let (env, token_contract_address, owner, recipient) = setup(with_account_contracts); let mint_amount = 10000; // Mint some tokens - Token::at(token_contract_address).mint_public(owner, mint_amount).call(&mut env.public()); + Token::at(token_contract_address).mint_to_public(owner, mint_amount).call(&mut env.public()); (env, token_contract_address, owner, recipient, mint_amount) } -pub unconstrained fn setup_and_mint_private( +pub unconstrained fn setup_and_mint_to_private( with_account_contracts: bool, ) -> (&mut TestEnvironment, AztecAddress, AztecAddress, AztecAddress, Field) { // Setup the tokens and mint public balance @@ -64,12 +64,12 @@ pub unconstrained fn setup_and_mint_private( // Mint some tokens let mint_amount = 10000; - mint_private(env, token_contract_address, owner, mint_amount); + mint_to_private(env, token_contract_address, owner, mint_amount); (env, token_contract_address, owner, recipient, mint_amount) } -pub unconstrained fn mint_private( +pub unconstrained fn mint_to_private( env: &mut TestEnvironment, token_contract_address: AztecAddress, recipient: AztecAddress, @@ -78,7 +78,10 @@ pub unconstrained fn mint_private( let note_randomness = random(); let _ = OracleMock::mock("getRandomField").returns(note_randomness); - Token::at(token_contract_address).mint_to_private(recipient, amount).call(&mut env.private()); + let from = recipient; // we are setting from to recipient because of TODO(#9887) + Token::at(token_contract_address).mint_to_private(from, recipient, amount).call( + &mut env.private(), + ); add_token_note( env, diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types.nr index 59c9dc6f1c3..1bc5f644e4f 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types.nr @@ -1,2 +1 @@ -mod transparent_note; -mod balance_set; +pub(crate) mod balance_set; diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/balance_set.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/balance_set.nr index 505b19653e1..7a8667b6357 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/balance_set.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/types/balance_set.nr @@ -1,15 +1,13 @@ use dep::aztec::{ context::{PrivateContext, UnconstrainedContext}, note::note_emission::OuterNoteEmission, - protocol_types::{ - address::AztecAddress, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, public_keys::NpkM, - }, + protocol_types::{address::AztecAddress, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL}, }; use dep::aztec::prelude::{NoteGetterOptions, NoteViewerOptions, PrivateSet}; use dep::uint_note::uint_note::UintNote; pub struct BalanceSet { - set: PrivateSet, + pub set: PrivateSet, } impl BalanceSet { diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr deleted file mode 100644 index ed1f08e0d74..00000000000 --- a/noir-projects/noir-contracts/contracts/token_contract/src/types/transparent_note.nr +++ /dev/null @@ -1,63 +0,0 @@ -// docs:start:token_types_all -use dep::aztec::{ - macros::notes::note, - note::utils::compute_note_hash_for_nullify, - prelude::{NoteHeader, NullifiableNote, PrivateContext}, - protocol_types::{ - constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash_with_separator, - }, -}; - -use dep::std::mem::zeroed; - -// Transparent note represents a note that is created in the clear (public execution), but can only be spent by those -// that know the preimage of the "secret_hash" (the secret). This is typically used when shielding a token balance. -// Owner of the tokens provides a "secret_hash" as an argument to the public "shield" function and then the tokens -// can be redeemed in private by presenting the preimage of the "secret_hash" (the secret). -#[note] -pub struct TransparentNote { - amount: Field, - secret_hash: Field, -} - -impl NullifiableNote for TransparentNote { - // Computing a nullifier in a transparent note is not guarded by making secret a part of the nullifier preimage (as - // is common in other cases) and instead is guarded by the functionality of "redeem_shield" function. There we do - // the following: - // 1) We pass the secret as an argument to the function and use it to compute a secret hash, - // 2) we fetch a note via the "get_notes" oracle which accepts the secret hash as an argument, - // 3) the "get_notes" oracle constrains that the secret hash in the returned note matches the one computed in - // circuit. - // This achieves that the note can only be spent by the party that knows the secret. - fn compute_nullifier( - self, - _context: &mut PrivateContext, - _note_hash_for_nullify: Field, - ) -> Field { - let note_hash_for_nullify = compute_note_hash_for_nullify(self); - poseidon2_hash_with_separator( - [note_hash_for_nullify], - GENERATOR_INDEX__NOTE_NULLIFIER as Field, - ) - } - - unconstrained fn compute_nullifier_without_context(self) -> Field { - // compute_nullifier ignores both of its parameters so we can reuse it here - self.compute_nullifier(zeroed(), zeroed()) - } -} - -impl TransparentNote { - // CONSTRUCTORS - pub fn new(amount: Field, secret_hash: Field) -> Self { - TransparentNote { amount, secret_hash, header: NoteHeader::empty() } - } -} - -impl Eq for TransparentNote { - fn eq(self, other: Self) -> bool { - (self.amount == other.amount) & (self.secret_hash == other.secret_hash) - } -} - -// docs:end:token_types_all diff --git a/noir-projects/noir-contracts/contracts/token_portal_content_hash_lib/src/lib.nr b/noir-projects/noir-contracts/contracts/token_portal_content_hash_lib/src/lib.nr index f7789aefcd5..682e80ce5f1 100644 --- a/noir-projects/noir-contracts/contracts/token_portal_content_hash_lib/src/lib.nr +++ b/noir-projects/noir-contracts/contracts/token_portal_content_hash_lib/src/lib.nr @@ -1,56 +1,57 @@ -// docs:start:mint_public_content_hash_nr +// docs:start:mint_to_public_content_hash_nr use dep::aztec::prelude::{AztecAddress, EthAddress}; use dep::aztec::protocol_types::hash::sha256_to_field; -// Computes a content hash of a deposit/mint_public message. +// Computes a content hash of a deposit/mint_to_public message. // Refer TokenPortal.sol for reference on L1. -pub fn get_mint_public_content_hash(owner: AztecAddress, amount: Field) -> Field { +pub fn get_mint_to_public_content_hash(owner: AztecAddress, amount: Field) -> Field { let mut hash_bytes = [0; 68]; let recipient_bytes:[u8; 32] = owner.to_field().to_be_bytes(); let amount_bytes:[u8; 32] = amount.to_be_bytes(); + // The purpose of including the following selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. + let selector = comptime { std::hash::keccak256("mint_to_public(bytes32,uint256)".as_bytes(), 31) }; + + for i in 0..4 { + hash_bytes[i] = selector[i]; + } + for i in 0..32 { hash_bytes[i + 4] = recipient_bytes[i]; hash_bytes[i + 36] = amount_bytes[i]; } - // Function selector: 0x3e87b9be keccak256('mint_public(bytes32,uint256)') - hash_bytes[0] = 0x3e; - hash_bytes[1] = 0x87; - hash_bytes[2] = 0xb9; - hash_bytes[3] = 0xbe; - let content_hash = sha256_to_field(hash_bytes); content_hash } -// docs:end:mint_public_content_hash_nr +// docs:end:mint_to_public_content_hash_nr -// docs:start:get_mint_private_content_hash -// Computes a content hash of a deposit/mint_private message. +// docs:start:get_mint_to_private_content_hash +// Computes a content hash of a deposit/mint_to_private message. // Refer TokenPortal.sol for reference on L1. -pub fn get_mint_private_content_hash( - secret_hash_for_redeeming_minted_notes: Field, +pub fn get_mint_to_private_content_hash( amount: Field ) -> Field { - let mut hash_bytes = [0; 68]; - let secret_hash_bytes:[u8; 32] = secret_hash_for_redeeming_minted_notes.to_be_bytes(); + let mut hash_bytes = [0; 36]; let amount_bytes:[u8; 32] = amount.to_be_bytes(); - for i in 0..32 { - hash_bytes[i + 4] = secret_hash_bytes[i]; - hash_bytes[i + 36] = amount_bytes[i]; + // The purpose of including the following selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. + let selector = comptime { std::hash::keccak256("mint_to_private(uint256)".as_bytes(), 24) }; + + for i in 0..4 { + hash_bytes[i] = selector[i]; } - // Function selector: 0xefa012c1 keccak256('mint_private(bytes32,uint256)') - hash_bytes[0] = 0xef; - hash_bytes[1] = 0xa0; - hash_bytes[2] = 0x12; - hash_bytes[3] = 0xc1; + for i in 0..32 { + hash_bytes[i + 4] = amount_bytes[i]; + } let content_hash = sha256_to_field(hash_bytes); content_hash } -// docs:end:get_mint_private_content_hash +// docs:end:get_mint_to_private_content_hash // docs:start:get_withdraw_content_hash // Computes a content hash of a withdraw message. @@ -64,11 +65,13 @@ pub fn get_withdraw_content_hash(recipient: EthAddress, amount: Field, caller_on let amount_bytes: [u8; 32] = amount.to_be_bytes(); let caller_on_l1_bytes: [u8; 32] = caller_on_l1.to_field().to_be_bytes(); - // 0x69328dec, selector for "withdraw(address,uint256,address)" - hash_bytes[0] = 0x69; - hash_bytes[1] = 0x32; - hash_bytes[2] = 0x8d; - hash_bytes[3] = 0xec; + // The purpose of including the following selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. + let selector = comptime { std::hash::keccak256("withdraw(address,uint256,address)".as_bytes(), 33) }; + + for i in 0..4 { + hash_bytes[i] = selector[i]; + } for i in 0..32 { hash_bytes[i + 4] = recipient_bytes[i]; diff --git a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr index a9219a45144..e1fd634121f 100644 --- a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr @@ -62,7 +62,7 @@ contract Uniswap { // Transfer funds to this contract Token::at(input_asset) - .transfer_public( + .transfer_in_public( sender, context.this_address(), input_amount, @@ -121,7 +121,6 @@ contract Uniswap { uniswap_fee_tier: Field, // which uniswap tier to use (eg 3000 for 0.3% fee) minimum_output_amount: Field, // minimum output amount to receive (slippage protection for the swap) // params for the depositing output_asset back to Aztec - secret_hash_for_redeeming_minted_notes: Field, // secret hash used to redeem minted notes at a later time. This enables anyone to call this function and mint tokens to a user on their behalf secret_hash_for_L1_to_l2_message: Field, // for when l1 uniswap portal inserts the message to consume output assets on L2 caller_on_L1: EthAddress, // ethereum address that can call this function on the L1 portal (0x0 if anyone can call) ) { @@ -172,7 +171,6 @@ contract Uniswap { uniswap_fee_tier, output_asset_bridge_portal_address, minimum_output_amount, - secret_hash_for_redeeming_minted_notes, secret_hash_for_L1_to_l2_message, caller_on_L1, ); diff --git a/noir-projects/noir-contracts/contracts/uniswap_contract/src/util.nr b/noir-projects/noir-contracts/contracts/uniswap_contract/src/util.nr index 8d93994d624..dc5605d7fd0 100644 --- a/noir-projects/noir-contracts/contracts/uniswap_contract/src/util.nr +++ b/noir-projects/noir-contracts/contracts/uniswap_contract/src/util.nr @@ -27,11 +27,19 @@ pub fn compute_swap_public_content_hash( secret_hash_for_L1_to_l2_message.to_be_bytes(); let caller_on_L1_bytes: [u8; 32] = caller_on_L1.to_field().to_be_bytes(); - // function selector: 0xf18186d8 keccak256("swap_public(address,uint256,uint24,address,uint256,bytes32,bytes32,address)") - hash_bytes[0] = 0xf1; - hash_bytes[1] = 0x81; - hash_bytes[2] = 0x86; - hash_bytes[3] = 0xd8; + // The purpose of including the following selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. + let selector = comptime { + std::hash::keccak256( + "swap_public(address,uint256,uint24,address,uint256,bytes32,bytes32,address)".as_bytes(), + 75, + ) + }; + + hash_bytes[0] = selector[0]; + hash_bytes[1] = selector[1]; + hash_bytes[2] = selector[2]; + hash_bytes[3] = selector[3]; for i in 0..32 { hash_bytes[i + 4] = input_token_portal_bytes[i]; @@ -58,11 +66,10 @@ pub fn compute_swap_private_content_hash( uniswap_fee_tier: Field, output_asset_bridge_portal_address: EthAddress, minimum_output_amount: Field, - secret_hash_for_redeeming_minted_notes: Field, secret_hash_for_L1_to_l2_message: Field, caller_on_L1: EthAddress, ) -> Field { - let mut hash_bytes = [0; 260]; // 8 fields of 32 bytes each + 4 bytes fn selector + let mut hash_bytes = [0; 228]; // 7 fields of 32 bytes each + 4 bytes fn selector let input_token_portal_bytes: [u8; 32] = input_asset_bridge_portal_address.to_field().to_be_bytes(); let in_amount_bytes: [u8; 32] = input_amount.to_be_bytes(); @@ -70,17 +77,23 @@ pub fn compute_swap_private_content_hash( let output_token_portal_bytes: [u8; 32] = output_asset_bridge_portal_address.to_field().to_be_bytes(); let amount_out_min_bytes: [u8; 32] = minimum_output_amount.to_be_bytes(); - let secret_hash_for_redeeming_minted_notes_bytes: [u8; 32] = - secret_hash_for_redeeming_minted_notes.to_be_bytes(); let secret_hash_for_L1_to_l2_message_bytes: [u8; 32] = secret_hash_for_L1_to_l2_message.to_be_bytes(); let caller_on_L1_bytes: [u8; 32] = caller_on_L1.to_field().to_be_bytes(); - // function selector: 0x16f416eb keccak256("swap_private(address,uint256,uint24,address,uint256,bytes32,bytes32,address)") - hash_bytes[0] = 0x16; - hash_bytes[1] = 0xf4; - hash_bytes[2] = 0x16; - hash_bytes[3] = 0xeb; + // The purpose of including the following selector is to make the message unique to that specific call. Note that + // it has nothing to do with calling the function. + let selector = comptime { + std::hash::keccak256( + "swap_private(address,uint256,uint24,address,uint256,bytes32,address)".as_bytes(), + 68, + ) + }; + + hash_bytes[0] = selector[0]; + hash_bytes[1] = selector[1]; + hash_bytes[2] = selector[2]; + hash_bytes[3] = selector[3]; for i in 0..32 { hash_bytes[i + 4] = input_token_portal_bytes[i]; @@ -88,9 +101,8 @@ pub fn compute_swap_private_content_hash( hash_bytes[i + 68] = uniswap_fee_tier_bytes[i]; hash_bytes[i + 100] = output_token_portal_bytes[i]; hash_bytes[i + 132] = amount_out_min_bytes[i]; - hash_bytes[i + 164] = secret_hash_for_redeeming_minted_notes_bytes[i]; - hash_bytes[i + 196] = secret_hash_for_L1_to_l2_message_bytes[i]; - hash_bytes[i + 228] = caller_on_L1_bytes[i]; + hash_bytes[i + 164] = secret_hash_for_L1_to_l2_message_bytes[i]; + hash_bytes[i + 196] = caller_on_L1_bytes[i]; } let content_hash = sha256_to_field(hash_bytes); content_hash diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/mod.nr index f5c1113c75e..eaafacaabe3 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/mod.nr @@ -1,10 +1,10 @@ -mod previous_kernel_validator; -mod private_call_data_validator; -mod private_kernel_circuit_output_validator; -mod private_kernel_circuit_public_inputs_composer; -mod reset_output_composer; -mod reset_output_validator; -mod tail_output_composer; -mod tail_output_validator; -mod tail_to_public_output_composer; -mod tail_to_public_output_validator; +pub(crate) mod previous_kernel_validator; +pub(crate) mod private_call_data_validator; +pub(crate) mod private_kernel_circuit_output_validator; +pub(crate) mod private_kernel_circuit_public_inputs_composer; +pub(crate) mod reset_output_composer; +pub(crate) mod reset_output_validator; +pub(crate) mod tail_output_composer; +pub(crate) mod tail_output_validator; +pub(crate) mod tail_to_public_output_composer; +pub(crate) mod tail_to_public_output_validator; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr index df372aa9751..0d20c84272f 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr @@ -19,7 +19,7 @@ use dep::types::{ side_effect::{Ordered, RangeOrdered}, }, address::AztecAddress, - constants::MAX_FIELD_VALUE, + constants::{MAX_FIELD_VALUE, REGISTERER_CONTRACT_ADDRESS}, transaction::tx_request::TxRequest, utils::arrays::find_index_hint, }; @@ -218,9 +218,16 @@ impl PrivateCallDataValidator { "encrypted_logs_hashes must be empty for static calls", ); assert_eq( - self.array_lengths.unencrypted_logs_hashes, + self.array_lengths.contract_class_logs_hashes, 0, - "unencrypted_logs_hashes must be empty for static calls", + "contract_class_logs_hashes must be empty for static calls", + ); + } + if (self.array_lengths.contract_class_logs_hashes != 0) { + assert_eq( + call_context.contract_address, + REGISTERER_CONTRACT_ADDRESS, + "only the class registerer may emit contract class logs", ); } } @@ -351,8 +358,8 @@ impl PrivateCallDataValidator { validate_incrementing_counters_within_range( counter_start, counter_end, - public_inputs.unencrypted_logs_hashes, - self.array_lengths.unencrypted_logs_hashes, + public_inputs.contract_class_logs_hashes, + self.array_lengths.contract_class_logs_hashes, ); validate_incrementing_counter_ranges_within_range( counter_start, diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr index b1fb0854863..12912206fb9 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr @@ -61,7 +61,7 @@ mod tests { validate_split_ranges( self.private_call.min_revertible_side_effect_counter, self.first_revertible_private_call_request_index, - self.private_call.private_call_requests.storage, + self.private_call.private_call_requests.storage(), self.private_call.private_call_requests.len(), ); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr index ab4d9245ec0..66eee01a1b9 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr @@ -242,9 +242,9 @@ impl PrivateKernelCircuitOutputValidator { array_lengths.encrypted_logs_hashes, ); assert_array_prepended( - self.output.end.unencrypted_logs_hashes, - previous_kernel.end.unencrypted_logs_hashes, - array_lengths.unencrypted_logs_hashes, + self.output.end.contract_class_logs_hashes, + previous_kernel.end.contract_class_logs_hashes, + array_lengths.contract_class_logs_hashes, ); assert_array_prepended( self.output.end.public_call_requests, @@ -324,10 +324,10 @@ impl PrivateKernelCircuitOutputValidator { contract_address, ); assert_array_appended_scoped( - self.output.end.unencrypted_logs_hashes, - private_call.unencrypted_logs_hashes, - array_lengths.unencrypted_logs_hashes, - offsets.unencrypted_logs_hashes, + self.output.end.contract_class_logs_hashes, + private_call.contract_class_logs_hashes, + array_lengths.contract_class_logs_hashes, + offsets.contract_class_logs_hashes, contract_address, ); assert_array_appended( diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr index 7e58f15693c..09d6d7944f1 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr @@ -76,8 +76,8 @@ impl PrivateKernelCircuitPublicInputsComposer { public_inputs.end.note_encrypted_logs_hashes = array_to_bounded_vec(start.note_encrypted_logs_hashes); public_inputs.end.encrypted_logs_hashes = array_to_bounded_vec(start.encrypted_logs_hashes); - public_inputs.end.unencrypted_logs_hashes = - array_to_bounded_vec(start.unencrypted_logs_hashes); + public_inputs.end.contract_class_logs_hashes = + array_to_bounded_vec(start.contract_class_logs_hashes); public_inputs.end.public_call_requests = array_to_bounded_vec(start.public_call_requests); public_inputs.end.private_call_stack = array_to_bounded_vec(start.private_call_stack); @@ -102,8 +102,8 @@ impl PrivateKernelCircuitPublicInputsComposer { // Note hashes, nullifiers, note_encrypted_logs_hashes, and encrypted_logs_hashes are sorted in the reset circuit. self.public_inputs.end.l2_to_l1_msgs.storage = sort_by_counter_asc(self.public_inputs.end.l2_to_l1_msgs.storage); - self.public_inputs.end.unencrypted_logs_hashes.storage = - sort_by_counter_asc(self.public_inputs.end.unencrypted_logs_hashes.storage); + self.public_inputs.end.contract_class_logs_hashes.storage = + sort_by_counter_asc(self.public_inputs.end.contract_class_logs_hashes.storage); self.public_inputs.end.public_call_requests.storage = sort_by_counter_desc(self.public_inputs.end.public_call_requests.storage); } @@ -237,11 +237,11 @@ impl PrivateKernelCircuitPublicInputsComposer { } } - let unencrypted_logs = private_call.unencrypted_logs_hashes; - for i in 0..unencrypted_logs.len() { - let log = unencrypted_logs[i]; + let contract_class_logs = private_call.contract_class_logs_hashes; + for i in 0..contract_class_logs.len() { + let log = contract_class_logs[i]; if !is_empty(log) { - self.public_inputs.end.unencrypted_logs_hashes.push(log.scope( + self.public_inputs.end.contract_class_logs_hashes.push(log.scope( private_call.call_context.contract_address, )); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer.nr index 3d570925058..003669e9e8f 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer.nr @@ -1,4 +1,4 @@ -mod reset_output_hints; +pub mod reset_output_hints; pub use reset_output_hints::ResetOutputHints; @@ -21,12 +21,12 @@ use dep::types::{ }; pub struct ResetOutputComposer { - previous_kernel: PrivateKernelCircuitPublicInputs, - validation_request_processor: PrivateValidationRequestProcessor, - note_hash_siloing_amount: u32, - nullifier_siloing_amount: u32, - encrypted_log_siloing_amount: u32, - hints: ResetOutputHints, + pub previous_kernel: PrivateKernelCircuitPublicInputs, + pub validation_request_processor: PrivateValidationRequestProcessor, + pub note_hash_siloing_amount: u32, + pub nullifier_siloing_amount: u32, + pub encrypted_log_siloing_amount: u32, + pub hints: ResetOutputHints, } impl ResetOutputComposer { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer/reset_output_hints.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer/reset_output_hints.nr index a88cbd99565..64d0b55aade 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer/reset_output_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer/reset_output_hints.nr @@ -20,17 +20,17 @@ use dep::types::{ pub struct ResetOutputHints { // note_hashes - kept_note_hashes: [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX], - sorted_note_hash_indexes: [u32; MAX_NOTE_HASHES_PER_TX], + pub kept_note_hashes: [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX], + pub sorted_note_hash_indexes: [u32; MAX_NOTE_HASHES_PER_TX], // nullifiers - kept_nullifiers: [ScopedNullifier; MAX_NULLIFIERS_PER_TX], - sorted_nullifier_indexes: [u32; MAX_NULLIFIERS_PER_TX], + pub kept_nullifiers: [ScopedNullifier; MAX_NULLIFIERS_PER_TX], + pub sorted_nullifier_indexes: [u32; MAX_NULLIFIERS_PER_TX], // note_encrypted_log_hashes - kept_note_encrypted_log_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - sorted_note_encrypted_log_hash_indexes: [u32; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - transient_or_propagated_note_hash_indexes_for_logs: [u32; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + pub kept_note_encrypted_log_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + pub sorted_note_encrypted_log_hash_indexes: [u32; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + pub transient_or_propagated_note_hash_indexes_for_logs: [u32; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], // encrypted_log_hashes - sorted_encrypted_log_hash_indexes: [u32; MAX_ENCRYPTED_LOGS_PER_TX], + pub sorted_encrypted_log_hash_indexes: [u32; MAX_ENCRYPTED_LOGS_PER_TX], } pub unconstrained fn generate_reset_output_hints( diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer/reset_output_hints/squash_transient_data.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer/reset_output_hints/squash_transient_data.nr index b5879b1a2c3..fd7bef196ec 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer/reset_output_hints/squash_transient_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/reset_output_composer/reset_output_hints/squash_transient_data.nr @@ -45,5 +45,5 @@ pub unconstrained fn squash_transient_data Gas { metered_da_bytes += data.encrypted_log_preimages_length as u32; metered_l2_gas += data.encrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; - metered_da_bytes += data.unencrypted_log_preimages_length as u32; - metered_l2_gas += data.unencrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; + metered_da_bytes += data.contract_class_log_preimages_length as u32; + metered_l2_gas += data.contract_class_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; Gas::new(metered_da_bytes * DA_GAS_PER_BYTE, metered_l2_gas) + Gas::tx_overhead() } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr index fee3e43e133..458a65a26f0 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr @@ -10,7 +10,7 @@ use dep::types::{ log_hash::{NoteLogHash, ScopedEncryptedLogHash, ScopedLogHash}, }, messaging::l2_to_l1_message::ScopedL2ToL1Message, - traits::is_empty, + traits::{is_empty, is_empty_array}, utils::arrays::assert_exposed_sorted_transformed_value_array, }; @@ -39,6 +39,10 @@ impl TailOutputValidator { fn validate_empty_values(self) { assert(is_empty(self.output.start_state), "start_state must be empty"); assert_eq(self.output.revert_code, 0, "revert_code must be empty"); + assert( + is_empty_array(self.output.end.unencrypted_logs_hashes), + "unencrypted logs in private must be empty", + ); } fn validate_propagated_values(self) { @@ -115,21 +119,20 @@ impl TailOutputValidator { |prev: ScopedL2ToL1Message, out: ScopedL2ToL1Message| out == prev.expose_to_public(), self.hints.sorted_l2_to_l1_msg_hints, ); - - // unencrypted_log_hashes + // contract_class_logs assert_exposed_sorted_transformed_value_array( - self.previous_kernel.end.unencrypted_logs_hashes, - self.output.end.unencrypted_logs_hashes, + self.previous_kernel.end.contract_class_logs_hashes, + self.output.end.contract_class_logs_hashes, |prev: ScopedLogHash, out: ScopedLogHash| out == prev.expose_to_public(), - self.hints.sorted_unencrypted_log_hash_hints, + self.hints.sorted_contract_class_log_hash_hints, ); } fn validate_gas_used(self) { let gas_used = meter_gas_used(self.output.end); - assert(self.output.end.gas_used == gas_used, "incorrect metered gas used"); + assert(self.output.gas_used == gas_used, "incorrect metered gas used"); let limits = self.previous_kernel.constants.tx_context.gas_settings.gas_limits; - assert(self.output.end.gas_used.within(limits), "The gas used exceeds the gas limits"); + assert(self.output.gas_used.within(limits), "The gas used exceeds the gas limits"); } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/tail_output_hints.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/tail_output_hints.nr index 459c68948b5..73f199f7a74 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/tail_output_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/tail_output_hints.nr @@ -1,15 +1,15 @@ use dep::types::{ abis::{kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, log_hash::ScopedLogHash}, - constants::{MAX_L2_TO_L1_MSGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX}, + constants::{MAX_CONTRACT_CLASS_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX}, utils::arrays::{get_order_hints_asc, OrderHint, sort_by_counter_asc}, }; pub struct TailOutputHints { // L2 to l1 msgs. sorted_l2_to_l1_msg_hints: [OrderHint; MAX_L2_TO_L1_MSGS_PER_TX], - // Unencrypted log hashes. - sorted_unencrypted_log_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], - sorted_unencrypted_log_hash_hints: [OrderHint; MAX_UNENCRYPTED_LOGS_PER_TX], + // Contract class log hashes. + sorted_contract_class_log_hashes: [ScopedLogHash; MAX_CONTRACT_CLASS_LOGS_PER_TX], + sorted_contract_class_log_hash_hints: [OrderHint; MAX_CONTRACT_CLASS_LOGS_PER_TX], } pub unconstrained fn generate_tail_output_hints( @@ -18,15 +18,15 @@ pub unconstrained fn generate_tail_output_hints( // l2_to_l1_msgs let sorted_l2_to_l1_msg_hints = get_order_hints_asc(previous_kernel.end.l2_to_l1_msgs); - // unencrypted_logs - let sorted_unencrypted_log_hashes = - sort_by_counter_asc(previous_kernel.end.unencrypted_logs_hashes); - let sorted_unencrypted_log_hash_hints = - get_order_hints_asc(previous_kernel.end.unencrypted_logs_hashes); + // contract_class_logs + let sorted_contract_class_log_hashes = + sort_by_counter_asc(previous_kernel.end.contract_class_logs_hashes); + let sorted_contract_class_log_hash_hints = + get_order_hints_asc(previous_kernel.end.contract_class_logs_hashes); TailOutputHints { sorted_l2_to_l1_msg_hints, - sorted_unencrypted_log_hashes, - sorted_unencrypted_log_hash_hints, + sorted_contract_class_log_hashes, + sorted_contract_class_log_hash_hints, } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr index f5d48debad2..05191951423 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr @@ -4,15 +4,11 @@ mod split_to_public; use crate::components::{ private_kernel_circuit_public_inputs_composer::PrivateKernelCircuitPublicInputsComposer, tail_to_public_output_composer::{ - meter_gas_used::{meter_gas_used_non_revertible, meter_gas_used_revertible}, - split_to_public::split_to_public, + meter_gas_used::meter_gas_used, split_to_public::split_to_public, }, }; -use dep::types::abis::{ - kernel_circuit_public_inputs::{ - PrivateKernelCircuitPublicInputs, PrivateToPublicKernelCircuitPublicInputs, - }, - validation_requests::PublicValidationRequests, +use dep::types::abis::kernel_circuit_public_inputs::{ + PrivateKernelCircuitPublicInputs, PrivateToPublicKernelCircuitPublicInputs, }; pub struct TailToPublicOutputComposer { @@ -31,14 +27,15 @@ impl TailToPublicOutputComposer { pub unconstrained fn finish(self) -> PrivateToPublicKernelCircuitPublicInputs { let source = self.output_composer.public_inputs; - let mut (non_revertible_accumulated_data, revertible_accumulated_data) = + let (non_revertible_accumulated_data, revertible_accumulated_data) = split_to_public(source.end, source.min_revertible_side_effect_counter); - non_revertible_accumulated_data.gas_used = - meter_gas_used_non_revertible(non_revertible_accumulated_data); - - revertible_accumulated_data.gas_used = - meter_gas_used_revertible(revertible_accumulated_data); + let gas_used = meter_gas_used( + non_revertible_accumulated_data, + revertible_accumulated_data, + source.public_teardown_call_request, + source.constants.tx_context.gas_settings.teardown_gas_limits, + ); let mut output = PrivateToPublicKernelCircuitPublicInputs { constants: source.constants, @@ -46,6 +43,7 @@ impl TailToPublicOutputComposer { non_revertible_accumulated_data, revertible_accumulated_data, public_teardown_call_request: source.public_teardown_call_request, + gas_used, fee_payer: source.fee_payer, }; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr index 16e11c7f4a9..c12b75696b5 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr @@ -3,15 +3,17 @@ use dep::types::{ accumulated_data::PrivateToPublicAccumulatedData, gas::Gas, log_hash::{LogHash, ScopedLogHash}, + public_call_request::PublicCallRequest, }, constants::{ DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, FIXED_AVM_STARTUP_L2_GAS, L2_GAS_PER_LOG_BYTE, L2_GAS_PER_NOTE_HASH, L2_GAS_PER_NULLIFIER, }, + traits::is_empty, utils::arrays::array_length, }; -fn meter_gas_used(data: PrivateToPublicAccumulatedData) -> Gas { +fn meter_accumulated_data_gas_used(data: PrivateToPublicAccumulatedData) -> Gas { let mut metered_da_bytes = 0; let mut metered_l2_gas = 0; @@ -35,20 +37,30 @@ fn meter_gas_used(data: PrivateToPublicAccumulatedData) -> Gas { metered_da_bytes += encrypted_log_preimages_length as u32; metered_l2_gas += encrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; - let unencrypted_log_preimages_length = - data.unencrypted_logs_hashes.fold(0, |len, l: ScopedLogHash| len + l.log_hash.length); - metered_da_bytes += unencrypted_log_preimages_length as u32; - metered_l2_gas += unencrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; + let contract_class_log_preimages_length = + data.contract_class_logs_hashes.fold(0, |len, l: ScopedLogHash| len + l.log_hash.length); + metered_da_bytes += contract_class_log_preimages_length as u32; + metered_l2_gas += contract_class_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; metered_l2_gas += array_length(data.public_call_requests) * FIXED_AVM_STARTUP_L2_GAS; Gas::new(metered_da_bytes * DA_GAS_PER_BYTE, metered_l2_gas) } -pub fn meter_gas_used_non_revertible(data: PrivateToPublicAccumulatedData) -> Gas { - meter_gas_used(data) + Gas::tx_overhead() -} +pub fn meter_gas_used( + non_revertible_data: PrivateToPublicAccumulatedData, + revertible_data: PrivateToPublicAccumulatedData, + public_teardown_call_request: PublicCallRequest, + teardown_gas_limits: Gas, +) -> Gas { + let teardown_gas = if is_empty(public_teardown_call_request) { + Gas::empty() + } else { + teardown_gas_limits + }; -pub fn meter_gas_used_revertible(data: PrivateToPublicAccumulatedData) -> Gas { - meter_gas_used(data) + Gas::tx_overhead() + + meter_accumulated_data_gas_used(non_revertible_data) + + meter_accumulated_data_gas_used(revertible_data) + + teardown_gas } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr index ad944b4cd0b..5d723d0804d 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr @@ -73,15 +73,15 @@ pub unconstrained fn split_to_public( } } - let unencrypted_logs_hashes = data.unencrypted_logs_hashes; - for i in 0..unencrypted_logs_hashes.max_len() { - if i < unencrypted_logs_hashes.len() { - let unencrypted_log_hash = unencrypted_logs_hashes.get_unchecked(i); - let public_log_hash = unencrypted_log_hash.expose_to_public(); - if unencrypted_log_hash.counter() < min_revertible_side_effect_counter { - non_revertible_builder.unencrypted_logs_hashes.push(public_log_hash); + let contract_class_logs_hashes = data.contract_class_logs_hashes; + for i in 0..contract_class_logs_hashes.max_len() { + if i < contract_class_logs_hashes.len() { + let contract_class_log_hash = contract_class_logs_hashes.get_unchecked(i); + let public_log_hash = contract_class_log_hash.expose_to_public(); + if contract_class_log_hash.counter() < min_revertible_side_effect_counter { + non_revertible_builder.contract_class_logs_hashes.push(public_log_hash); } else { - revertible_builder.unencrypted_logs_hashes.push(public_log_hash); + revertible_builder.contract_class_logs_hashes.push(public_log_hash); } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr index e768fbc3802..ef1437dafc1 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr @@ -1,9 +1,7 @@ mod tail_to_public_output_hints; use crate::components::{ - tail_to_public_output_composer::meter_gas_used::{ - meter_gas_used_non_revertible, meter_gas_used_revertible, - }, + tail_to_public_output_composer::meter_gas_used::meter_gas_used, tail_to_public_output_validator::tail_to_public_output_hints::{ generate_tail_to_public_output_hints, TailToPublicOutputHints, }, @@ -15,7 +13,7 @@ use dep::types::{ }, log_hash::{LogHash, NoteLogHash, ScopedEncryptedLogHash, ScopedLogHash}, note_hash::ScopedNoteHash, - nullifier::{Nullifier, ScopedNullifier}, + nullifier::ScopedNullifier, public_call_request::PublicCallRequest, side_effect::Counted, }, @@ -126,14 +124,14 @@ impl TailToPublicOutputValidator { hints.sorted_l2_to_l1_msg_hints, ); - // unencrypted_logs_hashes + // contract_class_logs_hashes assert_split_sorted_transformed_value_arrays_asc( - prev_data.unencrypted_logs_hashes, - prev_data.unencrypted_logs_hashes.map(|log: ScopedLogHash| log.expose_to_public()), + prev_data.contract_class_logs_hashes, + prev_data.contract_class_logs_hashes.map(|log: ScopedLogHash| log.expose_to_public()), split_counter, - output_non_revertible.unencrypted_logs_hashes, - output_revertible.unencrypted_logs_hashes, - hints.sorted_unencrypted_log_hash_hints, + output_non_revertible.contract_class_logs_hashes, + output_revertible.contract_class_logs_hashes, + hints.sorted_contract_class_log_hash_hints, ); // public_call_requests @@ -148,21 +146,14 @@ impl TailToPublicOutputValidator { } fn validate_gas_used(self) { - let gas_used = meter_gas_used_non_revertible(self.output.non_revertible_accumulated_data); - assert( - self.output.non_revertible_accumulated_data.gas_used == gas_used, - "incorrect metered non-revertible gas used", - ); - - let gas_used = meter_gas_used_revertible(self.output.revertible_accumulated_data); - assert( - self.output.revertible_accumulated_data.gas_used == gas_used, - "incorrect metered revertible gas used", + let gas_settings = self.output.constants.tx_context.gas_settings; + let gas_used = meter_gas_used( + self.output.non_revertible_accumulated_data, + self.output.revertible_accumulated_data, + self.output.public_teardown_call_request, + gas_settings.teardown_gas_limits, ); - - let limits = self.previous_kernel.constants.tx_context.gas_settings.gas_limits; - let total_gas_used = self.output.non_revertible_accumulated_data.gas_used - + self.output.revertible_accumulated_data.gas_used; - assert(total_gas_used.within(limits), "The gas used exceeds the gas limits"); + assert_eq(self.output.gas_used, gas_used, "incorrect metered gas used"); + assert(gas_used.within(gas_settings.gas_limits), "The gas used exceeds the gas limits"); } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr index 0918eaa04b2..231c175a269 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr @@ -1,14 +1,16 @@ use dep::types::{ abis::kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, - constants::{MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX}, + constants::{ + MAX_CONTRACT_CLASS_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, + }, utils::arrays::{get_split_order_hints_asc, get_split_order_hints_desc, SplitOrderHints}, }; pub struct TailToPublicOutputHints { // L2 to l1 msgs. sorted_l2_to_l1_msg_hints: SplitOrderHints, - // Unencrypted log hashes. - sorted_unencrypted_log_hash_hints: SplitOrderHints, + // Contract class log hashes. + sorted_contract_class_log_hash_hints: SplitOrderHints, // Public call requests. sorted_public_call_request_hints: SplitOrderHints, } @@ -22,9 +24,11 @@ pub unconstrained fn generate_tail_to_public_output_hints( let sorted_l2_to_l1_msg_hints = get_split_order_hints_asc(previous_kernel.end.l2_to_l1_msgs, split_counter); - // unencrypted_logs - let sorted_unencrypted_log_hash_hints = - get_split_order_hints_asc(previous_kernel.end.unencrypted_logs_hashes, split_counter); + // contract_class_logs + let sorted_contract_class_log_hash_hints = get_split_order_hints_asc( + previous_kernel.end.contract_class_logs_hashes, + split_counter, + ); // public_call_requests let sorted_public_call_request_hints = @@ -32,7 +36,7 @@ pub unconstrained fn generate_tail_to_public_output_hints( TailToPublicOutputHints { sorted_l2_to_l1_msg_hints, - sorted_unencrypted_log_hash_hints, + sorted_contract_class_log_hash_hints, sorted_public_call_request_hints, } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr index 17a7023c65c..fb958f86876 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr @@ -396,7 +396,7 @@ mod tests { builder.previous_kernel.append_nullifiers(3); builder.add_pending_nullifier_read_request(1); - let nullifier_being_read = builder.previous_kernel.nullifiers.storage[2]; + let nullifier_being_read = builder.previous_kernel.nullifiers.get(2); let mut read_request = builder.previous_kernel.nullifier_read_requests.pop(); read_request.read_request.counter = nullifier_being_read.counter() - 1; builder.previous_kernel.nullifier_read_requests.push(read_request); @@ -418,12 +418,12 @@ mod tests { let remaining_note_hash_rr_index = builder.previous_kernel.add_read_request_for_pending_note_hash(1); let note_hash_rr = - builder.previous_kernel.note_hash_read_requests.storage[remaining_note_hash_rr_index]; + builder.previous_kernel.note_hash_read_requests.get(remaining_note_hash_rr_index); let remaining_nullifier_rr_index = builder.previous_kernel.add_read_request_for_pending_nullifier(1); let nullifier_rr = - builder.previous_kernel.nullifier_read_requests.storage[remaining_nullifier_rr_index]; + builder.previous_kernel.nullifier_read_requests.get(remaining_nullifier_rr_index); let key_validation_index = builder.previous_kernel.add_request_for_key_validation( Point { x: 1, y: 2, is_infinite: false }, @@ -433,7 +433,7 @@ mod tests { let key_validation = builder .previous_kernel .scoped_key_validation_requests_and_generators - .storage[key_validation_index]; + .get(key_validation_index); // Check that they have been propagated to the next kernel let result = builder.execute(); @@ -453,7 +453,7 @@ mod tests { builder.previous_kernel.append_nullifiers(2); // The nullifier at index 1 is nullifying the hash at index 0; builder.nullify_pending_note_hash(1, 0); - let nullifiers = builder.previous_kernel.nullifiers.storage; + let nullifiers = builder.previous_kernel.nullifiers.storage(); let public_inputs = builder.execute(); assert(is_empty_array(public_inputs.end.note_hashes)); @@ -470,9 +470,9 @@ mod tests { builder.previous_kernel.append_nullifiers(2); // The nullifier at index 1 is nullifying the hash at index 0; builder.nullify_pending_note_hash(1, 0); - let note_hashes = builder.previous_kernel.note_hashes.storage; - let nullifiers = builder.previous_kernel.nullifiers.storage; - let note_logs = builder.previous_kernel.note_encrypted_logs_hashes.storage; + let note_hashes = builder.previous_kernel.note_hashes.storage(); + let nullifiers = builder.previous_kernel.nullifiers.storage(); + let note_logs = builder.previous_kernel.note_encrypted_logs_hashes.storage(); let public_inputs = builder.execute(); // The 0th hash is chopped. @@ -494,7 +494,7 @@ mod tests { builder.nullify_pending_note_hash(1, 1); // The nullifier at index 2 is nullifying the hash at index 0; builder.nullify_pending_note_hash(2, 0); - let nullifiers = builder.previous_kernel.nullifiers.storage; + let nullifiers = builder.previous_kernel.nullifiers.storage(); let public_inputs = builder.execute(); assert(is_empty_array(public_inputs.end.note_hashes)); @@ -510,21 +510,17 @@ mod tests { builder.previous_kernel.append_note_hashes_with_logs(3); // Shuffle the note hashes so they will have to be re-ordered. - let tmp = builder.previous_kernel.note_hashes.storage[0]; - builder.previous_kernel.note_hashes.storage[0] = - builder.previous_kernel.note_hashes.storage[1]; - builder.previous_kernel.note_hashes.storage[1] = - builder.previous_kernel.note_hashes.storage[2]; - builder.previous_kernel.note_hashes.storage[2] = tmp; + let tmp = builder.previous_kernel.note_hashes.get(0); + builder.previous_kernel.note_hashes.set(0, builder.previous_kernel.note_hashes.get(1)); + builder.previous_kernel.note_hashes.set(1, builder.previous_kernel.note_hashes.get(2)); + builder.previous_kernel.note_hashes.set(2, tmp); builder.previous_kernel.append_nullifiers(3); // Shuffle the nullifers so they will have to be re-ordered. - let tmp = builder.previous_kernel.nullifiers.storage[1]; - builder.previous_kernel.nullifiers.storage[1] = - builder.previous_kernel.nullifiers.storage[3]; - builder.previous_kernel.nullifiers.storage[3] = - builder.previous_kernel.nullifiers.storage[2]; - builder.previous_kernel.nullifiers.storage[2] = tmp; + let tmp = builder.previous_kernel.nullifiers.get(1); + builder.previous_kernel.nullifiers.set(1, builder.previous_kernel.nullifiers.get(3)); + builder.previous_kernel.nullifiers.set(3, builder.previous_kernel.nullifiers.get(2)); + builder.previous_kernel.nullifiers.set(2, tmp); // The nullifier at index 1 is nullifying the note hash at index 1; builder.nullify_pending_note_hash(1, 1); @@ -533,7 +529,7 @@ mod tests { // The nullifier at index 3 is nullifying the note hash at index 0; builder.nullify_pending_note_hash(3, 0); - let nullifiers = builder.previous_kernel.nullifiers.storage; + let nullifiers = builder.previous_kernel.nullifiers.storage(); let public_inputs = builder.execute(); assert(is_empty_array(public_inputs.end.note_hashes)); @@ -590,10 +586,10 @@ mod tests { builder.previous_kernel.append_encrypted_log_hashes(3); builder.previous_kernel.nullifiers.storage[2].nullifier.note_hash = 9988; // Get ordered items before shuffling. - let note_hashes = builder.previous_kernel.note_hashes.storage; - let nullifiers = builder.previous_kernel.nullifiers.storage; - let note_logs = builder.previous_kernel.note_encrypted_logs_hashes.storage; - let encrypted_logs = builder.previous_kernel.encrypted_logs_hashes.storage; + let note_hashes = builder.previous_kernel.note_hashes.storage(); + let nullifiers = builder.previous_kernel.nullifiers.storage(); + let note_logs = builder.previous_kernel.note_encrypted_logs_hashes.storage(); + let encrypted_logs = builder.previous_kernel.encrypted_logs_hashes.storage(); // Shuffle. swap_items(&mut builder.previous_kernel.note_hashes, 1, 0); swap_items(&mut builder.previous_kernel.note_hashes, 3, 2); @@ -656,7 +652,7 @@ mod tests { // The nullifier at index 1 is siloed. builder.previous_kernel.nullifiers.storage[1].contract_address = AztecAddress::zero(); - let nullifiers = builder.previous_kernel.nullifiers.storage; + let nullifiers = builder.previous_kernel.nullifiers.storage(); let public_inputs = builder.execute(); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr index 0aca41a778c..08eae183bd0 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr @@ -57,9 +57,10 @@ mod tests { use dep::types::{ abis::{ gas::Gas, kernel_circuit_public_inputs::KernelCircuitPublicInputs, - log_hash::ScopedLogHash, max_block_number::MaxBlockNumber, + max_block_number::MaxBlockNumber, }, address::{AztecAddress, EthAddress}, + messaging::l2_to_l1_message::ScopedL2ToL1Message, point::Point, tests::fixture_builder::FixtureBuilder, traits::is_empty, @@ -122,60 +123,57 @@ mod tests { // Logs for the previous call stack. let prev_encrypted_logs_hash = 80; let prev_encrypted_log_preimages_length = 13; - let prev_unencrypted_logs_hash = 956; - let prev_unencrypted_log_preimages_length = 24; + let prev_contract_class_logs_hash = 956; + let prev_contract_class_log_preimages_length = 24; builder.previous_kernel.add_masked_encrypted_log_hash( prev_encrypted_logs_hash, prev_encrypted_log_preimages_length, ); - builder.previous_kernel.add_unencrypted_log_hash( - prev_unencrypted_logs_hash, - prev_unencrypted_log_preimages_length, + builder.previous_kernel.add_contract_class_log_hash( + prev_contract_class_logs_hash, + prev_contract_class_log_preimages_length, ); // Logs for the current call stack. - let unencrypted_logs_hash = 26; - let unencrypted_log_preimages_length = 50; - builder.previous_kernel.add_unencrypted_log_hash( - unencrypted_logs_hash, - unencrypted_log_preimages_length, + let encrypted_logs_hash = 26; + let encrypted_log_preimages_length = 50; + builder.previous_kernel.add_masked_encrypted_log_hash( + encrypted_logs_hash, + encrypted_log_preimages_length, ); let public_inputs = builder.execute(); assert_eq( public_inputs.end.encrypted_log_preimages_length, - prev_encrypted_log_preimages_length, + prev_encrypted_log_preimages_length + encrypted_log_preimages_length, ); assert_eq( - public_inputs.end.unencrypted_log_preimages_length, - unencrypted_log_preimages_length + prev_unencrypted_log_preimages_length, + public_inputs.end.contract_class_log_preimages_length, + prev_contract_class_log_preimages_length, ); } #[test] - fn ordering_of_unencrypted_logs() { + fn ordering_of_msgs() { let mut builder = PrivateKernelTailInputsBuilder::new(); - builder.previous_kernel.append_unencrypted_log_hashes(2); + builder.previous_kernel.append_l2_to_l1_msgs(2); - // Reorder the logs - let original_logs = builder.previous_kernel.unencrypted_logs_hashes.storage; - let mut reversed_logs = [ScopedLogHash::empty(); 2]; - for i in 0..reversed_logs.len() { - reversed_logs[i] = builder.previous_kernel.unencrypted_logs_hashes.pop(); + // Reorder the msgs + let original_msgs = builder.previous_kernel.l2_to_l1_msgs.storage; + let mut reversed_msgs = [ScopedL2ToL1Message::empty(); 2]; + for i in 0..reversed_msgs.len() { + reversed_msgs[i] = builder.previous_kernel.l2_to_l1_msgs.pop(); } - builder.previous_kernel.unencrypted_logs_hashes.extend_from_array(reversed_logs); + builder.previous_kernel.l2_to_l1_msgs.extend_from_array(reversed_msgs); let public_inputs = builder.execute(); - let resulting_encrypted_logs = public_inputs.end.unencrypted_logs_hashes; + let resulting_msgs = public_inputs.end.l2_to_l1_msgs; assert_eq( - resulting_encrypted_logs, - original_logs.map(|mut log: ScopedLogHash| { - log.log_hash.counter = 0; - log - }), + resulting_msgs, + original_msgs.map(|mut msg: ScopedL2ToL1Message| msg.expose_to_public()), ); } @@ -248,7 +246,7 @@ mod tests { DA_GAS_PER_BYTE * DA_BYTES_PER_FIELD * 1, L2_GAS_PER_NULLIFIER * 1, ); - assert_eq(public_inputs.end.gas_used, expected_gas_consumed); + assert_eq(public_inputs.gas_used, expected_gas_consumed); } #[test] @@ -268,7 +266,7 @@ mod tests { 4 * DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE, 1 * L2_GAS_PER_NULLIFIER, ), - public_inputs.end.gas_used, + public_inputs.gas_used, ); } @@ -277,10 +275,9 @@ mod tests { let mut builder = PrivateKernelTailInputsBuilder::new(); builder.previous_kernel.add_masked_encrypted_log_hash(42, 3); builder.previous_kernel.add_masked_encrypted_log_hash(42, 4); - builder.previous_kernel.add_unencrypted_log_hash(42, 5); + builder.previous_kernel.add_contract_class_log_hash(42, 12); builder.previous_kernel.end_setup(); builder.previous_kernel.add_masked_encrypted_log_hash(42, 6); - builder.previous_kernel.add_unencrypted_log_hash(42, 7); let public_inputs = builder.execute(); @@ -290,7 +287,7 @@ mod tests { (1 * DA_BYTES_PER_FIELD + 25) * DA_GAS_PER_BYTE, 1 * L2_GAS_PER_NULLIFIER + 25 * L2_GAS_PER_LOG_BYTE, ), - public_inputs.end.gas_used, + public_inputs.gas_used, ); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr index 0dbd3cd46f6..fdc7a788ce9 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr @@ -170,21 +170,12 @@ mod tests { [output_nullifiers[3], output_nullifiers[4]], ); - assert_eq( - public_inputs.revertible_accumulated_data.gas_used, - Gas::new( - 2 * DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE, - 2 * L2_GAS_PER_NULLIFIER, - ), - ); - assert_eq( - public_inputs.non_revertible_accumulated_data.gas_used, - Gas::new( - 3 * DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE, - FIXED_AVM_STARTUP_L2_GAS + 3 * L2_GAS_PER_NULLIFIER, - ) - + Gas::tx_overhead(), - ); + let num_nullifiers = 1 /* tx nullifier */ + + 2 /* non-revertible */ + + 2 /* revertible */; + let da_gas = num_nullifiers * DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE; + let l2_gas = FIXED_AVM_STARTUP_L2_GAS + num_nullifiers * L2_GAS_PER_NULLIFIER; + assert_eq(public_inputs.gas_used, Gas::tx_overhead() + Gas::new(da_gas, l2_gas)); } #[test] @@ -213,21 +204,14 @@ mod tests { [exposed_note_hashes[2], exposed_note_hashes[3]], ); - assert_eq( - public_inputs.revertible_accumulated_data.gas_used, - Gas::new( - (2 * DA_BYTES_PER_FIELD) * DA_GAS_PER_BYTE, - 2 * L2_GAS_PER_NOTE_HASH, - ), - ); - assert_eq( - public_inputs.non_revertible_accumulated_data.gas_used, - Gas::new( - (3 * DA_BYTES_PER_FIELD) * DA_GAS_PER_BYTE, - FIXED_AVM_STARTUP_L2_GAS + L2_GAS_PER_NULLIFIER + 2 * L2_GAS_PER_NOTE_HASH, - ) - + Gas::tx_overhead(), - ); + let num_note_hashes = 2 /* non-revertible */ + + 2 /* revertible */; + let num_side_effects = num_note_hashes + 1 /* tx nullifier */; + let da_gas = (num_side_effects * DA_BYTES_PER_FIELD) * DA_GAS_PER_BYTE; + let l2_gas = FIXED_AVM_STARTUP_L2_GAS + + L2_GAS_PER_NULLIFIER + + num_note_hashes * L2_GAS_PER_NOTE_HASH; + assert_eq(public_inputs.gas_used, Gas::tx_overhead() + Gas::new(da_gas, l2_gas)); } #[test(should_fail_with = "Non empty note hash read requests")] @@ -264,42 +248,57 @@ mod tests { builder.previous_kernel.end_setup(); let public_inputs = builder.execute(); - assert_eq(public_inputs.revertible_accumulated_data.gas_used, Gas::empty()); - - let expected_non_revertible_gas_used = Gas::tx_overhead() - + Gas::new( - DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE * 1, - L2_GAS_PER_NULLIFIER * 1 + FIXED_AVM_STARTUP_L2_GAS, - ); - - assert_eq( - public_inputs.non_revertible_accumulated_data.gas_used, - expected_non_revertible_gas_used, - ); + let da_gas = DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE * 1; + let l2_gas = L2_GAS_PER_NULLIFIER * 1 + FIXED_AVM_STARTUP_L2_GAS; + assert_eq(public_inputs.gas_used, Gas::tx_overhead() + Gas::new(da_gas, l2_gas)); } #[test] unconstrained fn enqueued_public_calls_consume_startup_gas() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); + + let teardown_gas_limits = Gas::new(1, 2); + builder.previous_kernel.tx_context.gas_settings.teardown_gas_limits = teardown_gas_limits; + // add an extra non-revertible call builder.previous_kernel.append_public_call_requests(1); builder.previous_kernel.end_setup(); // add some revertible calls builder.previous_kernel.append_public_call_requests(3); + let public_inputs = builder.execute(); - let expected_revertible_gas_used = Gas::new(0, 3 * FIXED_AVM_STARTUP_L2_GAS); - assert_eq(public_inputs.revertible_accumulated_data.gas_used, expected_revertible_gas_used); + let num_public_calls = 2 /* non-revertible */ + + 3 /* revertible */; + let da_gas = DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE * 1; + let l2_gas = L2_GAS_PER_NULLIFIER * 1 + num_public_calls * FIXED_AVM_STARTUP_L2_GAS; + assert_eq(public_inputs.gas_used, Gas::tx_overhead() + Gas::new(da_gas, l2_gas)); + } + + #[test] + unconstrained fn enqueued_public_calls_with_teardown_gas() { + let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); - let expected_non_revertible_gas_used = Gas::tx_overhead() - + Gas::new( - DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE * 1, - L2_GAS_PER_NULLIFIER * 1 + 2 * FIXED_AVM_STARTUP_L2_GAS, - ); + let teardown_gas_limits = Gas::new(1, 2); + builder.previous_kernel.tx_context.gas_settings.teardown_gas_limits = teardown_gas_limits; + // add an extra non-revertible call + builder.previous_kernel.append_public_call_requests(1); + builder.previous_kernel.end_setup(); + // add some revertible calls + builder.previous_kernel.append_public_call_requests(3); + // add a teardown call + builder.previous_kernel.set_public_teardown_call_request(); + + let public_inputs = builder.execute(); + + let num_public_calls = 2 /* non-revertible */ + + 3 /* revertible */; + let da_gas = DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE * 1; + let l2_gas = L2_GAS_PER_NULLIFIER * 1 + num_public_calls * FIXED_AVM_STARTUP_L2_GAS; assert_eq( - public_inputs.non_revertible_accumulated_data.gas_used, - expected_non_revertible_gas_used, + public_inputs.gas_used, + Gas::tx_overhead() + Gas::new(da_gas, l2_gas) + teardown_gas_limits, ); } @@ -314,18 +313,12 @@ mod tests { let public_inputs = builder.execute(); - assert_eq( - Gas::new(1 * DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE, 0), - public_inputs.revertible_accumulated_data.gas_used, - ); - assert_eq( - Gas::tx_overhead() - + Gas::new( - 3 * DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE, - FIXED_AVM_STARTUP_L2_GAS + 1 * L2_GAS_PER_NULLIFIER, - ), - public_inputs.non_revertible_accumulated_data.gas_used, - ); + let num_msgs = 2 /* non-revertible */ + + 1 /* revertible */; + let num_side_effects = num_msgs + 1 /* tx nullifier */; + let da_gas = num_side_effects * DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE; + let l2_gas = FIXED_AVM_STARTUP_L2_GAS + 1 * L2_GAS_PER_NULLIFIER; + assert_eq(public_inputs.gas_used, Gas::tx_overhead() + Gas::new(da_gas, l2_gas)); } #[test] @@ -333,26 +326,18 @@ mod tests { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); builder.previous_kernel.add_masked_encrypted_log_hash(42, 3); builder.previous_kernel.add_masked_encrypted_log_hash(42, 4); - builder.previous_kernel.add_unencrypted_log_hash(42, 5); + builder.previous_kernel.add_contract_class_log_hash(42, 12); builder.previous_kernel.end_setup(); builder.previous_kernel.add_masked_encrypted_log_hash(42, 6); - builder.previous_kernel.add_unencrypted_log_hash(42, 7); let public_inputs = builder.execute(); - assert_eq( - Gas::new(13 * DA_GAS_PER_BYTE, 13 * L2_GAS_PER_LOG_BYTE), - public_inputs.revertible_accumulated_data.gas_used, - ); - - assert_eq( - Gas::tx_overhead() - + Gas::new( - (1 * DA_BYTES_PER_FIELD + 12) * DA_GAS_PER_BYTE, - FIXED_AVM_STARTUP_L2_GAS + 1 * L2_GAS_PER_NULLIFIER + 12 * L2_GAS_PER_LOG_BYTE, - ), - public_inputs.non_revertible_accumulated_data.gas_used, - ); + let num_log_bytes = 3 + 4 + 12 + 6; + let da_gas = (1 * DA_BYTES_PER_FIELD + num_log_bytes) * DA_GAS_PER_BYTE; + let l2_gas = FIXED_AVM_STARTUP_L2_GAS + + 1 * L2_GAS_PER_NULLIFIER + + num_log_bytes * L2_GAS_PER_LOG_BYTE; + assert_eq(public_inputs.gas_used, Gas::tx_overhead() + Gas::new(da_gas, l2_gas)); } #[test(should_fail_with = "The gas used exceeds the gas limits")] diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/mod.nr index 58b753d3b01..606b05a0120 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/mod.nr @@ -56,7 +56,7 @@ impl PrivateCallDataValidatorBuilder { let mut accumulated_note_hashes = self.previous_note_hashes; accumulated_note_hashes.extend_from_bounded_vec(self.private_call.note_hashes); PrivateCallDataValidator::new(private_call).validate( - accumulated_note_hashes.storage, + accumulated_note_hashes.storage(), self.private_call.protocol_contract_tree_root, ); } @@ -79,7 +79,7 @@ impl PrivateCallDataValidatorBuilder { pub fn validate_with_private_call_data(self, data: PrivateCallData) { let accumulated_note_hashes = self.previous_note_hashes; PrivateCallDataValidator::new(data).validate( - accumulated_note_hashes.storage, + accumulated_note_hashes.storage(), self.private_call.protocol_contract_tree_root, ); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_arrays.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_arrays.nr index 4e376e0f635..10daa7a993a 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_arrays.nr @@ -109,13 +109,3 @@ fn validate_arrays_malformed_encrypted_logs_hashes_fails() { builder.validate(); } - -#[test(should_fail_with = "invalid array")] -fn validate_arrays_malformed_unencrypted_logs_hashes_fails() { - let mut builder = PrivateCallDataValidatorBuilder::new(); - - builder.private_call.append_unencrypted_log_hashes(1); - unshift_empty_item(&mut builder.private_call.unencrypted_logs_hashes); - - builder.validate(); -} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call.nr index 22504557f46..37b5c400c23 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call.nr @@ -57,11 +57,22 @@ fn validate_call_is_static_creating_encrypted_logs_hashes_fails() { builder.validate(); } -#[test(should_fail_with = "unencrypted_logs_hashes must be empty for static calls")] -fn validate_call_is_static_creating_unencrypted_logs_hashes_fails() { +#[test(should_fail_with = "contract_class_logs_hashes must be empty for static calls")] +fn validate_call_is_static_creating_contract_class_logs_hashes_fails() { let mut builder = PrivateCallDataValidatorBuilder::new().is_static_call(); - builder.private_call.append_unencrypted_log_hashes(1); + builder.private_call.add_contract_class_log_hash(1, 2); + + builder.validate(); +} + +#[test(should_fail_with = "only the class registerer may emit contract class logs")] +fn validate_call_is_from_class_registerer_fails() { + let mut builder = PrivateCallDataValidatorBuilder::new(); + + builder.private_call.add_contract_class_log_hash(1, 2); + // set the contract address to be some msg sender (!= REGISTERER_CONTRACT_ADDRESS) + builder.private_call.contract_address = builder.private_call.msg_sender; builder.validate(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_previous_kernel.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_previous_kernel.nr index dbc0b8e954c..b7bb2d4ea67 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_previous_kernel.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_previous_kernel.nr @@ -262,25 +262,24 @@ fn validate_propagated_from_previous_kernel_encrypted_log_hashes_less_than_fails } /** - * unencrypted_log_hashes + * contract_class_log_hashes */ #[test] -fn validate_propagated_from_previous_kernel_unencrypted_log_hashes_succeeds() { +fn validate_propagated_from_previous_kernel_contract_class_log_hashes_succeeds() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.previous_kernel.append_unencrypted_log_hashes(2); - builder.output.append_unencrypted_log_hashes(2); + builder.previous_kernel.add_contract_class_log_hash(2, 1); + builder.output.add_contract_class_log_hash(2, 1); builder.validate_as_inner_call(); } -#[test(should_fail_with = "source item does not prepend to dest")] -fn validate_propagated_from_previous_kernel_unencrypted_log_hashes_less_than_fails() { +#[test(should_fail_with = "output should be appended with empty items")] +fn validate_propagated_from_previous_kernel_contract_class_log_hashes_less_than_fails() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.previous_kernel.append_unencrypted_log_hashes(2); // Propagate 1 less item to the output. - builder.output.append_unencrypted_log_hashes(1); + builder.output.add_contract_class_log_hash(2, 1); builder.validate_as_inner_call(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_private_call.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_private_call.nr index 897267ba89f..9028ded0bb6 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_private_call.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_private_call.nr @@ -369,25 +369,24 @@ fn validate_propagated_from_private_call_encrypted_log_hashes_output_one_more_fa } /** - * unencrypted_log_hashes + * contract_class_log_hashes */ #[test] -fn validate_propagated_from_private_call_unencrypted_log_hashes_succeeds() { +fn validate_propagated_from_private_call_contract_class_log_hashes_succeeds() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.private_call.append_unencrypted_log_hashes(2); - builder.output.append_unencrypted_log_hashes(2); + builder.private_call.add_contract_class_log_hash(2, 1); + builder.output.add_contract_class_log_hash(2, 1); builder.validate_as_inner_call(); } #[test(should_fail_with = "output should be appended with empty items")] -fn validate_propagated_from_private_call_unencrypted_log_hashes_output_one_more_fails() { +fn validate_propagated_from_private_call_contract_class_log_hashes_output_one_more_fails() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.private_call.append_unencrypted_log_hashes(2); // Propagate 1 more item to the output. - builder.output.append_unencrypted_log_hashes(3); + builder.output.add_contract_class_log_hash(2, 1); builder.validate_as_inner_call(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_previous_kernel_with_private_call.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_previous_kernel_with_private_call.nr index d11b387c074..5a2b04052f7 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_previous_kernel_with_private_call.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_previous_kernel_with_private_call.nr @@ -225,20 +225,15 @@ fn new_from_previous_kernel_with_private_call_encrypted_log_hashes_succeeds() { } #[test] -fn new_from_previous_kernel_with_private_call_unencrypted_log_hashes_succeeds() { +fn new_from_previous_kernel_with_private_call_contract_class_log_hashes_succeeds() { let mut builder = PrivateKernelCircuitPublicInputsComposerBuilder::new(); - builder.previous_kernel.append_unencrypted_log_hashes(2); - let prev = builder.previous_kernel.unencrypted_logs_hashes.storage; - builder.private_call.append_unencrypted_log_hashes(2); - let curr = builder.private_call.unencrypted_logs_hashes.storage; + builder.private_call.add_contract_class_log_hash(2, 200); + let curr = builder.private_call.contract_class_logs_hashes.storage; let output = builder.compose_from_previous_kernel(); - assert_array_eq( - output.end.unencrypted_logs_hashes, - [prev[0], prev[1], curr[0], curr[1]], - ); + assert_array_eq(output.end.contract_class_logs_hashes, [curr[0]]); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/propagate_from_private_call.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/propagate_from_private_call.nr index 07094557fd3..0206f75d389 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/propagate_from_private_call.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/propagate_from_private_call.nr @@ -161,15 +161,15 @@ fn propagate_from_private_call_encrypted_log_hashes_succeeds() { } #[test] -fn propagate_from_private_call_unencrypted_log_hashes_succeeds() { +fn propagate_from_private_call_contract_class_log_hashes_succeeds() { let mut builder = PrivateKernelCircuitPublicInputsComposerBuilder::new(); - builder.private_call.append_unencrypted_log_hashes(2); - let res = builder.private_call.unencrypted_logs_hashes.storage; + builder.private_call.add_contract_class_log_hash(2, 200); + let res = builder.private_call.contract_class_logs_hashes.storage; let output = builder.compose_from_tx_request(); - assert_array_eq(output.end.unencrypted_logs_hashes, [res[0], res[1]]); + assert_array_eq(output.end.contract_class_logs_hashes, [res[0]]); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/meter_gas_used.nr index 9759093dafa..82fff15a88d 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/meter_gas_used.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/meter_gas_used.nr @@ -58,10 +58,6 @@ fn meter_gas_used_everything_succeeds() { metered_da_bytes += 6; computed_l2_gas += 6 * L2_GAS_PER_LOG_BYTE; - builder.add_unencrypted_log_hash(3001, 51); - metered_da_bytes += 51; - computed_l2_gas += 51 * L2_GAS_PER_LOG_BYTE; - let data = builder.to_combined_accumulated_data(); let gas = meter_gas_used(data); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr index 89b81810ca1..a624732fde9 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr @@ -40,7 +40,7 @@ impl TailOutputValidatorBuilder { pub fn export_output(self) -> KernelCircuitPublicInputs { let mut output = self.output.to_kernel_circuit_public_inputs(); - output.end.gas_used = meter_gas_used(output.end); + output.gas_used = meter_gas_used(output.end); output } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_empty_values.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_empty_values.nr index 0ba030cc914..2e4be7bed2f 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_empty_values.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_empty_values.nr @@ -24,3 +24,12 @@ fn validate_empty_values_non_empty_revert_code_fails() { builder.validate(); } +#[test(should_fail_with = "unencrypted logs in private must be empty")] +fn validate_empty_values_non_empty_unencrypted_log_fails() { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.output.add_unencrypted_log_hash(1, 2); + + builder.validate(); +} + diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_gas_used.nr index 5f9b63587f2..f8393d50aa7 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_gas_used.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_gas_used.nr @@ -27,7 +27,7 @@ fn validate_gas_used_wrong_da_gas_fails() { let mut output = builder.export_output(); // Tweak the da gas in the output to be a wrong value. - output.end.gas_used.da_gas += 1; + output.gas_used.da_gas += 1; builder.validate_with_output(output); } @@ -38,7 +38,7 @@ fn validate_gas_used_wrong_l2_gas_fails() { let mut output = builder.export_output(); // Tweak the l2 gas in the output to be a wrong value. - output.end.gas_used.l2_gas += 1; + output.gas_used.l2_gas += 1; builder.validate_with_output(output); } @@ -48,7 +48,7 @@ fn validate_gas_used_exceed_da_limit_fails() { let mut builder = TailOutputValidatorBuilder::new_with_data(); let mut output = builder.export_output(); - let gas_used = output.end.gas_used.da_gas; + let gas_used = output.gas_used.da_gas; // Tweak the da gas limit to be less than the gas used. output.constants.tx_context.gas_settings.gas_limits.da_gas = gas_used - 1; // Constants must match. @@ -62,7 +62,7 @@ fn validate_gas_used_exceed_l2_limit_fails() { let mut builder = TailOutputValidatorBuilder::new_with_data(); let mut output = builder.export_output(); - let gas_used = output.end.gas_used.l2_gas; + let gas_used = output.gas_used.l2_gas; // Tweak the l2 gas limit to be less than the gas used. output.constants.tx_context.gas_settings.gas_limits.l2_gas = gas_used - 1; // Constants must match. diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_sorted_values.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_sorted_values.nr index e927ed83e6a..68924be6824 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_sorted_values.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_sorted_values.nr @@ -38,40 +38,26 @@ fn validate_propagated_sorted_values_l2_to_l1_msgs_mismatch_hash_fails() { } /** - * unencrypted_log_hashes + * contract_class_log_hashes */ #[test] -fn validate_propagated_sorted_values_unencrypted_log_hashes_succeeds() { +fn validate_propagated_sorted_values_contract_class_log_hashes_succeeds() { let mut builder = TailOutputValidatorBuilder::new(); - builder.previous_kernel.append_unencrypted_log_hashes(3); - builder.output.append_unencrypted_log_hashes(3); - builder.output.hash_unencrypted_log_hashes(); - - builder.validate(); -} - -#[test] -fn validate_propagated_sorted_values_unencrypted_log_hashes_unordered_succeeds() { - let mut builder = TailOutputValidatorBuilder::new(); - - builder.previous_kernel.append_unencrypted_log_hashes(3); - // Swap the items at index 0 and 2. - swap_items(&mut builder.previous_kernel.unencrypted_logs_hashes, 0, 2); - builder.output.append_unencrypted_log_hashes(3); - builder.output.hash_unencrypted_log_hashes(); + builder.previous_kernel.add_contract_class_log_hash(3, 2); + builder.output.add_contract_class_log_hash(3, 2); builder.validate(); } #[test(should_fail_with = "incorrect transformed value")] -fn validate_propagated_sorted_values_unencrypted_log_hashes_wrong_order_fails() { +fn validate_propagated_sorted_values_contract_class_log_hashes_mismatch_fails() { let mut builder = TailOutputValidatorBuilder::new(); - builder.previous_kernel.append_unencrypted_log_hashes(3); - builder.output.append_unencrypted_log_hashes(3); - // Swap the items in the output, making them out of order - swap_items(&mut builder.output.unencrypted_logs_hashes, 0, 2); + builder.previous_kernel.add_contract_class_log_hash(3, 2); + builder.output.add_contract_class_log_hash(3, 2); + // Tweak the content in the output. + builder.output.contract_class_logs_hashes.storage[0].log_hash.value += 1; builder.validate(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr index e684d244c33..1257df16703 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr @@ -1,8 +1,6 @@ -use crate::components::tail_to_public_output_composer::meter_gas_used::{ - meter_gas_used_non_revertible, meter_gas_used_revertible, -}; +use crate::components::tail_to_public_output_composer::meter_gas_used::meter_gas_used; use dep::types::{ - abis::gas::Gas, + abis::{gas::Gas, public_call_request::PublicCallRequest}, constants::{ DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, FIXED_AVM_STARTUP_L2_GAS, L2_GAS_PER_LOG_BYTE, L2_GAS_PER_NOTE_HASH, L2_GAS_PER_NULLIFIER, @@ -11,75 +9,72 @@ use dep::types::{ }; #[test] -fn meter_gas_used_non_revertible_empty_succeeds() { +fn meter_gas_used_empty_succeeds() { let builder = FixtureBuilder::new(); - let data = builder.to_private_to_public_accumulated_data(); - let gas = meter_gas_used_non_revertible(data); + let empty_data = builder.to_private_to_public_accumulated_data(); + let teardown_call_request = PublicCallRequest::empty(); + let teardown_gas_limits = Gas::new(1, 2); + let gas = meter_gas_used( + empty_data, + empty_data, + teardown_call_request, + teardown_gas_limits, + ); assert_eq(gas, Gas::tx_overhead()); } #[test] -fn meter_gas_used_non_revertible_everything_succeeds() { - let mut builder = FixtureBuilder::new(); +fn meter_gas_used_with_teardown_call_succeeds() { + let builder = FixtureBuilder::new(); + let empty_data = builder.to_private_to_public_accumulated_data(); - builder.append_note_hashes(4); - builder.append_nullifiers(3); - builder.append_l2_to_l1_msgs(1); - builder.add_note_encrypted_log_hash(1001, 12, 0); - builder.add_note_encrypted_log_hash(1002, 8, 0); - builder.add_note_encrypted_log_hash(1003, 20, 0); - builder.add_encrypted_log_hash(2001, 2); - builder.add_encrypted_log_hash(2002, 6); - builder.add_unencrypted_log_hash(3001, 51); - builder.append_public_call_requests(2); - builder.end_setup(); + let mut teardown_call_request = PublicCallRequest::empty(); + teardown_call_request.contract_address = builder.contract_address; - let data = builder.to_private_to_public_accumulated_data(); - let gas = meter_gas_used_non_revertible(data); + let teardown_gas_limits = Gas::new(1, 2); - let total_num_side_effects = 4 + 3 + 1; - let total_log_length = 12 - + 8 - + 20 // note_encrypted_log_hash - + 2 - + 6 // encrypted_log_hash - + 51; // unencrypted_log_hash - let computed_da_gas = - (total_num_side_effects * DA_BYTES_PER_FIELD + total_log_length) * DA_GAS_PER_BYTE; - let computed_l2_gas = 4 * L2_GAS_PER_NOTE_HASH - + 3 * L2_GAS_PER_NULLIFIER - + total_log_length * L2_GAS_PER_LOG_BYTE - + 2 * FIXED_AVM_STARTUP_L2_GAS; - - assert_eq(gas, Gas::new(computed_da_gas, computed_l2_gas) + Gas::tx_overhead()); + let gas = meter_gas_used( + empty_data, + empty_data, + teardown_call_request, + teardown_gas_limits, + ); + assert_eq(gas, Gas::tx_overhead() + teardown_gas_limits); } #[test] -fn meter_gas_used_revertible_empty_succeeds() { - let builder = FixtureBuilder::new(); - let data = builder.to_private_to_public_accumulated_data(); - let gas = meter_gas_used_revertible(data); - assert_eq(gas, Gas::empty()); -} +fn meter_gas_used_everything_succeeds() { + let mut non_revertible_builder = FixtureBuilder::new(); + let mut revertible_builder = FixtureBuilder::new(); -#[test] -fn meter_gas_used_revertible_everything_succeeds() { - let mut builder = FixtureBuilder::new(); + non_revertible_builder.append_note_hashes(3); + non_revertible_builder.append_nullifiers(1); + non_revertible_builder.append_l2_to_l1_msgs(0); + non_revertible_builder.add_note_encrypted_log_hash(1001, 12, 0); + non_revertible_builder.add_encrypted_log_hash(2001, 2); + non_revertible_builder.add_contract_class_log_hash(3001, 51); + non_revertible_builder.append_public_call_requests(1); + + revertible_builder.append_note_hashes(1); + revertible_builder.append_nullifiers(2); + revertible_builder.append_l2_to_l1_msgs(1); + revertible_builder.add_note_encrypted_log_hash(1002, 8, 0); + revertible_builder.add_note_encrypted_log_hash(1003, 20, 0); + revertible_builder.add_encrypted_log_hash(2002, 6); + revertible_builder.append_public_call_requests(1); - builder.append_note_hashes(4); - builder.append_nullifiers(3); - builder.append_l2_to_l1_msgs(1); - builder.add_note_encrypted_log_hash(1001, 12, 0); - builder.add_note_encrypted_log_hash(1002, 8, 0); - builder.add_note_encrypted_log_hash(1003, 20, 0); - builder.add_encrypted_log_hash(2001, 2); - builder.add_encrypted_log_hash(2002, 6); - builder.add_unencrypted_log_hash(3001, 51); - builder.append_public_call_requests(2); - builder.end_setup(); + let non_revertible_data = non_revertible_builder.to_private_to_public_accumulated_data(); + let revertible_data = revertible_builder.to_private_to_public_accumulated_data(); + let mut teardown_call_request = PublicCallRequest::empty(); + teardown_call_request.contract_address = non_revertible_builder.contract_address; + let teardown_gas_limits = Gas::new(1, 2); - let data = builder.to_private_to_public_accumulated_data(); - let gas = meter_gas_used_revertible(data); + let gas = meter_gas_used( + non_revertible_data, + revertible_data, + teardown_call_request, + teardown_gas_limits, + ); let total_num_side_effects = 4 + 3 + 1; let total_log_length = 12 @@ -87,7 +82,7 @@ fn meter_gas_used_revertible_everything_succeeds() { + 20 // note_encrypted_log_hash + 2 + 6 // encrypted_log_hash - + 51; // unencrypted_log_hash + + 51; // contract_class_log_hash let computed_da_gas = (total_num_side_effects * DA_BYTES_PER_FIELD + total_log_length) * DA_GAS_PER_BYTE; let computed_l2_gas = 4 * L2_GAS_PER_NOTE_HASH @@ -95,5 +90,8 @@ fn meter_gas_used_revertible_everything_succeeds() { + total_log_length * L2_GAS_PER_LOG_BYTE + 2 * FIXED_AVM_STARTUP_L2_GAS; - assert_eq(gas, Gas::new(computed_da_gas, computed_l2_gas)); + assert_eq( + gas, + Gas::new(computed_da_gas, computed_l2_gas) + Gas::tx_overhead() + teardown_gas_limits, + ); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr index 5faddeca1dc..6617e5abbfa 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr @@ -11,7 +11,7 @@ fn split_to_public_succeeds() { builder.append_l2_to_l1_msgs(1); builder.append_note_encrypted_log_hashes(3); builder.append_encrypted_log_hashes(2); - builder.append_unencrypted_log_hashes(1); + builder.add_contract_class_log_hash(2, 200); builder.append_public_call_requests(1); builder.end_setup(); // Revertibles. @@ -20,7 +20,6 @@ fn split_to_public_succeeds() { builder.append_l2_to_l1_msgs(1); builder.append_note_encrypted_log_hashes(1); builder.append_encrypted_log_hashes(2); - builder.append_unencrypted_log_hashes(1); builder.append_public_call_requests(2); let combined_data = builder.to_private_to_public_accumulated_data(); @@ -65,10 +64,10 @@ fn split_to_public_succeeds() { ); assert_array_eq(revertible.encrypted_logs_hashes, [expected[2], expected[3]]); - // unencrypted_logs_hashes - let expected = combined_data.unencrypted_logs_hashes; - assert_array_eq(non_revertible.unencrypted_logs_hashes, [expected[0]]); - assert_array_eq(revertible.unencrypted_logs_hashes, [expected[1]]); + // contract_class_logs_hashes + let expected = combined_data.contract_class_logs_hashes; + assert_array_eq(non_revertible.contract_class_logs_hashes, [expected[0]]); + assert_array_eq(revertible.contract_class_logs_hashes, []); // public_call_requests let call_requests = combined_data.public_call_requests; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr index 7910d8f2000..ea5e7c6362d 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr @@ -12,8 +12,8 @@ use dep::types::{ fn tail_to_public_output_composer_succeeds() { let mut builder = TailToPublicOutputComposerBuilder::new(); - let teardown_gas = Gas::new(789, 3254); - builder.previous_kernel.tx_context.gas_settings.teardown_gas_limits = teardown_gas; + let teardown_gas_limits = Gas::new(789, 3254); + builder.previous_kernel.tx_context.gas_settings.teardown_gas_limits = teardown_gas_limits; // Non-revertibles. builder.previous_kernel.append_siloed_note_hashes(4); @@ -27,14 +27,15 @@ fn tail_to_public_output_composer_succeeds() { builder.previous_kernel.add_masked_encrypted_log_hash(2001, 2); - builder.previous_kernel.add_unencrypted_log_hash(3001, 51); - builder.previous_kernel.add_unencrypted_log_hash(3002, 9); + builder.previous_kernel.add_contract_class_log_hash(3002, 9); builder.previous_kernel.append_public_call_requests(2); builder.previous_kernel.end_setup(); // Revertibles. + builder.previous_kernel.set_public_teardown_call_request(); + builder.previous_kernel.append_siloed_note_hashes(2); builder.previous_kernel.append_siloed_nullifiers(1); @@ -46,8 +47,6 @@ fn tail_to_public_output_composer_succeeds() { builder.previous_kernel.add_masked_encrypted_log_hash(2002, 6); builder.previous_kernel.add_masked_encrypted_log_hash(2003, 24); - builder.previous_kernel.add_unencrypted_log_hash(3002, 4); - builder.previous_kernel.append_public_call_requests(3); // Get ordered items before shuffling for verifying with the output later. @@ -55,7 +54,6 @@ fn tail_to_public_output_composer_succeeds() { // Shuffle ordered items. swap_items(&mut builder.previous_kernel.l2_to_l1_msgs, 0, 1); - swap_items(&mut builder.previous_kernel.unencrypted_logs_hashes, 0, 2); swap_items(&mut builder.previous_kernel.public_call_requests, 1, 2); // Output. @@ -113,15 +111,11 @@ fn tail_to_public_output_composer_succeeds() { [log_hashes[1], log_hashes[2]], ); - // unencrypted_logs_hashes - let log_hashes = data.unencrypted_logs_hashes; + // contract_class_logs_hashes + let log_hashes = data.contract_class_logs_hashes; assert_array_eq( - output.non_revertible_accumulated_data.unencrypted_logs_hashes, - [log_hashes[0], log_hashes[1]], - ); - assert_array_eq( - output.revertible_accumulated_data.unencrypted_logs_hashes, - [log_hashes[2]], + output.non_revertible_accumulated_data.contract_class_logs_hashes, + [log_hashes[0]], ); // public_call_requests @@ -137,37 +131,36 @@ fn tail_to_public_output_composer_succeeds() { ); // Gas: non-revertible - let total_num_side_effects = 4 + 3 + 1; - let total_log_length = 12 + let mut num_note_hashes = 4; + let mut num_nullifiers = 3; + let mut num_msgs = 1; + let mut num_public_calls = 2; + let mut total_log_length = 12 + 8 // note_encrypted_log_hash + 2 // encrypted_log_hash - + 51 - + 9; // unencrypted_log_hash - let computed_da_gas = - (total_num_side_effects * DA_BYTES_PER_FIELD + total_log_length) * DA_GAS_PER_BYTE; - let computed_l2_gas = 4 * L2_GAS_PER_NOTE_HASH - + 3 * L2_GAS_PER_NULLIFIER - + total_log_length * L2_GAS_PER_LOG_BYTE - + 2 * FIXED_AVM_STARTUP_L2_GAS; - assert_eq( - output.non_revertible_accumulated_data.gas_used, - Gas::new(computed_da_gas, computed_l2_gas) + Gas::tx_overhead(), - ); - + + 9; // contract_class_log_hash // Gas: revertible - let total_num_side_effects = 2 + 1 + 1; - let total_log_length = 20 // note_encrypted_log_hash - + 6 - + 24 // encrypted_log_hash - + 4; // unencrypted_log_hash + { + num_note_hashes += 2; + num_nullifiers += 1; + num_public_calls += 3; + num_msgs += 1; + total_log_length += 20 // note_encrypted_log_hash + + 6 + + 24; // encrypted_log_hash + } + + let num_da_effects = num_note_hashes + num_nullifiers + num_msgs; let computed_da_gas = - (total_num_side_effects * DA_BYTES_PER_FIELD + total_log_length) * DA_GAS_PER_BYTE; - let computed_l2_gas = 2 * L2_GAS_PER_NOTE_HASH - + 1 * L2_GAS_PER_NULLIFIER + (num_da_effects * DA_BYTES_PER_FIELD + total_log_length) * DA_GAS_PER_BYTE; + + let computed_l2_gas = num_note_hashes * L2_GAS_PER_NOTE_HASH + + num_nullifiers * L2_GAS_PER_NULLIFIER + total_log_length * L2_GAS_PER_LOG_BYTE - + 3 * FIXED_AVM_STARTUP_L2_GAS; + + num_public_calls * FIXED_AVM_STARTUP_L2_GAS; + assert_eq( - output.revertible_accumulated_data.gas_used, - Gas::new(computed_da_gas, computed_l2_gas), + output.gas_used, + Gas::tx_overhead() + Gas::new(computed_da_gas, computed_l2_gas) + teardown_gas_limits, ); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_validator_builder.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_validator_builder.nr index ae18dddbf04..0a71296ba82 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_validator_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_validator_builder.nr @@ -1,13 +1,13 @@ use crate::components::tail_to_public_output_validator::TailToPublicOutputValidator; use dep::types::tests::fixture_builder::FixtureBuilder; -pub struct TailToPublicOutputValidatorBuilder { - output: FixtureBuilder, - previous_kernel: FixtureBuilder, +pub(crate) struct TailToPublicOutputValidatorBuilder { + pub(crate) output: FixtureBuilder, + pub(crate) previous_kernel: FixtureBuilder, } impl TailToPublicOutputValidatorBuilder { - pub fn new() -> Self { + pub(crate) fn new() -> Self { let mut output = FixtureBuilder::new(); let mut previous_kernel = FixtureBuilder::new(); output.set_first_nullifier(); @@ -15,7 +15,7 @@ impl TailToPublicOutputValidatorBuilder { TailToPublicOutputValidatorBuilder { output, previous_kernel } } - pub fn validate(self) { + pub(crate) fn validate(self) { // TODO: Split the data using min_revertible_side_effect_counter in FixtureBuilder. let revertible = true; let output = self.output.to_private_to_public_kernel_circuit_public_inputs(revertible); diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/enqueued_call_data_validator.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/enqueued_call_data_validator.nr deleted file mode 100644 index e09e427bfeb..00000000000 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/enqueued_call_data_validator.nr +++ /dev/null @@ -1,129 +0,0 @@ -use crate::public_kernel_phase::PublicKernelPhase; -use dep::types::{ - abis::{ - accumulated_data::PublicAccumulatedDataArrayLengths, enqueued_call_data::EnqueuedCallData, - kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, - public_call_request::PublicCallRequest, - validation_requests::PublicValidationRequestArrayLengths, - }, - constants::MAX_L2_GAS_PER_ENQUEUED_CALL, - utils::arrays::array_length, -}; - -pub struct EnqueuedCallDataValidator { - enqueued_call: EnqueuedCallData, - phase: u8, -} - -impl EnqueuedCallDataValidator { - pub fn new(enqueued_call: EnqueuedCallData, phase: u8) -> Self { - EnqueuedCallDataValidator { enqueued_call, phase } - } - - pub fn validate(self) { - self.validate_revert_flag() - } - - pub fn validate_against_previous_kernel( - self, - previous_kernel: PublicKernelCircuitPublicInputs, - ) { - self.validate_global_variables(previous_kernel); - self.validate_against_call_request(previous_kernel); - self.validate_start_gas(previous_kernel); - self.validate_transaction_fee(previous_kernel); - } - - fn validate_revert_flag(self) { - if self.phase == PublicKernelPhase.SETUP { - assert_eq(self.enqueued_call.data.reverted, false, "Public call cannot be reverted"); - } - } - - fn validate_global_variables(self, previous_kernel: PublicKernelCircuitPublicInputs) { - let prev_global_variables = previous_kernel.constants.global_variables; - if !prev_global_variables.is_empty() { - // It's empty when the previous kernel is from private_kernel_tail_to_pubic. - let enqueued_call_globals = self.enqueued_call.data.constants.global_variables; - assert_eq( - enqueued_call_globals, - prev_global_variables, - "Global variables injected into the public call do not match constants", - ); - } - } - - fn validate_against_call_request(self, previous_kernel: PublicKernelCircuitPublicInputs) { - let call_request = if self.phase == PublicKernelPhase.SETUP { - let call_stack = previous_kernel.end_non_revertible.public_call_stack; - call_stack[array_length(call_stack) - 1] - } else if self.phase == PublicKernelPhase.APP_LOGIC { - let call_stack = previous_kernel.end.public_call_stack; - call_stack[array_length(call_stack) - 1] - } else if self.phase == PublicKernelPhase.TEARDOWN { - previous_kernel.public_teardown_call_request - } else { - assert(false, "Unknown phase"); - PublicCallRequest::empty() - }; - - assert( - self.enqueued_call.data.call_request == call_request, - "enqueued call does not match item at the top of the call stack", - ); - } - - // Validates that the start gas injected into the vm circuit matches the remaining gas. - fn validate_start_gas(self, previous_kernel: PublicKernelCircuitPublicInputs) { - let enqueued_call_start_gas = self.enqueued_call.data.start_gas_left; - // NOTE: the AVM circuit will fail to generate a proof if its "start gas" is > MAX_L2_GAS_PER_ENQUEUED_CALL, - // so the kernel never allocates more than that maximum to one enqueued call. - if self.phase != PublicKernelPhase.TEARDOWN { - // An enqueued call's start gas is the remaining gas left in the transaction after the previous kernel. - let tx_gas_limits = previous_kernel.constants.tx_context.gas_settings.gas_limits; - let mut computed_start_gas = tx_gas_limits.sub(previous_kernel.end.gas_used).sub( - previous_kernel.end_non_revertible.gas_used, - ); - // Keep L2 gas below max - computed_start_gas.l2_gas = - std::cmp::min(computed_start_gas.l2_gas, MAX_L2_GAS_PER_ENQUEUED_CALL); - assert_eq( - enqueued_call_start_gas, - computed_start_gas, - "Start gas for enqueued call does not match transaction gas left (with MAX_L2_GAS_PER_ENQUEUED_CALL applied)", - ); - } else { - let mut teardown_gas_limit = - previous_kernel.constants.tx_context.gas_settings.teardown_gas_limits; - // Keep L2 gas below max - teardown_gas_limit.l2_gas = - std::cmp::min(teardown_gas_limit.l2_gas, MAX_L2_GAS_PER_ENQUEUED_CALL); - assert_eq( - enqueued_call_start_gas, - teardown_gas_limit, - "Start gas for enqueued call does not match teardown gas allocation (with MAX_L2_GAS_PER_ENQUEUED_CALL applied)", - ); - } - } - - fn validate_transaction_fee(self, previous_kernel: PublicKernelCircuitPublicInputs) { - let transaction_fee = self.enqueued_call.data.transaction_fee; - if self.phase != PublicKernelPhase.TEARDOWN { - assert_eq(transaction_fee, 0, "Transaction fee must be zero on setup and app phases"); - } else { - let teardown_gas = - previous_kernel.constants.tx_context.gas_settings.teardown_gas_limits; - let total_gas_used = previous_kernel.end.gas_used - + previous_kernel.end_non_revertible.gas_used - + teardown_gas; - let block_gas_fees = self.enqueued_call.data.constants.global_variables.gas_fees; - let inclusion_fee = previous_kernel.constants.tx_context.gas_settings.inclusion_fee; - let computed_transaction_fee = - total_gas_used.compute_fee(block_gas_fees) + inclusion_fee; - assert( - transaction_fee == computed_transaction_fee, - "Transaction fee on teardown phase does not match expected value", - ); - } - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/mod.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/mod.nr index ffaa2d88a5c..fbccb685e14 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/mod.nr @@ -1,3 +1,2 @@ -mod enqueued_call_data_validator; mod public_kernel_output_composer; mod public_tail_output_composer; diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer.nr index 0c982cd789d..bb35add7cf7 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_kernel_output_composer.nr @@ -49,7 +49,6 @@ impl PublicKernelOutputComposer { self.propagate_validation_requests(enqueued_call); self.propagate_accumulated_data(enqueued_call, phase); self.propagate_end_side_effect_counter(enqueued_call); - self.update_gas_used(enqueued_call, phase); *self } @@ -154,14 +153,4 @@ impl PublicKernelOutputComposer { fn propagate_end_side_effect_counter(&mut self, enqueued_call: VMCircuitPublicInputs) { self.output_builder.end_side_effect_counter = enqueued_call.end_side_effect_counter; } - - fn update_gas_used(&mut self, enqueued_call: VMCircuitPublicInputs, phase: u8) { - let call_gas_used = enqueued_call.accumulated_data.gas_used; - if phase == PublicKernelPhase.SETUP { - self.output_builder.end_non_revertible.gas_used += call_gas_used; - } - if phase == PublicKernelPhase.APP_LOGIC { - self.output_builder.end.gas_used += call_gas_used; - } - } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer.nr index 788fd4eff55..87d6118f8f3 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer.nr @@ -42,6 +42,9 @@ impl PublicTailOutputComposer PublicTailOutputComposer( note_encrypted_logs_hashes, encrypted_logs_hashes, unencrypted_logs_hashes, + contract_class_logs_hashes: [ScopedLogHash::empty(); MAX_CONTRACT_CLASS_LOGS_PER_TX], note_encrypted_log_preimages_length, encrypted_log_preimages_length, unencrypted_log_preimages_length, + contract_class_log_preimages_length: 0, public_data_writes, - gas_used: revertible.gas_used + non_revertible.gas_used, } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/generate_public_data_leaves.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/generate_public_data_leaves.nr index f0e20f5a530..043a819cfb3 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/generate_public_data_leaves.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/components/public_tail_output_composer/generate_public_data_leaves.nr @@ -85,7 +85,7 @@ pub unconstrained fn generate_public_data_leaves PublicKernelCircuitPublicInputs { let phase = self.get_phase(); - let enqueued_call_data_validator = - EnqueuedCallDataValidator::new(self.enqueued_call, phase); - enqueued_call_data_validator.validate_against_previous_kernel( - self.previous_kernel.public_inputs, - ); - PublicKernelOutputComposer::new_from_previous_kernel(self.previous_kernel.public_inputs) .remove_top_call_request(phase) .propagate_from_enqueued_call(self.enqueued_call.data, phase) @@ -54,7 +45,7 @@ mod tests { }; use dep::types::{ abis::{ - accumulated_data::PublicAccumulatedDataArrayLengths, gas::Gas, + accumulated_data::PublicAccumulatedDataArrayLengths, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, max_block_number::MaxBlockNumber, validation_requests::PublicValidationRequestArrayLengths, @@ -121,24 +112,6 @@ mod tests { kernel.execute() } - pub fn populate_gas_used(&mut self) { - // Transaction gas limit is 1k. - self.previous_kernel.tx_context.gas_settings.gas_limits = Gas::new(1000, 1000); - - // Non-revertible has used 200. - self.previous_kernel.gas_used = Gas::new(200, 200); - - // Revertible has used 100. - self.previous_revertible.gas_used = Gas::new(100, 100); - - // So this call starts with 700 gas left - self.enqueued_call.start_gas_left = Gas::new(700, 700); - // And uses 250. - self.enqueued_call.gas_used = Gas::new(250, 250); - // Ending with 450 left. - self.enqueued_call.end_gas_left = Gas::new(450, 450); - } - pub fn succeeded(&mut self) { let _ = self.execute(); } @@ -187,34 +160,4 @@ mod tests { [prev_calls[0].inner], // Public call requests can only be propagated from previous kernel. ); } - - #[test] - unconstrained fn updates_revertible_gas_used() { - let mut builder = PublicKernelMergeCircuitPrivateInputsBuilder::new(); - builder.phase = PublicKernelPhase.APP_LOGIC; - - builder.populate_gas_used(); - - // So the updated gas used by revertible must go up by 250, and non-revertible must stay the same. - let output = builder.execute(); - assert_eq(output.end_non_revertible.gas_used, Gas::new(200, 200)); - assert_eq(output.end.gas_used, Gas::new(350, 350)); - } - - #[test] - unconstrained fn handle_revert_in_app_logic() { - let mut builder = PublicKernelMergeCircuitPrivateInputsBuilder::new(); - builder.phase = PublicKernelPhase.APP_LOGIC; - builder.enqueued_call.revert_code = 1; - - builder.populate_gas_used(); - - let output = builder.execute(); - - assert_eq(output.revert_code, 1); - - // gas_used is propagated even when reverts. - assert_eq(output.end_non_revertible.gas_used, Gas::new(200, 200)); - assert_eq(output.end.gas_used, Gas::new(350, 350)); - } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr index 3e413125fe1..3d88d23b463 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr @@ -263,8 +263,8 @@ mod tests { fn set_nullifiers_for_non_existent_read_request_hints(&mut self) { let nullifiers = array_merge( - self.previous_kernel.nullifiers.storage, - self.previous_revertible.nullifiers.storage, + self.previous_kernel.nullifiers.storage(), + self.previous_revertible.nullifiers.storage(), ) .map(|n: ScopedNullifier| n.nullifier); self.nullifier_non_existent_read_request_hints_builder.set_nullifiers(nullifiers); @@ -342,7 +342,7 @@ mod tests { } } - public_data_hints.storage + public_data_hints.storage() } fn sync_counters(&mut self) { @@ -371,10 +371,10 @@ mod tests { let kernel = PublicKernelTailCircuitPrivateInputs { previous_kernel, - note_hash_read_request_hints: self.note_hash_read_request_hints.storage, + note_hash_read_request_hints: self.note_hash_read_request_hints.storage(), nullifier_read_request_hints, nullifier_non_existent_read_request_hints, - l1_to_l2_msg_read_request_hints: self.l1_to_l2_msg_read_request_hints.storage, + l1_to_l2_msg_read_request_hints: self.l1_to_l2_msg_read_request_hints.storage(), public_data_hints, start_state: self.start_state, }; @@ -435,7 +435,7 @@ mod tests { assert_eq( public_inputs.end.unencrypted_logs_hashes, - builder.previous_revertible.unencrypted_logs_hashes.storage, + builder.previous_revertible.unencrypted_logs_hashes.storage(), ); } diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr index 52aa039a2b6..6af738b950a 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/note_hash_read_request_reset.nr @@ -9,9 +9,9 @@ use dep::types::{ }; pub struct NoteHashSettledReadHint { - read_request_index: u32, - membership_witness: MembershipWitness, - leaf_preimage: NoteHashLeafPreimage, + pub read_request_index: u32, + pub membership_witness: MembershipWitness, + pub leaf_preimage: NoteHashLeafPreimage, } impl ReadValueHint for NoteHashSettledReadHint { @@ -39,9 +39,9 @@ impl SettledReadHint for NoteHashSe } pub struct NoteHashReadRequestHints { - read_request_statuses: [ReadRequestStatus; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], - pending_read_hints: [PendingReadHint; NUM_PENDING_HINTS], - settled_read_hints: [NoteHashSettledReadHint; NUM_SETTLED_HINTS], + pub read_request_statuses: [ReadRequestStatus; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], + pub pending_read_hints: [PendingReadHint; NUM_PENDING_HINTS], + pub settled_read_hints: [NoteHashSettledReadHint; NUM_SETTLED_HINTS], } mod tests { diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr index 96a5fac86d0..38ce0da77a3 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr @@ -9,9 +9,9 @@ use dep::types::{ }; pub struct NullifierSettledReadHint { - read_request_index: u32, - membership_witness: MembershipWitness, - leaf_preimage: NullifierLeafPreimage, + pub read_request_index: u32, + pub membership_witness: MembershipWitness, + pub leaf_preimage: NullifierLeafPreimage, } impl ReadValueHint for NullifierSettledReadHint { @@ -39,9 +39,9 @@ impl SettledReadHint for Nullifier } pub struct NullifierReadRequestHints { - read_request_statuses: [ReadRequestStatus; MAX_NULLIFIER_READ_REQUESTS_PER_TX], - pending_read_hints: [PendingReadHint; NUM_PENDING_HINTS], - settled_read_hints: [NullifierSettledReadHint; NUM_SETTLED_HINTS], + pub read_request_statuses: [ReadRequestStatus; MAX_NULLIFIER_READ_REQUESTS_PER_TX], + pub pending_read_hints: [PendingReadHint; NUM_PENDING_HINTS], + pub settled_read_hints: [NullifierSettledReadHint; NUM_SETTLED_HINTS], } mod tests { diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr index 8f641126807..12951ebd19b 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr @@ -18,15 +18,15 @@ use dep::types::{ }; pub struct PrivateValidationRequestProcessor { - validation_requests: PrivateValidationRequests, - note_hash_read_request_hints: NoteHashReadRequestHints, - pending_note_hashes: [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX], - note_hash_tree_root: Field, - nullifier_read_request_hints: NullifierReadRequestHints, - pending_nullifiers: [ScopedNullifier; MAX_NULLIFIERS_PER_TX], - nullifier_tree_root: Field, - key_validation_hints: [KeyValidationHint; KEY_VALIDATION_REQUESTS], - validation_requests_split_counter: u32, + pub validation_requests: PrivateValidationRequests, + pub note_hash_read_request_hints: NoteHashReadRequestHints, + pub pending_note_hashes: [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX], + pub note_hash_tree_root: Field, + pub nullifier_read_request_hints: NullifierReadRequestHints, + pub pending_nullifiers: [ScopedNullifier; MAX_NULLIFIERS_PER_TX], + pub nullifier_tree_root: Field, + pub key_validation_hints: [KeyValidationHint; KEY_VALIDATION_REQUESTS], + pub validation_requests_split_counter: u32, } impl PrivateValidationRequestProcessor { diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/key_validation_hint.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/key_validation_hint.nr index 6f67737014b..dc15f06d7f0 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/key_validation_hint.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/key_validation_hint.nr @@ -121,5 +121,5 @@ pub unconstrained fn get_unverified_key_validation_requests u32; } pub struct PendingReadHint { - read_request_index: u32, - pending_value_index: u32, + pub read_request_index: u32, + pub pending_value_index: u32, } impl ReadValueHint for PendingReadHint { @@ -55,7 +55,7 @@ impl PendingReadHint { } } -trait SettledReadHint +pub trait SettledReadHint where LEAF_PREIMAGE: LeafPreimage, { @@ -189,7 +189,7 @@ pub unconstrained fn get_unverified_read_requests( propagated_read_requests.push(read_request); } } - propagated_read_requests.storage + propagated_read_requests.storage() } mod tests { diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr index 19471c18b8a..a1956abdee8 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/transient_data.nr @@ -4,8 +4,8 @@ use dep::types::{ }; pub struct TransientDataIndexHint { - nullifier_index: u32, - note_hash_index: u32, + pub nullifier_index: u32, + pub note_hash_index: u32, } impl TransientDataIndexHint { diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/mod.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/mod.nr index 3d21477493f..c590c5806c6 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/mod.nr @@ -1,6 +1,6 @@ -mod note_hash_read_request_hints_builder; -mod nullifier_non_existent_read_request_hints_builder; -mod nullifier_read_request_hints_builder; +pub mod note_hash_read_request_hints_builder; +pub mod nullifier_non_existent_read_request_hints_builder; +pub mod nullifier_read_request_hints_builder; pub use note_hash_read_request_hints_builder::NoteHashReadRequestHintsBuilder; pub use nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr index e066aedb756..a396244a5a6 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/note_hash_read_request_hints_builder.nr @@ -5,9 +5,9 @@ use crate::{ use dep::types::constants::MAX_NOTE_HASH_READ_REQUESTS_PER_TX; pub struct NoteHashReadRequestHintsBuilder { - read_request_statuses: [ReadRequestStatus; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], - pending_read_hints: BoundedVec, - settled_read_hints: BoundedVec, + pub read_request_statuses: [ReadRequestStatus; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], + pub pending_read_hints: BoundedVec, + pub settled_read_hints: BoundedVec, } impl NoteHashReadRequestHintsBuilder { @@ -35,8 +35,8 @@ impl NoteHashReadRequest ) -> NoteHashReadRequestHints { NoteHashReadRequestHints { read_request_statuses: self.read_request_statuses, - pending_read_hints: self.pending_read_hints.storage, - settled_read_hints: self.settled_read_hints.storage, + pending_read_hints: self.pending_read_hints.storage(), + settled_read_hints: self.settled_read_hints.storage(), } } } diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr index a7d48860ad1..bd3e55294ac 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr @@ -77,7 +77,7 @@ impl NullifierNonExistentReadRequestHintsBuilder { } NullifierNonExistentReadRequestHints { - non_membership_hints: self.non_membership_hints.storage, + non_membership_hints: self.non_membership_hints.storage(), sorted_pending_values, sorted_pending_value_index_hints, next_pending_value_indices, diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr index 9d60bce4e83..ddd28b07ebc 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_read_request_hints_builder.nr @@ -5,9 +5,9 @@ use crate::{ use dep::types::constants::MAX_NULLIFIER_READ_REQUESTS_PER_TX; pub struct NullifierReadRequestHintsBuilder { - read_request_statuses: [ReadRequestStatus; MAX_NULLIFIER_READ_REQUESTS_PER_TX], - pending_read_hints: BoundedVec, - settled_read_hints: BoundedVec, + pub read_request_statuses: [ReadRequestStatus; MAX_NULLIFIER_READ_REQUESTS_PER_TX], + pub pending_read_hints: BoundedVec, + pub settled_read_hints: BoundedVec, } impl NullifierReadRequestHintsBuilder { @@ -35,8 +35,8 @@ impl NullifierReadReques ) -> NullifierReadRequestHints { NullifierReadRequestHints { read_request_statuses: self.read_request_statuses, - pending_read_hints: self.pending_read_hints.storage, - settled_read_hints: self.settled_read_hints.storage, + pending_read_hints: self.pending_read_hints.storage(), + settled_read_hints: self.settled_read_hints.storage(), } } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr index b63e3376986..28bae2e2bd9 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr @@ -572,7 +572,7 @@ mod tests { let mut sorted_write_tuples = unsafe { get_sorted_tuple( - final_public_data_writes.storage, + final_public_data_writes.storage(), |(_, leaf_a): (u32, PublicDataTreeLeaf), (_, leaf_b): (u32, PublicDataTreeLeaf)| { full_field_less_than(leaf_b.slot, leaf_a.slot) }, @@ -1135,7 +1135,7 @@ mod tests { // Since we fill the tree completely, we know to expect a full tree as below let expected_tree = dep::types::merkle_tree::variable_merkle_tree::tests::generate_full_sha_tree( - siloed_l2_to_l1_msgs.storage, + siloed_l2_to_l1_msgs.storage(), ); assert_eq(out_hash, expected_tree.get_root()); } @@ -1445,7 +1445,7 @@ mod tests { builder.fee_payer_fee_juice_balance_pre_existing_public_data_index = Option::some(1); // Set values for computing exact tx_fee - builder.kernel_data.tx_context.gas_settings.inclusion_fee = tx_fee; + builder.transaction_fee = tx_fee; // Set expected protocol data update builder.protocol_public_data_writes.push(( diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr index 0d557a7cf9c..848147c61b9 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/private_base_rollup.nr @@ -41,9 +41,8 @@ pub struct PrivateBaseRollupInputs { impl PrivateBaseRollupInputs { fn compute_transaction_fee(self) -> Field { let gas_fees = self.constants.global_variables.gas_fees; - let data = self.tube_data.public_inputs; - let inclusion_fee = data.constants.tx_context.gas_settings.inclusion_fee; - inclusion_fee + data.end.gas_used.compute_fee(gas_fees) + let gas_used = self.tube_data.public_inputs.gas_used; + gas_used.compute_fee(gas_fees) } pub fn execute(self) -> BaseOrMergeRollupPublicInputs { diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr index 8a8a9650bbc..4e3fa619a5a 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/public_base_rollup.nr @@ -13,7 +13,6 @@ use dep::types::{ abis::{ accumulated_data::CombinedAccumulatedData, combined_constant_data::CombinedConstantData, - gas::Gas, log_hash::{LogHash, ScopedLogHash}, }, constants::{ @@ -67,10 +66,20 @@ impl PublicBaseRollupInputs { from_private.revertible_accumulated_data.encrypted_logs_hashes, ) }; + let contract_class_logs_hashes = if reverted { + from_private.non_revertible_accumulated_data.contract_class_logs_hashes + } else { + array_merge( + from_private.non_revertible_accumulated_data.contract_class_logs_hashes, + from_private.revertible_accumulated_data.contract_class_logs_hashes, + ) + }; let note_encrypted_log_preimages_length = note_encrypted_logs_hashes.fold(0, |len, l: LogHash| len + l.length); let encrypted_log_preimages_length = encrypted_logs_hashes.fold(0, |len, l: ScopedLogHash| len + l.log_hash.length); + let contract_class_log_preimages_length = + contract_class_logs_hashes.fold(0, |len, l: ScopedLogHash| len + l.log_hash.length); let unencrypted_log_preimages_length = from_public .accumulated_data .unencrypted_logs_hashes @@ -82,11 +91,12 @@ impl PublicBaseRollupInputs { note_encrypted_logs_hashes, encrypted_logs_hashes, unencrypted_logs_hashes: from_public.accumulated_data.unencrypted_logs_hashes, + contract_class_logs_hashes, note_encrypted_log_preimages_length, encrypted_log_preimages_length, unencrypted_log_preimages_length, + contract_class_log_preimages_length, public_data_writes: from_public.accumulated_data.public_data_writes, - gas_used: Gas::empty(), // gas_used is not used in rollup circuits. }; let constants = @@ -106,6 +116,7 @@ impl PublicBaseRollupInputs { end, start_state, revert_code, + gas_used: from_public.end_gas_used, fee_payer: from_private.fee_payer, } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr index ba64a36779d..7dbe6021d88 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr @@ -12,13 +12,12 @@ use dep::types::{ public_data_write::PublicDataWrite, }, constants::{ - AZTEC_MAX_EPOCH_DURATION, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, - MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + AZTEC_MAX_EPOCH_DURATION, MAX_CONTRACT_CLASS_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, }, hash::{ - accumulate_sha256, compute_tx_logs_hash, compute_tx_note_logs_hash, silo_encrypted_log_hash, - silo_unencrypted_log_hash, + accumulate_sha256, compute_tx_logs_hash, silo_encrypted_log_hash, silo_unencrypted_log_hash, }, merkle_tree::VariableMerkleTree, traits::is_empty, @@ -200,8 +199,8 @@ pub fn compute_txs_effects_hash(previous_rollup_data: [PreviousRollupData; 2]) - ]) } -fn silo_and_hash_unencrypted_logs( - unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], +fn silo_and_hash_unencrypted_logs( + unencrypted_logs_hashes: [ScopedLogHash; N], ) -> Field { let siloed_logs = unencrypted_logs_hashes.map(|log: ScopedLogHash| { LogHash { @@ -235,20 +234,22 @@ fn silo_and_hash_encrypted_logs( // MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX public data update requests -> MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 fields // __ // 1 note encrypted logs length --> 1 field | -// 1 encrypted logs length --> 1 field | -> 3 types of logs - 3 fields for its lengths -// 1 unencrypted logs length --> 1 field __| -// __ -// 1 note encrypted logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! | -// 1 encrypted logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! | -> 3 types of logs - 3 fields for its hashes -// 1 unencrypted logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! __| +// 1 encrypted logs length --> 1 field | -> 4 types of logs - 4 fields for its lengths +// 1 unencrypted logs length --> 1 field | +// 1 contract class logs length --> 1 field __| +// __ +// 1 note encrypted logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! | +// 1 encrypted logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! | -> 4 types of logs - 4 fields for its hashes +// 1 unencrypted logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! | +// 1 contract class logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! __| global TX_EFFECTS_HASH_INPUT_FIELDS = 1 + 1 + MAX_NOTE_HASHES_PER_TX + MAX_NULLIFIERS_PER_TX + 1 + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 - + 3 - + 3; + + 4 + + 4; // Computes the tx effects hash for a base rollup (a single transaction) pub fn compute_tx_effects_hash( @@ -270,9 +271,12 @@ pub fn compute_tx_effects_hash( let note_logs_length = combined.note_encrypted_log_preimages_length; let encrypted_logs_length = combined.encrypted_log_preimages_length; let unencrypted_logs_length = combined.unencrypted_log_preimages_length; - let note_encrypted_logs_hash = compute_tx_note_logs_hash(combined.note_encrypted_logs_hashes); + let contract_class_logs_length = combined.contract_class_log_preimages_length; + let note_encrypted_logs_hash = compute_tx_logs_hash(combined.note_encrypted_logs_hashes); let encrypted_logs_hash = silo_and_hash_encrypted_logs(combined.encrypted_logs_hashes); let unencrypted_logs_hash = silo_and_hash_unencrypted_logs(combined.unencrypted_logs_hashes); + let contract_class_logs_hash = + silo_and_hash_unencrypted_logs(combined.contract_class_logs_hashes); let mut offset = 0; @@ -320,6 +324,10 @@ pub fn compute_tx_effects_hash( tx_effects_hash_input[offset] = unencrypted_logs_length; offset += 1; + // CONTRACT CLASS LOGS LENGTH + tx_effects_hash_input[offset] = contract_class_logs_length; + offset += 1; + // NOTE ENCRYPTED LOGS HASH tx_effects_hash_input[offset] = note_encrypted_logs_hash; offset += 1; @@ -332,6 +340,10 @@ pub fn compute_tx_effects_hash( tx_effects_hash_input[offset] = unencrypted_logs_hash; offset += 1; + // CONTRACT CLASS LOGS HASH + tx_effects_hash_input[offset] = contract_class_logs_hash; + offset += 1; + assert_eq(offset, TX_EFFECTS_HASH_INPUT_FIELDS); // Sanity check let mut hash_input_flattened = [0; TX_EFFECTS_HASH_INPUT_FIELDS * 32]; for offset in 0..TX_EFFECTS_HASH_INPUT_FIELDS { @@ -356,7 +368,7 @@ fn get_all_update_requests_for_tx_effects( all_update_requests.push(update_request); } } - all_update_requests.storage + all_update_requests.storage() } #[test] @@ -367,8 +379,8 @@ fn consistent_TX_EFFECTS_HASH_INPUT_FIELDS() { + MAX_NULLIFIERS_PER_TX + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 + 1 // out hash - + 3 // logs lengths - + 3; // logs hashes + + 4 // logs lengths + + 4; // logs hashes assert( TX_EFFECTS_HASH_INPUT_FIELDS == expected_size, "tx effects hash input size is incorrect", diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr index 1ee5fa308a9..440dbcfa3cb 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr @@ -1,9 +1,9 @@ use crate::{ - abis::{gas::Gas, log_hash::{LogHash, ScopedLogHash}, public_data_write::PublicDataWrite}, + abis::{log_hash::{LogHash, ScopedLogHash}, public_data_write::PublicDataWrite}, constants::{ - COMBINED_ACCUMULATED_DATA_LENGTH, MAX_ENCRYPTED_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, + COMBINED_ACCUMULATED_DATA_LENGTH, MAX_CONTRACT_CLASS_LOGS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, }, messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::{Deserialize, Empty, Serialize}, @@ -11,23 +11,23 @@ use crate::{ }; pub struct CombinedAccumulatedData { - note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], - nullifiers: [Field; MAX_NULLIFIERS_PER_TX], - l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], + pub note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], + pub nullifiers: [Field; MAX_NULLIFIERS_PER_TX], + pub l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], - note_encrypted_logs_hashes: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - encrypted_logs_hashes: [ScopedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], - unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], + pub note_encrypted_logs_hashes: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + pub encrypted_logs_hashes: [ScopedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], + pub unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], + pub contract_class_logs_hashes: [ScopedLogHash; MAX_CONTRACT_CLASS_LOGS_PER_TX], // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the // variable-length data. - note_encrypted_log_preimages_length: Field, - encrypted_log_preimages_length: Field, - unencrypted_log_preimages_length: Field, + pub note_encrypted_log_preimages_length: Field, + pub encrypted_log_preimages_length: Field, + pub unencrypted_log_preimages_length: Field, + pub contract_class_log_preimages_length: Field, - public_data_writes: [PublicDataWrite; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - - gas_used: Gas, + pub public_data_writes: [PublicDataWrite; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], } impl Empty for CombinedAccumulatedData { @@ -39,11 +39,12 @@ impl Empty for CombinedAccumulatedData { note_encrypted_logs_hashes: [LogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_TX], encrypted_logs_hashes: [ScopedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX], unencrypted_logs_hashes: [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + contract_class_logs_hashes: [ScopedLogHash::empty(); MAX_CONTRACT_CLASS_LOGS_PER_TX], note_encrypted_log_preimages_length: 0, encrypted_log_preimages_length: 0, unencrypted_log_preimages_length: 0, + contract_class_log_preimages_length: 0, public_data_writes: [PublicDataWrite::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - gas_used: Gas::empty(), } } } @@ -66,16 +67,18 @@ impl Serialize for CombinedAccumulatedData { for i in 0..self.unencrypted_logs_hashes.len() { fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize()); } + for i in 0..self.contract_class_logs_hashes.len() { + fields.extend_from_array(self.contract_class_logs_hashes[i].serialize()); + } fields.push(self.note_encrypted_log_preimages_length); fields.push(self.encrypted_log_preimages_length); fields.push(self.unencrypted_log_preimages_length); + fields.push(self.contract_class_log_preimages_length); for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { fields.extend_from_array(self.public_data_writes[i].serialize()); } - fields.extend_from_array(self.gas_used.serialize()); - assert_eq(fields.len(), COMBINED_ACCUMULATED_DATA_LENGTH); fields.storage() @@ -105,14 +108,18 @@ impl Deserialize for CombinedAccumulatedData { ScopedLogHash::deserialize, [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], ), + contract_class_logs_hashes: reader.read_struct_array( + ScopedLogHash::deserialize, + [ScopedLogHash::empty(); MAX_CONTRACT_CLASS_LOGS_PER_TX], + ), note_encrypted_log_preimages_length: reader.read(), encrypted_log_preimages_length: reader.read(), unencrypted_log_preimages_length: reader.read(), + contract_class_log_preimages_length: reader.read(), public_data_writes: reader.read_struct_array( PublicDataWrite::deserialize, [PublicDataWrite::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], ), - gas_used: reader.read_struct(Gas::deserialize), }; reader.finish(); item @@ -127,14 +134,18 @@ impl Eq for CombinedAccumulatedData { & (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) & (self.encrypted_logs_hashes == other.encrypted_logs_hashes) & (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) + & (self.contract_class_logs_hashes == other.contract_class_logs_hashes) & ( self.note_encrypted_log_preimages_length == other.note_encrypted_log_preimages_length ) & (self.encrypted_log_preimages_length == other.encrypted_log_preimages_length) & (self.unencrypted_log_preimages_length == other.unencrypted_log_preimages_length) + & ( + self.contract_class_log_preimages_length + == other.contract_class_log_preimages_length + ) & (self.public_data_writes == other.public_data_writes) - & (self.gas_used == other.gas_used) } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/mod.nr index b3950385b1f..354485f84ee 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/mod.nr @@ -1,12 +1,12 @@ -mod avm_accumulated_data; -mod combined_accumulated_data; -mod private_accumulated_data; -mod private_accumulated_data_builder; -mod private_to_avm_accumulated_data; -mod private_to_public_accumulated_data; -mod private_to_public_accumulated_data_builder; -mod public_accumulated_data; -mod public_accumulated_data_builder; +pub mod avm_accumulated_data; +pub mod combined_accumulated_data; +pub mod private_accumulated_data; +pub mod private_accumulated_data_builder; +pub mod private_to_avm_accumulated_data; +pub mod private_to_public_accumulated_data; +pub mod private_to_public_accumulated_data_builder; +pub mod public_accumulated_data; +pub mod public_accumulated_data_builder; pub use avm_accumulated_data::AvmAccumulatedData; pub use combined_accumulated_data::CombinedAccumulatedData; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr index bd951cae60e..2cbe86491a7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr @@ -12,23 +12,22 @@ use crate::{ utils::reader::Reader, }; use crate::constants::{ - MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, - MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, - PRIVATE_ACCUMULATED_DATA_LENGTH, + MAX_CONTRACT_CLASS_LOGS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, PRIVATE_ACCUMULATED_DATA_LENGTH, }; pub struct PrivateAccumulatedData { - note_hashes: [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX], - nullifiers: [ScopedNullifier; MAX_NULLIFIERS_PER_TX], - l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], + pub note_hashes: [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX], + pub nullifiers: [ScopedNullifier; MAX_NULLIFIERS_PER_TX], + pub l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], - note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - encrypted_logs_hashes: [ScopedEncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], - unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], + pub note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + pub encrypted_logs_hashes: [ScopedEncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], + pub contract_class_logs_hashes: [ScopedLogHash; MAX_CONTRACT_CLASS_LOGS_PER_TX], - public_call_requests: [Counted; MAX_ENQUEUED_CALLS_PER_TX], - private_call_stack: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX], + pub public_call_requests: [Counted; MAX_ENQUEUED_CALLS_PER_TX], + pub private_call_stack: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX], } impl Serialize for PrivateAccumulatedData { @@ -55,8 +54,8 @@ impl Serialize for PrivateAccumulatedData { fields.extend_from_array(self.encrypted_logs_hashes[i].serialize()); } - for i in 0..MAX_UNENCRYPTED_LOGS_PER_TX { - fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize()); + for i in 0..MAX_CONTRACT_CLASS_LOGS_PER_TX { + fields.extend_from_array(self.contract_class_logs_hashes[i].serialize()); } for i in 0..MAX_ENQUEUED_CALLS_PER_TX { @@ -98,9 +97,9 @@ impl Deserialize for PrivateAccumulatedData { ScopedEncryptedLogHash::deserialize, [ScopedEncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX], ), - unencrypted_logs_hashes: reader.read_struct_array( + contract_class_logs_hashes: reader.read_struct_array( ScopedLogHash::deserialize, - [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + [ScopedLogHash::empty(); MAX_CONTRACT_CLASS_LOGS_PER_TX], ), public_call_requests: reader.read_struct_array( Counted::deserialize, @@ -123,7 +122,7 @@ impl Eq for PrivateAccumulatedData { & (self.l2_to_l1_msgs == other.l2_to_l1_msgs) & (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) & (self.encrypted_logs_hashes == other.encrypted_logs_hashes) - & (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) + & (self.contract_class_logs_hashes == other.contract_class_logs_hashes) & (self.public_call_requests == other.public_call_requests) & (self.private_call_stack == other.private_call_stack) } @@ -137,7 +136,7 @@ impl Empty for PrivateAccumulatedData { l2_to_l1_msgs: [ScopedL2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_TX], note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_TX], encrypted_logs_hashes: [ScopedEncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX], - unencrypted_logs_hashes: [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + contract_class_logs_hashes: [ScopedLogHash::empty(); MAX_CONTRACT_CLASS_LOGS_PER_TX], public_call_requests: [Counted::empty(); MAX_ENQUEUED_CALLS_PER_TX], private_call_stack: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX], } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr index fbf1d4fe2d8..c4071413800 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr @@ -9,38 +9,38 @@ use crate::{ side_effect::Counted, }, constants::{ - MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, - MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_CONTRACT_CLASS_LOGS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, }, messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::Empty, }; pub struct PrivateAccumulatedDataBuilder { - note_hashes: BoundedVec, - nullifiers: BoundedVec, - l2_to_l1_msgs: BoundedVec, + pub note_hashes: BoundedVec, + pub nullifiers: BoundedVec, + pub l2_to_l1_msgs: BoundedVec, - note_encrypted_logs_hashes: BoundedVec, - encrypted_logs_hashes: BoundedVec, - unencrypted_logs_hashes: BoundedVec, + pub note_encrypted_logs_hashes: BoundedVec, + pub encrypted_logs_hashes: BoundedVec, + pub contract_class_logs_hashes: BoundedVec, - public_call_requests: BoundedVec, MAX_ENQUEUED_CALLS_PER_TX>, - private_call_stack: BoundedVec, + pub public_call_requests: BoundedVec, MAX_ENQUEUED_CALLS_PER_TX>, + pub private_call_stack: BoundedVec, } impl PrivateAccumulatedDataBuilder { pub fn finish(self) -> PrivateAccumulatedData { PrivateAccumulatedData { - note_hashes: self.note_hashes.storage, - nullifiers: self.nullifiers.storage, - l2_to_l1_msgs: self.l2_to_l1_msgs.storage, - note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage, - encrypted_logs_hashes: self.encrypted_logs_hashes.storage, - unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, - public_call_requests: self.public_call_requests.storage, - private_call_stack: self.private_call_stack.storage, + note_hashes: self.note_hashes.storage(), + nullifiers: self.nullifiers.storage(), + l2_to_l1_msgs: self.l2_to_l1_msgs.storage(), + note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage(), + encrypted_logs_hashes: self.encrypted_logs_hashes.storage(), + contract_class_logs_hashes: self.contract_class_logs_hashes.storage(), + public_call_requests: self.public_call_requests.storage(), + private_call_stack: self.private_call_stack.storage(), } } } @@ -53,7 +53,7 @@ impl Empty for PrivateAccumulatedDataBuilder { l2_to_l1_msgs: BoundedVec::new(), note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), - unencrypted_logs_hashes: BoundedVec::new(), + contract_class_logs_hashes: BoundedVec::new(), public_call_requests: BoundedVec::new(), private_call_stack: BoundedVec::new(), } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_avm_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_avm_accumulated_data.nr index ac1aa0fb67c..f79a124b547 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_avm_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_avm_accumulated_data.nr @@ -9,9 +9,9 @@ use crate::{ }; pub struct PrivateToAvmAccumulatedData { - note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], - nullifiers: [Field; MAX_NULLIFIERS_PER_TX], - l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], + pub note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], + pub nullifiers: [Field; MAX_NULLIFIERS_PER_TX], + pub l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], } impl Empty for PrivateToAvmAccumulatedData { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_public_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_public_accumulated_data.nr index 396d8c2cb93..9b80a20cf36 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_public_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_public_accumulated_data.nr @@ -1,24 +1,23 @@ use crate::{ - abis::{gas::Gas, log_hash::{LogHash, ScopedLogHash}, public_call_request::PublicCallRequest}, + abis::{log_hash::{LogHash, ScopedLogHash}, public_call_request::PublicCallRequest}, messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::{Deserialize, Empty, Serialize}, - utils::{arrays::array_length, reader::Reader}, + utils::reader::Reader, }; use crate::constants::{ - MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH, + MAX_CONTRACT_CLASS_LOGS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH, }; pub struct PrivateToPublicAccumulatedData { - note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], - nullifiers: [Field; MAX_NULLIFIERS_PER_TX], - l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], - note_encrypted_logs_hashes: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - encrypted_logs_hashes: [ScopedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], - unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], - public_call_requests: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], - gas_used: Gas, + pub note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], + pub nullifiers: [Field; MAX_NULLIFIERS_PER_TX], + pub l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], + pub note_encrypted_logs_hashes: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + pub encrypted_logs_hashes: [ScopedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], + pub contract_class_logs_hashes: [ScopedLogHash; MAX_CONTRACT_CLASS_LOGS_PER_TX], + pub public_call_requests: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], } impl Empty for PrivateToPublicAccumulatedData { @@ -29,9 +28,8 @@ impl Empty for PrivateToPublicAccumulatedData { l2_to_l1_msgs: [ScopedL2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_TX], note_encrypted_logs_hashes: [LogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_TX], encrypted_logs_hashes: [ScopedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX], - unencrypted_logs_hashes: [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + contract_class_logs_hashes: [ScopedLogHash::empty(); MAX_CONTRACT_CLASS_LOGS_PER_TX], public_call_requests: [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], - gas_used: Gas::empty(), } } } @@ -43,9 +41,8 @@ impl Eq for PrivateToPublicAccumulatedData { & (self.l2_to_l1_msgs == other.l2_to_l1_msgs) & (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) & (self.encrypted_logs_hashes == other.encrypted_logs_hashes) - & (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) + & (self.contract_class_logs_hashes == other.contract_class_logs_hashes) & (self.public_call_requests == other.public_call_requests) - & (self.gas_used == other.gas_used) } } @@ -65,13 +62,12 @@ impl Serialize for PrivateToPublicAcc for i in 0..self.encrypted_logs_hashes.len() { fields.extend_from_array(self.encrypted_logs_hashes[i].serialize()); } - for i in 0..self.unencrypted_logs_hashes.len() { - fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize()); + for i in 0..self.contract_class_logs_hashes.len() { + fields.extend_from_array(self.contract_class_logs_hashes[i].serialize()); } for i in 0..self.public_call_requests.len() { fields.extend_from_array(self.public_call_requests[i].serialize()); } - fields.extend_from_array(self.gas_used.serialize()); assert_eq(fields.len(), PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH); @@ -100,15 +96,14 @@ impl Deserialize for PrivateToPublicA ScopedLogHash::deserialize, [ScopedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX], ), - unencrypted_logs_hashes: reader.read_struct_array( + contract_class_logs_hashes: reader.read_struct_array( ScopedLogHash::deserialize, - [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], + [ScopedLogHash::empty(); MAX_CONTRACT_CLASS_LOGS_PER_TX], ), public_call_requests: reader.read_struct_array( PublicCallRequest::deserialize, [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], ), - gas_used: reader.read_struct(Gas::deserialize), }; reader.finish(); item diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_public_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_public_accumulated_data_builder.nr index e3516d4af94..18090601cd5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_public_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_to_public_accumulated_data_builder.nr @@ -1,18 +1,13 @@ use crate::{ abis::{ accumulated_data::private_to_public_accumulated_data::PrivateToPublicAccumulatedData, - gas::Gas, log_hash::{LogHash, ScopedLogHash}, - note_hash::ScopedNoteHash, - nullifier::Nullifier, public_call_request::PublicCallRequest, - public_data_update_request::PublicDataUpdateRequest, - side_effect::Counted, }, constants::{ - MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, + MAX_CONTRACT_CLASS_LOGS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, }, messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::Empty, @@ -25,9 +20,8 @@ pub struct PrivateToPublicAccumulatedDataBuilder { l2_to_l1_msgs: BoundedVec, note_encrypted_logs_hashes: BoundedVec, encrypted_logs_hashes: BoundedVec, - unencrypted_logs_hashes: BoundedVec, + contract_class_logs_hashes: BoundedVec, public_call_requests: BoundedVec, - gas_used: Gas, } impl PrivateToPublicAccumulatedDataBuilder { @@ -38,22 +32,20 @@ impl PrivateToPublicAccumulatedDataBuilder { l2_to_l1_msgs: array_to_bounded_vec(data.l2_to_l1_msgs), note_encrypted_logs_hashes: array_to_bounded_vec(data.note_encrypted_logs_hashes), encrypted_logs_hashes: array_to_bounded_vec(data.encrypted_logs_hashes), - unencrypted_logs_hashes: array_to_bounded_vec(data.unencrypted_logs_hashes), + contract_class_logs_hashes: array_to_bounded_vec(data.contract_class_logs_hashes), public_call_requests: array_to_bounded_vec(data.public_call_requests), - gas_used: data.gas_used, } } pub fn finish(self) -> PrivateToPublicAccumulatedData { PrivateToPublicAccumulatedData { - note_hashes: self.note_hashes.storage, - nullifiers: self.nullifiers.storage, - l2_to_l1_msgs: self.l2_to_l1_msgs.storage, - note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage, - encrypted_logs_hashes: self.encrypted_logs_hashes.storage, - unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, - public_call_requests: self.public_call_requests.storage, - gas_used: self.gas_used, + note_hashes: self.note_hashes.storage(), + nullifiers: self.nullifiers.storage(), + l2_to_l1_msgs: self.l2_to_l1_msgs.storage(), + note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage(), + encrypted_logs_hashes: self.encrypted_logs_hashes.storage(), + contract_class_logs_hashes: self.contract_class_logs_hashes.storage(), + public_call_requests: self.public_call_requests.storage(), } } } @@ -66,9 +58,8 @@ impl Empty for PrivateToPublicAccumulatedDataBuilder { l2_to_l1_msgs: BoundedVec::new(), note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), - unencrypted_logs_hashes: BoundedVec::new(), + contract_class_logs_hashes: BoundedVec::new(), public_call_requests: BoundedVec::new(), - gas_used: Gas::empty(), } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr index b7b0658a7f8..c4d1c87188e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr @@ -20,19 +20,19 @@ use crate::{ // TODO(#9594): To be deprecated. pub struct PublicAccumulatedData { - note_hashes: [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX], - nullifiers: [Nullifier; MAX_NULLIFIERS_PER_TX], - l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], + pub note_hashes: [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX], + pub nullifiers: [Nullifier; MAX_NULLIFIERS_PER_TX], + pub l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], - note_encrypted_logs_hashes: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - encrypted_logs_hashes: [ScopedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], - unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], + pub note_encrypted_logs_hashes: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + pub encrypted_logs_hashes: [ScopedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], + pub unencrypted_logs_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], - public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + pub public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - public_call_stack: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], + pub public_call_stack: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], - gas_used: Gas, + pub gas_used: Gas, } impl Empty for PublicAccumulatedData { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr index 1e6a36766cb..986db95df09 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr @@ -20,19 +20,19 @@ use crate::{ // TODO(#9594): To be deprecated. pub struct PublicAccumulatedDataBuilder { - note_hashes: BoundedVec, - nullifiers: BoundedVec, - l2_to_l1_msgs: BoundedVec, + pub note_hashes: BoundedVec, + pub nullifiers: BoundedVec, + pub l2_to_l1_msgs: BoundedVec, - note_encrypted_logs_hashes: BoundedVec, - encrypted_logs_hashes: BoundedVec, - unencrypted_logs_hashes: BoundedVec, + pub note_encrypted_logs_hashes: BoundedVec, + pub encrypted_logs_hashes: BoundedVec, + pub unencrypted_logs_hashes: BoundedVec, - public_data_update_requests: BoundedVec, + pub public_data_update_requests: BoundedVec, - public_call_stack: BoundedVec, + pub public_call_stack: BoundedVec, - gas_used: Gas, + pub gas_used: Gas, } impl PublicAccumulatedDataBuilder { @@ -52,14 +52,14 @@ impl PublicAccumulatedDataBuilder { pub fn finish(self) -> PublicAccumulatedData { PublicAccumulatedData { - note_hashes: self.note_hashes.storage, - nullifiers: self.nullifiers.storage, - l2_to_l1_msgs: self.l2_to_l1_msgs.storage, - note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage, - encrypted_logs_hashes: self.encrypted_logs_hashes.storage, - unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, - public_data_update_requests: self.public_data_update_requests.storage, - public_call_stack: self.public_call_stack.storage, + note_hashes: self.note_hashes.storage(), + nullifiers: self.nullifiers.storage(), + l2_to_l1_msgs: self.l2_to_l1_msgs.storage(), + note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage(), + encrypted_logs_hashes: self.encrypted_logs_hashes.storage(), + unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage(), + public_data_update_requests: self.public_data_update_requests.storage(), + public_call_stack: self.public_call_stack.storage(), gas_used: self.gas_used, } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr index 793b5dc4dc2..3f8f0f329a2 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr @@ -1,10 +1,10 @@ pub struct AppendOnlyTreeSnapshot { - root: Field, + pub root: Field, // TODO(Alvaro) change this to a u64 - next_available_leaf_index: u32, + pub next_available_leaf_index: u32, } -global APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2; +pub global APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2; impl AppendOnlyTreeSnapshot { pub fn serialize(self) -> [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH] { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr index 280f82ceff5..1ce06e8f53a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/avm_circuit_public_inputs.nr @@ -6,6 +6,7 @@ use crate::{ PrivateToAvmAccumulatedData, PrivateToAvmAccumulatedDataArrayLengths, }, }, + gas::Gas, gas_settings::GasSettings, global_variables::GlobalVariables, public_call_request::PublicCallRequest, @@ -21,6 +22,7 @@ pub struct AvmCircuitPublicInputs { // Inputs. global_variables: GlobalVariables, start_tree_snapshots: TreeSnapshots, + start_gas_used: Gas, gas_settings: GasSettings, public_setup_call_requests: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], public_app_logic_call_requests: [PublicCallRequest; MAX_ENQUEUED_CALLS_PER_TX], @@ -33,6 +35,7 @@ pub struct AvmCircuitPublicInputs { /////////////////////////////////// // Outputs. end_tree_snapshots: TreeSnapshots, + end_gas_used: Gas, accumulated_data: AvmAccumulatedData, transaction_fee: Field, reverted: bool, @@ -43,6 +46,7 @@ impl Empty for AvmCircuitPublicInputs { AvmCircuitPublicInputs { global_variables: GlobalVariables::empty(), start_tree_snapshots: TreeSnapshots::empty(), + start_gas_used: Gas::empty(), gas_settings: GasSettings::empty(), public_setup_call_requests: [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], public_app_logic_call_requests: [PublicCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_TX], @@ -52,6 +56,7 @@ impl Empty for AvmCircuitPublicInputs { previous_non_revertible_accumulated_data: PrivateToAvmAccumulatedData::empty(), previous_revertible_accumulated_data: PrivateToAvmAccumulatedData::empty(), end_tree_snapshots: TreeSnapshots::empty(), + end_gas_used: Gas::empty(), accumulated_data: AvmAccumulatedData::empty(), transaction_fee: 0, reverted: false, @@ -63,6 +68,7 @@ impl Eq for AvmCircuitPublicInputs { fn eq(self, other: Self) -> bool { (self.global_variables == other.global_variables) & (self.start_tree_snapshots == other.start_tree_snapshots) + & (self.start_gas_used == other.start_gas_used) & (self.gas_settings == other.gas_settings) & (self.public_setup_call_requests == other.public_setup_call_requests) & (self.public_app_logic_call_requests == other.public_app_logic_call_requests) @@ -84,6 +90,7 @@ impl Eq for AvmCircuitPublicInputs { == other.previous_revertible_accumulated_data ) & (self.end_tree_snapshots == other.end_tree_snapshots) + & (self.end_gas_used == other.end_gas_used) & (self.accumulated_data == other.accumulated_data) & (self.transaction_fee == other.transaction_fee) & (self.reverted == other.reverted) @@ -96,6 +103,7 @@ impl Serialize for AvmCircuitPublicInputs { fields.extend_from_array(self.global_variables.serialize()); fields.extend_from_array(self.start_tree_snapshots.serialize()); + fields.extend_from_array(self.start_gas_used.serialize()); fields.extend_from_array(self.gas_settings.serialize()); for i in 0..self.public_setup_call_requests.len() { fields.extend_from_array(self.public_setup_call_requests[i].serialize()); @@ -111,6 +119,7 @@ impl Serialize for AvmCircuitPublicInputs { fields.extend_from_array(self.previous_non_revertible_accumulated_data.serialize()); fields.extend_from_array(self.previous_revertible_accumulated_data.serialize()); fields.extend_from_array(self.end_tree_snapshots.serialize()); + fields.extend_from_array(self.end_gas_used.serialize()); fields.extend_from_array(self.accumulated_data.serialize()); fields.push(self.transaction_fee); fields.push(self.reverted as Field); @@ -127,6 +136,7 @@ impl Deserialize for AvmCircuitPublicInputs { let item = AvmCircuitPublicInputs { global_variables: reader.read_struct(GlobalVariables::deserialize), start_tree_snapshots: reader.read_struct(TreeSnapshots::deserialize), + start_gas_used: reader.read_struct(Gas::deserialize), gas_settings: reader.read_struct(GasSettings::deserialize), public_setup_call_requests: reader.read_struct_array( PublicCallRequest::deserialize, @@ -150,6 +160,7 @@ impl Deserialize for AvmCircuitPublicInputs { PrivateToAvmAccumulatedData::deserialize, ), end_tree_snapshots: reader.read_struct(TreeSnapshots::deserialize), + end_gas_used: reader.read_struct(Gas::deserialize), accumulated_data: reader.read_struct(AvmAccumulatedData::deserialize), transaction_fee: reader.read(), reverted: reader.read() as bool, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/combined_constant_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/combined_constant_data.nr index 3bf4f558a0d..03e9863016b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/combined_constant_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/combined_constant_data.nr @@ -6,17 +6,17 @@ use crate::transaction::tx_context::TxContext; use crate::utils::reader::Reader; pub struct CombinedConstantData { - historical_header: Header, + pub historical_header: Header, // Note: `chain_id` and `version` in tx_context are not redundant to the values in // self.historical_header.global_variables because they can be different in case of a protocol upgrade. In such // a situation we could be using header from a block before the upgrade took place but be using the updated // protocol to execute and prove the transaction. - tx_context: TxContext, - vk_tree_root: Field, - protocol_contract_tree_root: Field, + pub tx_context: TxContext, + pub vk_tree_root: Field, + pub protocol_contract_tree_root: Field, // Should be empty for private-only txs. This is filled in by the sequencer for txs with public calls. - global_variables: GlobalVariables, + pub global_variables: GlobalVariables, } impl CombinedConstantData { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/contract_class_function_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/contract_class_function_leaf_preimage.nr index df6c115b6f6..cbbe90d98e4 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/contract_class_function_leaf_preimage.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/contract_class_function_leaf_preimage.nr @@ -4,8 +4,8 @@ use crate::hash::poseidon2_hash_with_separator; use crate::traits::Hash; pub struct ContractClassFunctionLeafPreimage { - selector: FunctionSelector, - vk_hash: Field, + pub selector: FunctionSelector, + pub vk_hash: Field, } impl Hash for ContractClassFunctionLeafPreimage { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/enqueued_call_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/enqueued_call_data.nr index 06c8db2ef42..ca862ecdaf4 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/enqueued_call_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/enqueued_call_data.nr @@ -4,6 +4,6 @@ use crate::abis::kernel_circuit_public_inputs::vm_circuit_public_inputs::VMCircu pub struct Proof {} pub struct EnqueuedCallData { - data: VMCircuitPublicInputs, - proof: Proof, + pub data: VMCircuitPublicInputs, + pub proof: Proof, } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr index 2366cb99ab7..d73187f52a4 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr @@ -5,8 +5,8 @@ use crate::{ }; pub struct FunctionData { - selector: FunctionSelector, - is_private: bool, + pub selector: FunctionSelector, + pub is_private: bool, } impl Eq for FunctionData { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr index e5aa823cec1..a195a0179d0 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr @@ -2,7 +2,7 @@ use crate::traits::{Deserialize, Empty, FromField, Serialize, ToField}; pub struct FunctionSelector { // 1st 4-bytes of abi-encoding of function. - inner: u32, + pub inner: u32, } impl Eq for FunctionSelector { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr index 60e2b29fa77..7c8b9f84996 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr @@ -1,8 +1,8 @@ use crate::{constants::GAS_FEES_LENGTH, traits::{Deserialize, Empty, Serialize}}; pub struct GasFees { - fee_per_da_gas: Field, - fee_per_l2_gas: Field, + pub fee_per_da_gas: Field, + pub fee_per_l2_gas: Field, } impl GasFees { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr index bf31b75ac47..764d05e4a42 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr @@ -1,8 +1,7 @@ use crate::{ abis::{gas::Gas, gas_fees::GasFees}, constants::{ - DEFAULT_GAS_LIMIT, DEFAULT_INCLUSION_FEE, DEFAULT_MAX_FEE_PER_GAS, - DEFAULT_TEARDOWN_GAS_LIMIT, GAS_SETTINGS_LENGTH, + DEFAULT_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS, DEFAULT_TEARDOWN_GAS_LIMIT, GAS_SETTINGS_LENGTH, }, traits::{Deserialize, Empty, Serialize}, utils::reader::Reader, @@ -12,17 +11,11 @@ pub struct GasSettings { gas_limits: Gas, teardown_gas_limits: Gas, max_fees_per_gas: GasFees, - inclusion_fee: Field, } impl GasSettings { - pub fn new( - gas_limits: Gas, - teardown_gas_limits: Gas, - max_fees_per_gas: GasFees, - inclusion_fee: Field, - ) -> Self { - Self { gas_limits, teardown_gas_limits, max_fees_per_gas, inclusion_fee } + pub fn new(gas_limits: Gas, teardown_gas_limits: Gas, max_fees_per_gas: GasFees) -> Self { + Self { gas_limits, teardown_gas_limits, max_fees_per_gas } } pub fn default() -> Self { @@ -30,7 +23,6 @@ impl GasSettings { Gas::new(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT), Gas::new(DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT), GasFees::new(DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_FEE_PER_GAS), - DEFAULT_INCLUSION_FEE, ) } } @@ -40,13 +32,12 @@ impl Eq for GasSettings { (self.gas_limits == other.gas_limits) & (self.teardown_gas_limits == other.teardown_gas_limits) & (self.max_fees_per_gas == other.max_fees_per_gas) - & (self.inclusion_fee == other.inclusion_fee) } } impl Empty for GasSettings { fn empty() -> Self { - GasSettings::new(Gas::empty(), Gas::empty(), GasFees::empty(), 0) + GasSettings::new(Gas::empty(), Gas::empty(), GasFees::empty()) } } @@ -57,9 +48,8 @@ impl Serialize for GasSettings { serialized.extend_from_array(self.gas_limits.serialize()); serialized.extend_from_array(self.teardown_gas_limits.serialize()); serialized.extend_from_array(self.max_fees_per_gas.serialize()); - serialized.push(self.inclusion_fee); - serialized.storage + serialized.storage() } } @@ -70,7 +60,6 @@ impl Deserialize for GasSettings { reader.read_struct(Gas::deserialize), reader.read_struct(Gas::deserialize), reader.read_struct(GasFees::deserialize), - reader.read(), ) } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr index abcfab91273..deb4de74aa2 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr @@ -8,14 +8,14 @@ use crate::{ // docs:start:global-variables pub struct GlobalVariables { - chain_id: Field, - version: Field, - block_number: Field, - slot_number: Field, - timestamp: u64, - coinbase: EthAddress, - fee_recipient: AztecAddress, - gas_fees: GasFees, + pub chain_id: Field, + pub version: Field, + pub block_number: Field, + pub slot_number: Field, + pub timestamp: u64, + pub coinbase: EthAddress, + pub fee_recipient: AztecAddress, + pub gas_fees: GasFees, } // docs:end:global-variables @@ -45,7 +45,7 @@ impl Serialize for GlobalVariables { serialized.push(self.fee_recipient.to_field()); serialized.extend_from_array(self.gas_fees.serialize()); - serialized.storage + serialized.storage() } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr index 1c0c70bea6d..115beab20f9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr @@ -1,7 +1,7 @@ use crate::{ abis::{ accumulated_data::CombinedAccumulatedData, combined_constant_data::CombinedConstantData, - validation_requests::RollupValidationRequests, + gas::Gas, validation_requests::RollupValidationRequests, }, address::AztecAddress, constants::KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH, @@ -12,12 +12,13 @@ use crate::{ // TODO: Update it to be specifically for the private_kernel_tail once we remove public_kernel_tail, which also outputs this. pub struct KernelCircuitPublicInputs { - rollup_validation_requests: RollupValidationRequests, - end: CombinedAccumulatedData, - constants: CombinedConstantData, - start_state: PartialStateReference, - revert_code: u8, - fee_payer: AztecAddress, + pub rollup_validation_requests: RollupValidationRequests, + pub end: CombinedAccumulatedData, + pub constants: CombinedConstantData, + pub start_state: PartialStateReference, + pub revert_code: u8, + pub gas_used: Gas, + pub fee_payer: AztecAddress, } impl Empty for KernelCircuitPublicInputs { @@ -28,6 +29,7 @@ impl Empty for KernelCircuitPublicInputs { constants: CombinedConstantData::empty(), start_state: PartialStateReference::empty(), revert_code: 0, + gas_used: Gas::empty(), fee_payer: AztecAddress::empty(), } } @@ -40,6 +42,7 @@ impl Eq for KernelCircuitPublicInputs { & (self.constants.eq(other.constants)) & (self.start_state.eq(other.start_state)) & (self.revert_code == other.revert_code) + & (self.gas_used == other.gas_used) & (self.fee_payer.eq(other.fee_payer)) } } @@ -53,6 +56,7 @@ impl Serialize for KernelCircuitPublicInput fields.extend_from_array(self.constants.serialize()); fields.extend_from_array(self.start_state.serialize()); fields.push(self.revert_code as Field); + fields.extend_from_array(self.gas_used.serialize()); fields.extend_from_array(self.fee_payer.serialize()); assert_eq(fields.len(), KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH); @@ -72,6 +76,7 @@ impl Deserialize for KernelCircuitPublicInp constants: reader.read_struct(CombinedConstantData::deserialize), start_state: reader.read_struct(PartialStateReference::deserialize), revert_code: reader.read() as u8, + gas_used: reader.read_struct(Gas::deserialize), fee_payer: reader.read_struct(AztecAddress::deserialize), }; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/mod.nr index d3f95abdae1..03d416e5e03 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/mod.nr @@ -1,10 +1,10 @@ -mod kernel_circuit_public_inputs; -mod private_kernel_circuit_public_inputs; -mod private_kernel_circuit_public_inputs_builder; -mod private_to_public_kernel_circuit_public_inputs; -mod public_kernel_circuit_public_inputs; -mod public_kernel_circuit_public_inputs_builder; -mod vm_circuit_public_inputs; +pub mod kernel_circuit_public_inputs; +pub mod private_kernel_circuit_public_inputs; +pub mod private_kernel_circuit_public_inputs_builder; +pub mod private_to_public_kernel_circuit_public_inputs; +pub mod public_kernel_circuit_public_inputs; +pub mod public_kernel_circuit_public_inputs_builder; +pub mod vm_circuit_public_inputs; pub use kernel_circuit_public_inputs::KernelCircuitPublicInputs; pub use private_kernel_circuit_public_inputs::{ diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr index 917840135b4..c99ace67a29 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr @@ -18,7 +18,7 @@ pub struct PrivateKernelCircuitPublicInputsArrayLengths { l2_to_l1_msgs: u32, note_encrypted_logs_hashes: u32, encrypted_logs_hashes: u32, - unencrypted_logs_hashes: u32, + contract_class_logs_hashes: u32, public_call_requests: u32, private_call_stack: u32, } @@ -40,7 +40,7 @@ impl PrivateKernelCircuitPublicInputsArrayLengths { l2_to_l1_msgs: array_length(public_inputs.end.l2_to_l1_msgs), note_encrypted_logs_hashes: array_length(public_inputs.end.note_encrypted_logs_hashes), encrypted_logs_hashes: array_length(public_inputs.end.encrypted_logs_hashes), - unencrypted_logs_hashes: array_length(public_inputs.end.unencrypted_logs_hashes), + contract_class_logs_hashes: array_length(public_inputs.end.contract_class_logs_hashes), public_call_requests: array_length(public_inputs.end.public_call_requests), private_call_stack: array_length(public_inputs.end.private_call_stack), } @@ -56,7 +56,7 @@ impl PrivateKernelCircuitPublicInputsArrayLengths { l2_to_l1_msgs: 0, note_encrypted_logs_hashes: 0, encrypted_logs_hashes: 0, - unencrypted_logs_hashes: 0, + contract_class_logs_hashes: 0, public_call_requests: 0, private_call_stack: 0, } @@ -76,19 +76,19 @@ impl Eq for PrivateKernelCircuitPublicInputsArrayLengths { & (self.l2_to_l1_msgs == other.l2_to_l1_msgs) & (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) & (self.encrypted_logs_hashes == other.encrypted_logs_hashes) - & (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) + & (self.contract_class_logs_hashes == other.contract_class_logs_hashes) & (self.public_call_requests == other.public_call_requests) & (self.private_call_stack == other.private_call_stack) } } pub struct PrivateKernelCircuitPublicInputs { - constants: TxConstantData, - min_revertible_side_effect_counter: u32, - validation_requests: PrivateValidationRequests, - end: PrivateAccumulatedData, - public_teardown_call_request: PublicCallRequest, - fee_payer: AztecAddress, + pub constants: TxConstantData, + pub min_revertible_side_effect_counter: u32, + pub validation_requests: PrivateValidationRequests, + pub end: PrivateAccumulatedData, + pub public_teardown_call_request: PublicCallRequest, + pub fee_payer: AztecAddress, } impl Serialize for PrivateKernelCircuitPublicInputs { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_to_public_kernel_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_to_public_kernel_circuit_public_inputs.nr index 39da0112fec..517f6870590 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_to_public_kernel_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_to_public_kernel_circuit_public_inputs.nr @@ -1,7 +1,8 @@ use crate::{ abis::{ - accumulated_data::PrivateToPublicAccumulatedData, public_call_request::PublicCallRequest, - tx_constant_data::TxConstantData, validation_requests::RollupValidationRequests, + accumulated_data::PrivateToPublicAccumulatedData, gas::Gas, + public_call_request::PublicCallRequest, tx_constant_data::TxConstantData, + validation_requests::RollupValidationRequests, }, address::AztecAddress, constants::PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH, @@ -10,12 +11,13 @@ use crate::{ }; pub struct PrivateToPublicKernelCircuitPublicInputs { - constants: TxConstantData, - rollup_validation_requests: RollupValidationRequests, - non_revertible_accumulated_data: PrivateToPublicAccumulatedData, - revertible_accumulated_data: PrivateToPublicAccumulatedData, - public_teardown_call_request: PublicCallRequest, - fee_payer: AztecAddress, + pub constants: TxConstantData, + pub rollup_validation_requests: RollupValidationRequests, + pub non_revertible_accumulated_data: PrivateToPublicAccumulatedData, + pub revertible_accumulated_data: PrivateToPublicAccumulatedData, + pub public_teardown_call_request: PublicCallRequest, + pub gas_used: Gas, + pub fee_payer: AztecAddress, } impl Empty for PrivateToPublicKernelCircuitPublicInputs { @@ -26,6 +28,7 @@ impl Empty for PrivateToPublicKernelCircuitPublicInputs { non_revertible_accumulated_data: PrivateToPublicAccumulatedData::empty(), revertible_accumulated_data: PrivateToPublicAccumulatedData::empty(), public_teardown_call_request: PublicCallRequest::empty(), + gas_used: Gas::empty(), fee_payer: AztecAddress::empty(), } } @@ -38,6 +41,7 @@ impl Eq for PrivateToPublicKernelCircuitPublicInputs { & (self.non_revertible_accumulated_data == other.non_revertible_accumulated_data) & (self.revertible_accumulated_data == other.revertible_accumulated_data) & (self.public_teardown_call_request == other.public_teardown_call_request) + & (self.gas_used == other.gas_used) & (self.fee_payer == other.fee_payer) } } @@ -52,6 +56,7 @@ impl Serialize for Privat fields.extend_from_array(self.non_revertible_accumulated_data.serialize()); fields.extend_from_array(self.revertible_accumulated_data.serialize()); fields.extend_from_array(self.public_teardown_call_request.serialize()); + fields.extend_from_array(self.gas_used.serialize()); fields.extend_from_array(self.fee_payer.serialize()); assert_eq(fields.len(), PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH); @@ -76,6 +81,7 @@ impl Deserialize for Priv PrivateToPublicAccumulatedData::deserialize, ), public_teardown_call_request: reader.read_struct(PublicCallRequest::deserialize), + gas_used: reader.read_struct(Gas::deserialize), fee_payer: reader.read_struct(AztecAddress::deserialize), }; reader.finish(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs.nr index fdaafa52e48..701bd43e1dc 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs.nr @@ -10,14 +10,14 @@ use crate::{ }; pub struct PublicKernelCircuitPublicInputs { - constants: CombinedConstantData, - validation_requests: PublicValidationRequests, - end_non_revertible: PublicAccumulatedData, - end: PublicAccumulatedData, - end_side_effect_counter: u32, - public_teardown_call_request: PublicCallRequest, - fee_payer: AztecAddress, - revert_code: u8, + pub constants: CombinedConstantData, + pub validation_requests: PublicValidationRequests, + pub end_non_revertible: PublicAccumulatedData, + pub end: PublicAccumulatedData, + pub end_side_effect_counter: u32, + pub public_teardown_call_request: PublicCallRequest, + pub fee_payer: AztecAddress, + pub revert_code: u8, } impl Empty for PublicKernelCircuitPublicInputs { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/vm_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/vm_circuit_public_inputs.nr index ca283b49fdf..af6fd3b2560 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/vm_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/vm_circuit_public_inputs.nr @@ -14,20 +14,20 @@ use crate::{ // TODO(#9594): To be deprecated. pub struct VMCircuitPublicInputs { - constants: CombinedConstantData, - call_request: PublicCallRequest, + pub constants: CombinedConstantData, + pub call_request: PublicCallRequest, - public_call_stack: [PublicInnerCallRequest; MAX_ENQUEUED_CALLS_PER_TX], + pub public_call_stack: [PublicInnerCallRequest; MAX_ENQUEUED_CALLS_PER_TX], - previous_validation_request_array_lengths: PublicValidationRequestArrayLengths, // Lengths of the validation requests before the enqueued call. - validation_requests: PublicValidationRequests, // Validation requests emitted throughout the enqueued call. - previous_accumulated_data_array_lengths: PublicAccumulatedDataArrayLengths, // Lengths of the accumulated data before the enqueued call. - accumulated_data: PublicAccumulatedData, // Data emitted throughout the enqueued call. - start_side_effect_counter: u32, - end_side_effect_counter: u32, - start_gas_left: Gas, - transaction_fee: Field, - reverted: bool, + pub previous_validation_request_array_lengths: PublicValidationRequestArrayLengths, // Lengths of the validation requests before the enqueued call. + pub validation_requests: PublicValidationRequests, // Validation requests emitted throughout the enqueued call. + pub previous_accumulated_data_array_lengths: PublicAccumulatedDataArrayLengths, // Lengths of the accumulated data before the enqueued call. + pub accumulated_data: PublicAccumulatedData, // Data emitted throughout the enqueued call. + pub start_side_effect_counter: u32, + pub end_side_effect_counter: u32, + pub start_gas_left: Gas, + pub transaction_fee: Field, + pub reverted: bool, } impl Empty for VMCircuitPublicInputs { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr index 6969df71a5e..2b085fffd6a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr @@ -10,9 +10,9 @@ use crate::{ }; pub struct LogHash { - value: Field, - counter: u32, - length: Field, + pub value: Field, + pub counter: u32, + pub length: Field, } impl Ordered for LogHash { @@ -63,8 +63,8 @@ impl LogHash { } pub struct ScopedLogHash { - log_hash: LogHash, - contract_address: AztecAddress, + pub log_hash: LogHash, + pub contract_address: AztecAddress, } impl Scoped for ScopedLogHash { @@ -139,10 +139,10 @@ impl ScopedLogHash { } pub struct EncryptedLogHash { - value: Field, - counter: u32, - length: Field, - randomness: Field, + pub value: Field, + pub counter: u32, + pub length: Field, + pub randomness: Field, } impl Ordered for EncryptedLogHash { @@ -199,8 +199,8 @@ impl EncryptedLogHash { } pub struct ScopedEncryptedLogHash { - log_hash: EncryptedLogHash, - contract_address: AztecAddress, + pub log_hash: EncryptedLogHash, + pub contract_address: AztecAddress, } impl Scoped for ScopedEncryptedLogHash { @@ -279,10 +279,10 @@ impl Deserialize for ScopedEncryptedLogHash { } pub struct NoteLogHash { - value: Field, - counter: u32, - length: Field, - note_hash_counter: u32, + pub value: Field, + pub counter: u32, + pub length: Field, + pub note_hash_counter: u32, } impl NoteLogHash { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr index 501ff0a3c55..131ca7f90e1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr @@ -18,14 +18,18 @@ impl Eq for MaxBlockNumber { impl Serialize for MaxBlockNumber { fn serialize(self) -> [Field; MAX_BLOCK_NUMBER_LENGTH] { - [self._opt._is_some as Field, self._opt._value as Field] + [self._opt.is_some() as Field, self._opt.unwrap_unchecked() as Field] } } impl Deserialize for MaxBlockNumber { fn deserialize(serialized: [Field; MAX_BLOCK_NUMBER_LENGTH]) -> MaxBlockNumber { MaxBlockNumber { - _opt: Option { _is_some: serialized[0] as bool, _value: serialized[1] as u32 }, + _opt: if serialized[0] as bool { + Option::some(serialized[1] as u32) + } else { + Option::none() + }, } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr index 83063fe84cc..0b842cc1625 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr @@ -7,8 +7,8 @@ use crate::{ }; pub struct NoteHash { - value: Field, - counter: u32, + pub value: Field, + pub counter: u32, } impl Ordered for NoteHash { @@ -48,8 +48,8 @@ impl NoteHash { } pub struct ScopedNoteHash { - note_hash: NoteHash, - contract_address: AztecAddress, + pub note_hash: NoteHash, + pub contract_address: AztecAddress, } impl Scoped for ScopedNoteHash { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash_leaf_preimage.nr index 0c8d740f55e..1a77e9fd974 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash_leaf_preimage.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash_leaf_preimage.nr @@ -8,7 +8,7 @@ use crate::{ }; pub struct NoteHashLeafPreimage { - value: Field, + pub value: Field, } impl Empty for NoteHashLeafPreimage { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr index bcbe51a7dbd..eab73ba87a2 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr @@ -79,8 +79,8 @@ impl Nullifier { } pub struct ScopedNullifier { - nullifier: Nullifier, - contract_address: AztecAddress, + pub nullifier: Nullifier, + pub contract_address: AztecAddress, } impl Scoped for ScopedNullifier { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr index d9361aa1dec..09504c10608 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr @@ -1,4 +1,4 @@ -global NULLIFIER_LEAF_PREIMAGE_LENGTH: u32 = 3; +pub global NULLIFIER_LEAF_PREIMAGE_LENGTH: u32 = 3; use crate::{ abis::{read_request::ScopedReadRequest, side_effect::Readable}, @@ -8,9 +8,9 @@ use crate::{ }; pub struct NullifierLeafPreimage { - nullifier: Field, - next_nullifier: Field, - next_index: u32, + pub nullifier: Field, + pub next_nullifier: Field, + pub next_index: u32, } impl Empty for NullifierLeafPreimage { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr index e8d26f48238..680361208e9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr @@ -6,11 +6,11 @@ use crate::{ }; pub struct PrivateCallRequest { - call_context: CallContext, - args_hash: Field, - returns_hash: Field, - start_side_effect_counter: u32, - end_side_effect_counter: u32, + pub call_context: CallContext, + pub args_hash: Field, + pub returns_hash: Field, + pub start_side_effect_counter: u32, + pub end_side_effect_counter: u32, } impl Ordered for PrivateCallRequest { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr index 0f1a754f4b5..78dad89c218 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr @@ -12,12 +12,11 @@ use crate::{ validation_requests::KeyValidationRequestAndGenerator, }, constants::{ - MAX_ENCRYPTED_LOGS_PER_CALL, MAX_ENQUEUED_CALLS_PER_CALL, + MAX_CONTRACT_CLASS_LOGS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_ENQUEUED_CALLS_PER_CALL, MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL, - MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, - PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, + MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, }, header::Header, messaging::l2_to_l1_message::L2ToL1Message, @@ -37,7 +36,7 @@ pub struct PrivateCircuitPublicInputsArrayLengths { public_call_requests: u32, note_encrypted_logs_hashes: u32, encrypted_logs_hashes: u32, - unencrypted_logs_hashes: u32, + contract_class_logs_hashes: u32, } impl PrivateCircuitPublicInputsArrayLengths { @@ -55,47 +54,47 @@ impl PrivateCircuitPublicInputsArrayLengths { public_call_requests: validate_array(public_inputs.public_call_requests), note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes), encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes), - unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes), + contract_class_logs_hashes: validate_array(public_inputs.contract_class_logs_hashes), } } } // Public inputs to private app circuit. pub struct PrivateCircuitPublicInputs { - call_context: CallContext, + pub call_context: CallContext, - args_hash: Field, - returns_hash: Field, + pub args_hash: Field, + pub returns_hash: Field, - min_revertible_side_effect_counter: u32, - is_fee_payer: bool, + pub min_revertible_side_effect_counter: u32, + pub is_fee_payer: bool, - max_block_number: MaxBlockNumber, + pub max_block_number: MaxBlockNumber, - note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], - nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL], - key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL], + pub note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], + pub nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL], + pub key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL], - note_hashes: [NoteHash; MAX_NOTE_HASHES_PER_CALL], - nullifiers: [Nullifier; MAX_NULLIFIERS_PER_CALL], - private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL], - public_call_requests: [Counted; MAX_ENQUEUED_CALLS_PER_CALL], - public_teardown_call_request: PublicCallRequest, - l2_to_l1_msgs: [L2ToL1Message; MAX_L2_TO_L1_MSGS_PER_CALL], + pub note_hashes: [NoteHash; MAX_NOTE_HASHES_PER_CALL], + pub nullifiers: [Nullifier; MAX_NULLIFIERS_PER_CALL], + pub private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL], + pub public_call_requests: [Counted; MAX_ENQUEUED_CALLS_PER_CALL], + pub public_teardown_call_request: PublicCallRequest, + pub l2_to_l1_msgs: [L2ToL1Message; MAX_L2_TO_L1_MSGS_PER_CALL], - start_side_effect_counter: u32, - end_side_effect_counter: u32, - note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL], - encrypted_logs_hashes: [EncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_CALL], - unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL], + pub start_side_effect_counter: u32, + pub end_side_effect_counter: u32, + pub note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL], + pub encrypted_logs_hashes: [EncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_CALL], + pub contract_class_logs_hashes: [LogHash; MAX_CONTRACT_CLASS_LOGS_PER_CALL], // Header of a block whose state is used during private execution (not the block the transaction is included in). - historical_header: Header, + pub historical_header: Header, // Note: The chain_id and version here are not redundant to the values in self.historical_header.global_variables because // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block // before the upgrade took place but be using the updated protocol to execute and prove the transaction. - tx_context: TxContext, + pub tx_context: TxContext, } impl Eq for PrivateCircuitPublicInputs { @@ -121,7 +120,7 @@ impl Eq for PrivateCircuitPublicInputs { & (self.end_side_effect_counter == other.end_side_effect_counter) & (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) & (self.encrypted_logs_hashes == other.encrypted_logs_hashes) - & (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) + & (self.contract_class_logs_hashes == other.contract_class_logs_hashes) & self.historical_header.eq(other.historical_header) & self.tx_context.eq(other.tx_context) } @@ -172,8 +171,8 @@ impl Serialize for PrivateCircuitPublicInp for i in 0..self.encrypted_logs_hashes.len() { fields.extend_from_array(self.encrypted_logs_hashes[i].serialize()); } - for i in 0..self.unencrypted_logs_hashes.len() { - fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize()); + for i in 0..self.contract_class_logs_hashes.len() { + fields.extend_from_array(self.contract_class_logs_hashes[i].serialize()); } fields.extend_from_array(self.historical_header.serialize()); fields.extend_from_array(self.tx_context.serialize()); @@ -238,9 +237,9 @@ impl Deserialize for PrivateCircuitPublicI EncryptedLogHash::deserialize, [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL], ), - unencrypted_logs_hashes: reader.read_struct_array( + contract_class_logs_hashes: reader.read_struct_array( LogHash::deserialize, - [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], + [LogHash::empty(); MAX_CONTRACT_CLASS_LOGS_PER_CALL], ), historical_header: reader.read_struct(Header::deserialize), tx_context: reader.read_struct(TxContext::deserialize), @@ -277,7 +276,7 @@ impl Empty for PrivateCircuitPublicInputs { end_side_effect_counter: 0 as u32, note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL], encrypted_logs_hashes: [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL], - unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], + contract_class_logs_hashes: [LogHash::empty(); MAX_CONTRACT_CLASS_LOGS_PER_CALL], historical_header: Header::empty(), tx_context: TxContext::empty(), } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr index 5b3941764c0..be9751aad92 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr @@ -8,31 +8,31 @@ use crate::{ }; pub struct PrivateCallData { - public_inputs: PrivateCircuitPublicInputs, + pub public_inputs: PrivateCircuitPublicInputs, - vk: ClientIVCVerificationKey, + pub vk: ClientIVCVerificationKey, - salted_initialization_hash: SaltedInitializationHash, - public_keys: PublicKeys, - contract_class_artifact_hash: Field, - contract_class_public_bytecode_commitment: Field, - function_leaf_membership_witness: MembershipWitness, - protocol_contract_sibling_path: [Field; PROTOCOL_CONTRACT_TREE_HEIGHT], + pub salted_initialization_hash: SaltedInitializationHash, + pub public_keys: PublicKeys, + pub contract_class_artifact_hash: Field, + pub contract_class_public_bytecode_commitment: Field, + pub function_leaf_membership_witness: MembershipWitness, + pub protocol_contract_sibling_path: [Field; PROTOCOL_CONTRACT_TREE_HEIGHT], - acir_hash: Field, + pub acir_hash: Field, } pub struct PrivateCallDataWithoutPublicInputs { - vk: ClientIVCVerificationKey, + pub vk: ClientIVCVerificationKey, - salted_initialization_hash: SaltedInitializationHash, - public_keys: PublicKeys, - contract_class_artifact_hash: Field, - contract_class_public_bytecode_commitment: Field, - function_leaf_membership_witness: MembershipWitness, - protocol_contract_sibling_path: [Field; PROTOCOL_CONTRACT_TREE_HEIGHT], + pub salted_initialization_hash: SaltedInitializationHash, + pub public_keys: PublicKeys, + pub contract_class_artifact_hash: Field, + pub contract_class_public_bytecode_commitment: Field, + pub function_leaf_membership_witness: MembershipWitness, + pub protocol_contract_sibling_path: [Field; PROTOCOL_CONTRACT_TREE_HEIGHT], - acir_hash: Field, + pub acir_hash: Field, } impl PrivateCallDataWithoutPublicInputs { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr index 62942a62da9..e272ede7eaa 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr @@ -7,10 +7,10 @@ use crate::{ }; pub struct PrivateKernelData { - public_inputs: PrivateKernelCircuitPublicInputs, - vk: ClientIVCVerificationKey, - vk_index: u32, - vk_path: [Field; VK_TREE_HEIGHT], + pub public_inputs: PrivateKernelCircuitPublicInputs, + pub vk: ClientIVCVerificationKey, + pub vk_index: u32, + pub vk_path: [Field; VK_TREE_HEIGHT], } impl PrivateKernelData { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_data.nr new file mode 100644 index 00000000000..d1efafb102e --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_data.nr @@ -0,0 +1,11 @@ +use crate::abis::public_circuit_public_inputs::PublicCircuitPublicInputs; + +// Mocked here as the only remaining non-recursive proof +pub struct Proof {} + +// TODO(#7124): To be deprecated. +pub struct PublicCallData { + pub public_inputs: PublicCircuitPublicInputs, + pub proof: Proof, + pub bytecode_hash: Field, +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_request.nr index 7502a34f88f..8e4aa25fa6b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_request.nr @@ -7,15 +7,15 @@ use crate::{ }; pub struct PublicCallRequest { - msg_sender: AztecAddress, - contract_address: AztecAddress, + pub msg_sender: AztecAddress, + pub contract_address: AztecAddress, // TODO: To be removed. // Function selector is the first world of calldata. - function_selector: FunctionSelector, + pub function_selector: FunctionSelector, - is_static_call: bool, - args_hash: Field, + pub is_static_call: bool, + pub args_hash: Field, } impl Eq for PublicCallRequest { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr new file mode 100644 index 00000000000..3a5cf64961c --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr @@ -0,0 +1,237 @@ +use crate::{ + abis::{ + call_context::CallContext, gas::Gas, global_variables::GlobalVariables, log_hash::LogHash, + note_hash::NoteHash, nullifier::Nullifier, + public_inner_call_request::PublicInnerCallRequest, read_request::ReadRequest, + tree_leaf_read_request::TreeLeafReadRequest, + }, + address::AztecAddress, + constants::{ + MAX_ENQUEUED_CALLS_PER_CALL, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, + MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_CALL, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, + MAX_NULLIFIERS_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, + }, + contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, + header::Header, + messaging::l2_to_l1_message::L2ToL1Message, + traits::{Deserialize, Empty, Serialize}, + utils::reader::Reader, +}; + +// Public inputs to public app circuit. +pub struct PublicCircuitPublicInputs { + pub call_context: CallContext, + + pub args_hash: Field, + pub returns_hash: Field, + + pub note_hash_read_requests: [TreeLeafReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], + pub nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL], + pub nullifier_non_existent_read_requests: [ReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL], + pub l1_to_l2_msg_read_requests: [TreeLeafReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL], + pub contract_storage_update_requests: [StorageUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL], + pub contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL], + + // todo: add sideeffect ranges for the input to these hashes + pub public_call_requests: [PublicInnerCallRequest; MAX_ENQUEUED_CALLS_PER_CALL], + pub note_hashes: [NoteHash; MAX_NOTE_HASHES_PER_CALL], + pub nullifiers: [Nullifier; MAX_NULLIFIERS_PER_CALL], + pub l2_to_l1_msgs: [L2ToL1Message; MAX_L2_TO_L1_MSGS_PER_CALL], + + pub start_side_effect_counter: u32, + pub end_side_effect_counter: u32, + + pub unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL], + + // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block + // previous to the one in which the tx is included. + pub historical_header: Header, + + // Global variables injected into this circuit + pub global_variables: GlobalVariables, + + pub prover_address: AztecAddress, + + pub revert_code: u8, + + pub start_gas_left: Gas, + pub end_gas_left: Gas, + pub transaction_fee: Field, +} + +impl Eq for PublicCircuitPublicInputs { + fn eq(self, other: Self) -> bool { + self.serialize() == other.serialize() + } +} + +impl Serialize for PublicCircuitPublicInputs { + fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] { + let mut fields: BoundedVec = BoundedVec::new(); + fields.extend_from_array(self.call_context.serialize()); + fields.push(self.args_hash); + fields.push(self.returns_hash); + for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_CALL { + fields.extend_from_array(self.note_hash_read_requests[i].serialize()); + } + for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL { + fields.extend_from_array(self.nullifier_read_requests[i].serialize()); + } + for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL { + fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize()); + } + for i in 0..MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL { + fields.extend_from_array(self.l1_to_l2_msg_read_requests[i].serialize()); + } + for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL { + fields.extend_from_array(self.contract_storage_update_requests[i].serialize()); + } + for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL { + fields.extend_from_array(self.contract_storage_reads[i].serialize()); + } + for i in 0..MAX_ENQUEUED_CALLS_PER_CALL { + fields.extend_from_array(self.public_call_requests[i].serialize()); + } + for i in 0..MAX_NOTE_HASHES_PER_CALL { + fields.extend_from_array(self.note_hashes[i].serialize()); + } + for i in 0..MAX_NULLIFIERS_PER_CALL { + fields.extend_from_array(self.nullifiers[i].serialize()); + } + for i in 0..MAX_L2_TO_L1_MSGS_PER_CALL { + fields.extend_from_array(self.l2_to_l1_msgs[i].serialize()); + } + + fields.push(self.start_side_effect_counter as Field); + fields.push(self.end_side_effect_counter as Field); + + for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL { + fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize()); + } + fields.extend_from_array(self.historical_header.serialize()); + fields.extend_from_array(self.global_variables.serialize()); + fields.push(self.prover_address.to_field()); + fields.push(self.revert_code as Field); + fields.extend_from_array(self.start_gas_left.serialize()); + fields.extend_from_array(self.end_gas_left.serialize()); + fields.push(self.transaction_fee); + fields.storage() + } +} + +impl Deserialize for PublicCircuitPublicInputs { + fn deserialize(serialized: [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self { + // TODO(#4390): This should accept a reader ^ to avoid copying data. + let mut reader = Reader::new(serialized); + let inputs = PublicCircuitPublicInputs { + call_context: reader.read_struct(CallContext::deserialize), + args_hash: reader.read(), + returns_hash: reader.read(), + note_hash_read_requests: reader.read_struct_array( + TreeLeafReadRequest::deserialize, + [TreeLeafReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], + ), + nullifier_read_requests: reader.read_struct_array( + ReadRequest::deserialize, + [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL], + ), + nullifier_non_existent_read_requests: reader.read_struct_array( + ReadRequest::deserialize, + [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL], + ), + l1_to_l2_msg_read_requests: reader.read_struct_array( + TreeLeafReadRequest::deserialize, + [TreeLeafReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL], + ), + contract_storage_update_requests: reader.read_struct_array( + StorageUpdateRequest::deserialize, + [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL], + ), + contract_storage_reads: reader.read_struct_array( + StorageRead::deserialize, + [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL], + ), + public_call_requests: reader.read_struct_array( + PublicInnerCallRequest::deserialize, + [PublicInnerCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_CALL], + ), + note_hashes: reader.read_struct_array( + NoteHash::deserialize, + [NoteHash::empty(); MAX_NOTE_HASHES_PER_CALL], + ), + nullifiers: reader.read_struct_array( + Nullifier::deserialize, + [Nullifier::empty(); MAX_NULLIFIERS_PER_CALL], + ), + l2_to_l1_msgs: reader.read_struct_array( + L2ToL1Message::deserialize, + [L2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_CALL], + ), + start_side_effect_counter: reader.read() as u32, + end_side_effect_counter: reader.read() as u32, + unencrypted_logs_hashes: reader.read_struct_array( + LogHash::deserialize, + [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], + ), + historical_header: reader.read_struct(Header::deserialize), + global_variables: reader.read_struct(GlobalVariables::deserialize), + prover_address: reader.read_struct(AztecAddress::deserialize), + revert_code: reader.read() as u8, + start_gas_left: reader.read_struct(Gas::deserialize), + end_gas_left: reader.read_struct(Gas::deserialize), + transaction_fee: reader.read(), + }; + + reader.finish(); + inputs + } +} + +impl Empty for PublicCircuitPublicInputs { + fn empty() -> Self { + PublicCircuitPublicInputs { + call_context: CallContext::empty(), + args_hash: 0, + returns_hash: 0, + note_hash_read_requests: [ + TreeLeafReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL + ], + nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL], + nullifier_non_existent_read_requests: [ + ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL + ], + l1_to_l2_msg_read_requests: [ + TreeLeafReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL + ], + contract_storage_update_requests: [ + StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL + ], + contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL], + public_call_requests: [PublicInnerCallRequest::empty(); MAX_ENQUEUED_CALLS_PER_CALL], + note_hashes: [NoteHash::empty(); MAX_NOTE_HASHES_PER_CALL], + nullifiers: [Nullifier::empty(); MAX_NULLIFIERS_PER_CALL], + l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_CALL], + start_side_effect_counter: 0 as u32, + end_side_effect_counter: 0 as u32, + unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], + historical_header: Header::empty(), + global_variables: GlobalVariables::empty(), + prover_address: AztecAddress::zero(), + revert_code: 0 as u8, + start_gas_left: Gas::empty(), + end_gas_left: Gas::empty(), + transaction_fee: 0, + } + } +} + +#[test] +fn serialization_of_empty() { + let pcpi = PublicCircuitPublicInputs::empty(); + let serialized = pcpi.serialize(); + let deserialized = PublicCircuitPublicInputs::deserialize(serialized); + assert(pcpi.eq(deserialized)); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_read.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_read.nr index 15ae34c512e..f2dc6e6d739 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_read.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_read.nr @@ -5,9 +5,9 @@ use crate::{ }; pub struct PublicDataRead { - leaf_slot: Field, - value: Field, - counter: u32, + pub leaf_slot: Field, + pub value: Field, + pub counter: u32, } impl Eq for PublicDataRead { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr index 988e795f267..1cbcc3f6a56 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr @@ -7,9 +7,9 @@ use crate::{ // TODO: Rename to PublicDataWrite pub struct PublicDataUpdateRequest { - leaf_slot: Field, - new_value: Field, - counter: u32, + pub leaf_slot: Field, + pub new_value: Field, + pub counter: u32, } impl Ordered for PublicDataUpdateRequest { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr index 8e86512fafd..e65ee047329 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr @@ -10,11 +10,11 @@ use crate::{ }; pub struct PublicKernelData { - public_inputs: PublicKernelCircuitPublicInputs, - proof: NestedRecursiveProof, - vk: HonkVerificationKey, - vk_index: u32, - vk_path: [Field; VK_TREE_HEIGHT], + pub public_inputs: PublicKernelCircuitPublicInputs, + pub proof: NestedRecursiveProof, + pub vk: HonkVerificationKey, + pub vk_index: u32, + pub vk_path: [Field; VK_TREE_HEIGHT], } impl Verifiable for PublicKernelData { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr index 8191f4ee4dc..0511d3a7236 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr @@ -7,8 +7,8 @@ use crate::{ }; pub struct ReadRequest { - value: Field, - counter: u32, + pub value: Field, + pub counter: u32, } impl Ordered for ReadRequest { @@ -48,8 +48,8 @@ impl ReadRequest { } pub struct ScopedReadRequest { - read_request: ReadRequest, - contract_address: AztecAddress, + pub read_request: ReadRequest, + pub contract_address: AztecAddress, } impl Scoped for ScopedReadRequest { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/tree_leaf_read_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/tree_leaf_read_request.nr index 22998960b2c..97076df51e8 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/tree_leaf_read_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/tree_leaf_read_request.nr @@ -1,8 +1,8 @@ use crate::{constants::TREE_LEAF_READ_REQUEST_LENGTH, traits::{Deserialize, Empty, Serialize}}; pub struct TreeLeafReadRequest { - value: Field, - leaf_index: Field, + pub value: Field, + pub leaf_index: Field, } impl Eq for TreeLeafReadRequest { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/tx_constant_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/tx_constant_data.nr index 9d3d8d6bcd9..be7c8151d70 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/tx_constant_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/tx_constant_data.nr @@ -8,14 +8,14 @@ use crate::{ // Constants used throughout the executions of both private and public. pub struct TxConstantData { - historical_header: Header, + pub historical_header: Header, // Note: `chain_id` and `version` in tx_context are not redundant to the values in // self.historical_header.global_variables because they can be different in case of a protocol upgrade. In such // a situation we could be using header from a block before the upgrade took place but be using the updated // protocol to execute and prove the transaction. - tx_context: TxContext, - vk_tree_root: Field, - protocol_contract_tree_root: Field, + pub tx_context: TxContext, + pub vk_tree_root: Field, + pub protocol_contract_tree_root: Field, } impl Empty for TxConstantData { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr index cb2c3eea7d3..78ddc929b6b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr @@ -2,8 +2,8 @@ use crate::{point::Point, traits::{Deserialize, Empty, Serialize}}; pub use crate::constants::KEY_VALIDATION_REQUEST_LENGTH; pub struct KeyValidationRequest { - pk_m: Point, - sk_app: Field, // not a grumpkin scalar because it's output of poseidon2 + pub pk_m: Point, + pub sk_app: Field, // not a grumpkin scalar because it's output of poseidon2 } impl Eq for KeyValidationRequest { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr index 5ae055a5724..3cac3031196 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr @@ -10,8 +10,8 @@ use crate::{ }; pub struct KeyValidationRequestAndGenerator { - request: KeyValidationRequest, - sk_app_generator: Field, + pub request: KeyValidationRequest, + pub sk_app_generator: Field, } impl Eq for KeyValidationRequestAndGenerator { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/mod.nr index 31703c5c251..d6cf2668f07 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/mod.nr @@ -1,11 +1,11 @@ -mod key_validation_request; -mod key_validation_request_and_generator; -mod private_validation_requests; -mod private_validation_requests_builder; -mod public_validation_requests; -mod public_validation_requests_builder; -mod rollup_validation_requests; -mod scoped_key_validation_request_and_generator; +pub mod key_validation_request; +pub mod key_validation_request_and_generator; +pub mod private_validation_requests; +pub mod private_validation_requests_builder; +pub mod public_validation_requests; +pub mod public_validation_requests_builder; +pub mod rollup_validation_requests; +pub mod scoped_key_validation_request_and_generator; pub use key_validation_request::KeyValidationRequest; pub use key_validation_request_and_generator::KeyValidationRequestAndGenerator; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/private_validation_requests.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/private_validation_requests.nr index a5be36aee20..3357f60b294 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/private_validation_requests.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/private_validation_requests.nr @@ -15,11 +15,11 @@ use crate::{ }; pub struct PrivateValidationRequests { - for_rollup: RollupValidationRequests, - note_hash_read_requests: [ScopedReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], - nullifier_read_requests: [ScopedReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_TX], - scoped_key_validation_requests_and_generators: [ScopedKeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_TX], - split_counter: Option, + pub for_rollup: RollupValidationRequests, + pub note_hash_read_requests: [ScopedReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], + pub nullifier_read_requests: [ScopedReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_TX], + pub scoped_key_validation_requests_and_generators: [ScopedKeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_TX], + pub split_counter: Option, } impl Serialize for PrivateValidationRequests { @@ -70,7 +70,13 @@ impl Deserialize for PrivateValidationReques MAX_KEY_VALIDATION_REQUESTS_PER_TX ], ), - split_counter: Option { _is_some: reader.read_bool(), _value: reader.read_u32() }, + split_counter: if reader.read_bool() { + Option::some(reader.read_u32()) + } else { + // We need to read the final reader value even if we don't use it in order to flush the reader. + let _ = reader.read_u32(); + Option::none() + }, }; reader.finish(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/private_validation_requests_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/private_validation_requests_builder.nr index 1fe0e108e8b..c5b0ddbb5e9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/private_validation_requests_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/private_validation_requests_builder.nr @@ -27,11 +27,11 @@ impl PrivateValidationRequestsBuilder { pub fn finish(self) -> PrivateValidationRequests { PrivateValidationRequests { for_rollup: self.for_rollup(), - note_hash_read_requests: self.note_hash_read_requests.storage, - nullifier_read_requests: self.nullifier_read_requests.storage, + note_hash_read_requests: self.note_hash_read_requests.storage(), + nullifier_read_requests: self.nullifier_read_requests.storage(), scoped_key_validation_requests_and_generators: self .scoped_key_validation_requests_and_generators - .storage, + .storage(), split_counter: self.split_counter, } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/public_validation_requests.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/public_validation_requests.nr index 2767e7e5d5e..165249091fc 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/public_validation_requests.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/public_validation_requests.nr @@ -15,12 +15,12 @@ use crate::{ }; pub struct PublicValidationRequests { - for_rollup: RollupValidationRequests, - note_hash_read_requests: [TreeLeafReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], - nullifier_read_requests: [ScopedReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_TX], - nullifier_non_existent_read_requests: [ScopedReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX], - l1_to_l2_msg_read_requests: [TreeLeafReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX], - public_data_reads: [PublicDataRead; MAX_PUBLIC_DATA_READS_PER_TX], + pub for_rollup: RollupValidationRequests, + pub note_hash_read_requests: [TreeLeafReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_TX], + pub nullifier_read_requests: [ScopedReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_TX], + pub nullifier_non_existent_read_requests: [ScopedReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX], + pub l1_to_l2_msg_read_requests: [TreeLeafReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX], + pub public_data_reads: [PublicDataRead; MAX_PUBLIC_DATA_READS_PER_TX], } impl Serialize for PublicValidationRequests { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/public_validation_requests_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/public_validation_requests_builder.nr index b5a45d5faea..30f38166770 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/public_validation_requests_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/public_validation_requests_builder.nr @@ -44,11 +44,11 @@ impl PublicValidationRequestsBuilder { pub fn finish(self) -> PublicValidationRequests { PublicValidationRequests { for_rollup: self.for_rollup(), - note_hash_read_requests: self.note_hash_read_requests.storage, - nullifier_read_requests: self.nullifier_read_requests.storage, - nullifier_non_existent_read_requests: self.nullifier_non_existent_read_requests.storage, - public_data_reads: self.public_data_reads.storage, - l1_to_l2_msg_read_requests: self.l1_to_l2_msg_read_requests.storage, + note_hash_read_requests: self.note_hash_read_requests.storage(), + nullifier_read_requests: self.nullifier_read_requests.storage(), + nullifier_non_existent_read_requests: self.nullifier_non_existent_read_requests.storage(), + public_data_reads: self.public_data_reads.storage(), + l1_to_l2_msg_read_requests: self.l1_to_l2_msg_read_requests.storage(), } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/rollup_validation_requests.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/rollup_validation_requests.nr index 79ddba32742..a78f38da126 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/rollup_validation_requests.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/rollup_validation_requests.nr @@ -8,7 +8,7 @@ use crate::{ // These are validation requests that cannot be fulfilled in the current context (private or public), and must be // instead forwarded to the rollup for it to take care of them. pub struct RollupValidationRequests { - max_block_number: MaxBlockNumber, + pub max_block_number: MaxBlockNumber, } impl Empty for RollupValidationRequests { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/scoped_key_validation_request_and_generator.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/scoped_key_validation_request_and_generator.nr index 17eda595bc8..b7110818147 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/scoped_key_validation_request_and_generator.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/scoped_key_validation_request_and_generator.nr @@ -10,8 +10,8 @@ use crate::{ }; pub struct ScopedKeyValidationRequestAndGenerator { - request: KeyValidationRequestAndGenerator, - contract_address: AztecAddress, + pub request: KeyValidationRequestAndGenerator, + pub contract_address: AztecAddress, } impl Scoped for ScopedKeyValidationRequestAndGenerator { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr index 3dbaa0521a2..add563f1a32 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr @@ -1,17 +1,16 @@ use crate::{ abis::function_selector::FunctionSelector, address::{ - partial_address::PartialAddress, public_keys_hash::PublicKeysHash, - salted_initialization_hash::SaltedInitializationHash, + partial_address::PartialAddress, salted_initialization_hash::SaltedInitializationHash, }, constants::{ AZTEC_ADDRESS_LENGTH, FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__CONTRACT_ADDRESS_V1, - GENERATOR_INDEX__PUBLIC_KEYS_HASH, MAX_FIELD_VALUE, + MAX_FIELD_VALUE, }, contract_class_id::ContractClassId, hash::{poseidon2_hash_with_separator, private_functions_root_from_siblings}, merkle_tree::membership::MembershipWitness, - public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, ToPoint, TpkM}, + public_keys::{IvpkM, NpkM, OvpkM, PublicKeys, TpkM}, traits::{Deserialize, Empty, FromField, Serialize, ToField}, utils, }; @@ -27,7 +26,7 @@ use std::{ // Aztec address pub struct AztecAddress { - inner: Field, + pub inner: Field, } impl Eq for AztecAddress { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/mod.nr index 88b0236e421..04b09ae70a7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/mod.nr @@ -1,8 +1,8 @@ -mod aztec_address; -mod eth_address; -mod partial_address; -mod public_keys_hash; -mod salted_initialization_hash; +pub mod aztec_address; +pub mod eth_address; +pub mod partial_address; +pub mod public_keys_hash; +pub mod salted_initialization_hash; pub use aztec_address::AztecAddress; pub use eth_address::EthAddress; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr index e44ff45d7d5..e44e5d387a8 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr @@ -10,7 +10,7 @@ global PARTIAL_ADDRESS_LENGTH: u32 = 1; // Partial address pub struct PartialAddress { - inner: Field, + pub inner: Field, } impl ToField for PartialAddress { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr index 5ef32bae6e8..824b5cb2341 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr @@ -5,7 +5,7 @@ use crate::{ // Salted initialization hash. Used in the computation of a partial address. pub struct SaltedInitializationHash { - inner: Field, + pub inner: Field, } impl ToField for SaltedInitializationHash { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index c1881a4675b..b7542af13b3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -41,6 +41,7 @@ pub global MAX_KEY_VALIDATION_REQUESTS_PER_CALL: u32 = 16; pub global MAX_NOTE_ENCRYPTED_LOGS_PER_CALL: u32 = 16; pub global MAX_ENCRYPTED_LOGS_PER_CALL: u32 = 4; pub global MAX_UNENCRYPTED_LOGS_PER_CALL: u32 = 4; +pub global MAX_CONTRACT_CLASS_LOGS_PER_CALL: u32 = 1; // TREES RELATED CONSTANTS pub global ARCHIVE_HEIGHT: u32 = 29; @@ -94,6 +95,7 @@ pub global MAX_KEY_VALIDATION_REQUESTS_PER_TX: u32 = 64; pub global MAX_NOTE_ENCRYPTED_LOGS_PER_TX: u32 = 64; pub global MAX_ENCRYPTED_LOGS_PER_TX: u32 = 8; pub global MAX_UNENCRYPTED_LOGS_PER_TX: u32 = 8; +pub global MAX_CONTRACT_CLASS_LOGS_PER_TX: u32 = 1; // docs:end:constants // KERNEL CIRCUIT PRIVATE INPUTS CONSTANTS @@ -142,7 +144,7 @@ pub global GENESIS_ARCHIVE_ROOT: Field = 0x2a05cb8aeefe9b9797f90650eae072f5ab7437807e62f9724ce1900467779860; // The following and the value in `deploy_l1_contracts` must match. We should not have the code both places, but // we are running into circular dependency issues. #3342 -pub global FEE_JUICE_INITIAL_MINT: Field = 20000000000; +global FEE_JUICE_INITIAL_MINT: Field = 200000000000000; // Last 4 bytes of the Poseidon2 hash of 'public_dispatch(Field)'. pub global PUBLIC_DISPATCH_SELECTOR: Field = 0xd5441b0d; @@ -179,7 +181,6 @@ pub global DEFAULT_GAS_LIMIT: u32 = 1_000_000_000; pub global DEFAULT_TEARDOWN_GAS_LIMIT: u32 = 12_000_000; pub global MAX_L2_GAS_PER_ENQUEUED_CALL: u32 = 12_000_000; pub global DEFAULT_MAX_FEE_PER_GAS: Field = 10; -pub global DEFAULT_INCLUSION_FEE: Field = 0; pub global DA_BYTES_PER_FIELD: u32 = 32; pub global DA_GAS_PER_BYTE: u32 = 16; // pays for preamble information in TX Effects @@ -253,7 +254,7 @@ pub global DEFAULT_TPK_M_Y = 0x2039907fe37f08d10739255141bb066c506a12f7d1e8dfec2 pub global AZTEC_ADDRESS_LENGTH: u32 = 1; pub global GAS_FEES_LENGTH: u32 = 2; pub global GAS_LENGTH: u32 = 2; -pub global GAS_SETTINGS_LENGTH: u32 = GAS_LENGTH * 2 + GAS_FEES_LENGTH + /* inclusion_fee */ 1; +pub global GAS_SETTINGS_LENGTH: u32 = GAS_LENGTH * 2 + GAS_FEES_LENGTH; pub global CALL_CONTEXT_LENGTH: u32 = 4; pub global CONTENT_COMMITMENT_LENGTH: u32 = 4; pub global CONTRACT_INSTANCE_LENGTH: u32 = 16; @@ -323,7 +324,7 @@ pub global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + 2 + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_CALL) + (ENCRYPTED_LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) - + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + + (LOG_HASH_LENGTH * MAX_CONTRACT_CLASS_LOGS_PER_CALL) + HEADER_LENGTH + TX_CONTEXT_LENGTH; pub global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH @@ -375,10 +376,10 @@ pub global COMBINED_ACCUMULATED_DATA_LENGTH: u32 = MAX_NOTE_HASHES_PER_TX + (MAX_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX) + (SCOPED_LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) - + 3 - + (MAX_UNENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) - + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_WRITE_LENGTH) - + GAS_LENGTH; + + 4 + + (SCOPED_LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + + (SCOPED_LOG_HASH_LENGTH * MAX_CONTRACT_CLASS_LOGS_PER_TX) + + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_WRITE_LENGTH); pub global TX_CONSTANT_DATA_LENGTH: u32 = HEADER_LENGTH + TX_CONTEXT_LENGTH + 1 /* vk_tree_root */ @@ -390,7 +391,7 @@ pub global PRIVATE_ACCUMULATED_DATA_LENGTH: u32 = (SCOPED_NOTE_HASH_LENGTH * MAX + (MAX_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX) + (SCOPED_ENCRYPTED_LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) - + (SCOPED_LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + + (SCOPED_LOG_HASH_LENGTH * MAX_CONTRACT_CLASS_LOGS_PER_TX) + (PRIVATE_CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + (COUNTED_PUBLIC_CALL_REQUEST_LENGTH * MAX_ENQUEUED_CALLS_PER_TX); pub global PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = TX_CONSTANT_DATA_LENGTH @@ -416,9 +417,8 @@ pub global PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH: u32 = MAX_NOTE_HASHES_PER_ + (MAX_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (MAX_NOTE_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_ENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) - + (MAX_UNENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) - + (MAX_ENQUEUED_CALLS_PER_TX * PUBLIC_CALL_REQUEST_LENGTH) - + GAS_LENGTH; + + (MAX_CONTRACT_CLASS_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) + + (MAX_ENQUEUED_CALLS_PER_TX * PUBLIC_CALL_REQUEST_LENGTH); pub global PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH: u32 = MAX_NOTE_HASHES_PER_TX + MAX_NULLIFIERS_PER_TX @@ -436,6 +436,7 @@ pub global PRIVATE_TO_PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = TX_CONST + PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH /* non_revertible_accumulated_data */ + PRIVATE_TO_PUBLIC_ACCUMULATED_DATA_LENGTH /* revertible_accumulated_data */ + PUBLIC_CALL_REQUEST_LENGTH /* public_teardown_call_request */ + + GAS_LENGTH /* gas_used */ + AZTEC_ADDRESS_LENGTH /* fee_payer */; pub global PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = COMBINED_CONSTANT_DATA_LENGTH + PUBLIC_VALIDATION_REQUESTS_LENGTH @@ -462,11 +463,13 @@ pub global KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = ROLLUP_VALIDATION_REQUESTS + COMBINED_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH - + 1 + + 1 /* revert_code */ + + GAS_LENGTH /* gas_used */ + AZTEC_ADDRESS_LENGTH; pub global AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = GLOBAL_VARIABLES_LENGTH + TREE_SNAPSHOTS_LENGTH /* start_tree_snapshots */ + + GAS_LENGTH /* start_gas_used */ + GAS_SETTINGS_LENGTH + (MAX_ENQUEUED_CALLS_PER_TX * PUBLIC_CALL_REQUEST_LENGTH) /* public_setup_call_requests */ + (MAX_ENQUEUED_CALLS_PER_TX * PUBLIC_CALL_REQUEST_LENGTH) /* public_app_logic_call_requests */ @@ -476,10 +479,10 @@ pub global AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = GLOBAL_VARIABLES_LENGTH + PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH /* previous_non_revertible_accumulated_data */ + PRIVATE_TO_AVM_ACCUMULATED_DATA_LENGTH /* previous_revertible_accumulated_data */ + TREE_SNAPSHOTS_LENGTH /* end_tree_snapshots */ + + GAS_LENGTH /* end_gas_used */ + AVM_ACCUMULATED_DATA_LENGTH + 1 /* transaction_fee */ - + 1 /* reverted */ -; + + 1 /* reverted */; pub global CONSTANT_ROLLUP_DATA_LENGTH: u32 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + 1 /* vk_tree_root */ @@ -537,7 +540,7 @@ pub global AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS: u32 = 2 + 21 * 4; // `AVM_PROOF_LENGTH_IN_FIELDS` must be updated when AVM circuit changes. // To determine latest value, hover `COMPUTED_AVM_PROOF_LENGTH_IN_FIELDS` // in barretenberg/cpp/src/barretenberg/vm/avm/generated/flavor.hpp -pub global AVM_PROOF_LENGTH_IN_FIELDS: u32 = 4211; +pub global AVM_PROOF_LENGTH_IN_FIELDS: u32 = 4291; pub global AVM_PUBLIC_COLUMN_MAX_SIZE: u32 = 1024; pub global AVM_PUBLIC_INPUTS_FLATTENED_SIZE: u32 = 2 * AVM_PUBLIC_COLUMN_MAX_SIZE + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH; @@ -708,7 +711,8 @@ pub global AVM_CALL_BASE_L2_GAS: u32 = 45 + (2 * L2_GAS_PER_NULLIFIER_READ_REQUE pub global AVM_STATICCALL_BASE_L2_GAS: u32 = 45 + (2 * L2_GAS_PER_NULLIFIER_READ_REQUEST); pub global AVM_RETURN_BASE_L2_GAS: u32 = 28; pub global AVM_REVERT_BASE_L2_GAS: u32 = 28; -pub global AVM_DEBUGLOG_BASE_L2_GAS: u32 = 12; // Must be equal to AVM_JUMP_BASE_L2_GAS as long as circuit implements debugLog as a jump +pub global AVM_DEBUGLOG_BASE_L2_GAS: u32 = 12; +pub global AVM_DEBUGLOG_DYN_L2_GAS: u32 = 3; pub global AVM_POSEIDON2_BASE_L2_GAS: u32 = 78; pub global AVM_SHA256COMPRESSION_BASE_L2_GAS: u32 = 261; pub global AVM_KECCAKF1600_BASE_L2_GAS: u32 = 300; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr index 76938ab5391..c70783fd035 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr @@ -2,7 +2,7 @@ use crate::constants::GENERATOR_INDEX__CONTRACT_LEAF; use crate::traits::{Deserialize, FromField, Serialize, ToField}; pub struct ContractClassId { - inner: Field, + pub inner: Field, } impl Eq for ContractClassId { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr index 115a1e9ad6d..bce65761c52 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr @@ -1,8 +1,5 @@ use crate::{ - address::{ - aztec_address::AztecAddress, partial_address::PartialAddress, - public_keys_hash::PublicKeysHash, - }, + address::{aztec_address::AztecAddress, partial_address::PartialAddress}, constants::CONTRACT_INSTANCE_LENGTH, contract_class_id::ContractClassId, public_keys::PublicKeys, @@ -10,11 +7,11 @@ use crate::{ }; pub struct ContractInstance { - salt: Field, - deployer: AztecAddress, - contract_class_id: ContractClassId, - initialization_hash: Field, - public_keys: PublicKeys, + pub salt: Field, + pub deployer: AztecAddress, + pub contract_class_id: ContractClassId, + pub initialization_hash: Field, + pub public_keys: PublicKeys, } impl Eq for ContractInstance { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/mod.nr new file mode 100644 index 00000000000..d4562b82bd7 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/mod.nr @@ -0,0 +1,2 @@ +pub mod storage_read; +pub mod storage_update_request; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_read.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_read.nr new file mode 100644 index 00000000000..ac94988b6ea --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_read.nr @@ -0,0 +1,51 @@ +use crate::{constants::CONTRACT_STORAGE_READ_LENGTH, traits::{Deserialize, Empty, Serialize}}; + +pub struct StorageRead { + pub storage_slot: Field, + pub current_value: Field, + pub counter: u32, +} + +impl Eq for StorageRead { + fn eq(self, other: Self) -> bool { + (self.storage_slot == other.storage_slot) + & (self.current_value == other.current_value) + & (self.current_value == other.current_value) + } +} + +impl Empty for StorageRead { + fn empty() -> Self { + Self { storage_slot: 0, current_value: 0, counter: 0 } + } +} + +impl Serialize for StorageRead { + fn serialize(self) -> [Field; CONTRACT_STORAGE_READ_LENGTH] { + [self.storage_slot, self.current_value, self.counter as Field] + } +} + +impl Deserialize for StorageRead { + fn deserialize(serialized: [Field; CONTRACT_STORAGE_READ_LENGTH]) -> Self { + Self { + storage_slot: serialized[0], + current_value: serialized[1], + counter: serialized[2] as u32, + } + } +} + +impl StorageRead { + pub fn is_empty(self) -> bool { + (self.storage_slot == 0) & (self.current_value == 0) & (self.counter == 0) + } +} + +#[test] +fn serialization_of_empty() { + let item = StorageRead::empty(); + let serialized = item.serialize(); + let deserialized = StorageRead::deserialize(serialized); + assert(item.eq(deserialized)); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr new file mode 100644 index 00000000000..3ab1442f1a5 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr @@ -0,0 +1,52 @@ +use crate::{ + constants::CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH, + traits::{Deserialize, Empty, Serialize}, +}; + +pub struct StorageUpdateRequest { + pub storage_slot: Field, + pub new_value: Field, + pub counter: u32, +} + +impl Eq for StorageUpdateRequest { + fn eq(self, request: Self) -> bool { + (request.storage_slot == self.storage_slot) & (request.new_value == self.new_value) + } +} + +impl Empty for StorageUpdateRequest { + fn empty() -> Self { + StorageUpdateRequest { storage_slot: 0, new_value: 0, counter: 0 } + } +} + +impl Serialize for StorageUpdateRequest { + fn serialize(self) -> [Field; CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH] { + [self.storage_slot, self.new_value, self.counter as Field] + } +} + +impl Deserialize for StorageUpdateRequest { + fn deserialize(serialized: [Field; CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH]) -> Self { + StorageUpdateRequest { + storage_slot: serialized[0], + new_value: serialized[1], + counter: serialized[2] as u32, + } + } +} + +impl StorageUpdateRequest { + pub fn is_empty(self) -> bool { + self.storage_slot == 0 + } +} + +#[test] +fn serialization_of_empty() { + let item = StorageUpdateRequest::empty(); + let serialized = item.serialize(); + let deserialized = StorageUpdateRequest::deserialize(serialized); + assert(item.eq(deserialized)); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/data/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/data/mod.nr index ff14e4cfce7..a450152ea7e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/data/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/data/mod.nr @@ -1,8 +1,8 @@ -mod public_data_hint; -mod public_data_leaf_hint; -mod public_data_tree_leaf; -mod public_data_tree_leaf_preimage; -mod hash; +pub mod public_data_hint; +pub mod public_data_leaf_hint; +pub mod public_data_tree_leaf; +pub mod public_data_tree_leaf_preimage; +pub mod hash; pub use public_data_hint::PublicDataHint; pub use public_data_leaf_hint::PublicDataLeafHint; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_tree_leaf.nr b/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_tree_leaf.nr index 64f02300c9e..a65c295d8ed 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_tree_leaf.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_tree_leaf.nr @@ -4,8 +4,8 @@ use crate::{ }; pub struct PublicDataTreeLeaf { - slot: Field, - value: Field, + pub slot: Field, + pub value: Field, } impl Eq for PublicDataTreeLeaf { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_tree_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_tree_leaf_preimage.nr index 99d9b410412..e895921ce1a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_tree_leaf_preimage.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/data/public_data_tree_leaf_preimage.nr @@ -1,10 +1,10 @@ use crate::{merkle_tree::leaf_preimage::IndexedTreeLeafPreimage, traits::{Empty, Hash}}; pub struct PublicDataTreeLeafPreimage { - slot: Field, - value: Field, - next_slot: Field, - next_index: u32, + pub slot: Field, + pub value: Field, + pub next_slot: Field, + pub next_index: u32, } impl Empty for PublicDataTreeLeafPreimage { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr index 80ccd3129dd..84004c7c2f4 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -9,12 +9,11 @@ use crate::{ address::{AztecAddress, EthAddress}, constants::{ FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__OUTER_NULLIFIER, - GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__UNIQUE_NOTE_HASH, GENERATOR_INDEX__VK, - MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__UNIQUE_NOTE_HASH, + MAX_CONTRACT_CLASS_LOGS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, }, merkle_tree::root::root_from_sibling_path, messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message}, - proof::verification_key::VerificationKey, traits::{is_empty, ToField}, utils::field::field_from_bytes_32_trunc, }; @@ -148,7 +147,7 @@ pub fn compute_l2_to_l1_hash( } } - sha256_to_field(bytes.storage) + sha256_to_field(bytes.storage()) } pub fn silo_l2_to_l1_message( @@ -200,34 +199,10 @@ pub fn accumulate_sha256(input: [Field; 2]) -> Field { } // Computes the final logs hash for a tx. -// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX -// to avoid doubling code, since we can't define the byte len to be 32*N directly. -pub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field { +pub fn compute_tx_logs_hash(logs: [LogHash; N]) -> Field { // Convert each field element into a byte array and append the bytes to `hash_input_flattened` - let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32]; - for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX { - // TODO: This is not checking that the decomposition is smaller than P - let input_as_bytes: [u8; 32] = logs[offset].value.to_be_radix(256); - for byte_index in 0..32 { - hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index]; - } - } - // Ideally we would push to a slice then hash, but there is no sha_slice - // Hardcode to 256 bytes for now - let mut hash = sha256_to_field(hash_input_flattened); - // Not having a 0 value hash for empty logs causes issues with empty txs - // used for padding. Returning early is currently unsupported. - // We always provide sorted logs here, so 0 being empty means all are empty. - if is_empty(logs[0]) { - hash = 0; - } - hash -} - -pub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field { - // Convert each field element into a byte array and append the bytes to `hash_input_flattened` - let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32]; - for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX { + let mut hash_input_flattened = [0; N * 32]; + for offset in 0..N { // TODO: This is not checking that the decomposition is smaller than P let input_as_bytes: [u8; 32] = logs[offset].value.to_be_radix(256); for byte_index in 0..32 { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/header.nr b/noir-projects/noir-protocol-circuits/crates/types/src/header.nr index 46f503c91e8..23e9c6a2a87 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/header.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/header.nr @@ -16,11 +16,11 @@ use crate::{ // docs:start:header pub struct Header { - last_archive: AppendOnlyTreeSnapshot, - content_commitment: ContentCommitment, - state: StateReference, - global_variables: GlobalVariables, - total_fees: Field, + pub last_archive: AppendOnlyTreeSnapshot, + pub content_commitment: ContentCommitment, + pub state: StateReference, + pub global_variables: GlobalVariables, + pub total_fees: Field, } // docs:end:header diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/indexed_tagging_secret.nr b/noir-projects/noir-protocol-circuits/crates/types/src/indexed_tagging_secret.nr index 3ea0310ef92..89837964cff 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/indexed_tagging_secret.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/indexed_tagging_secret.nr @@ -2,19 +2,16 @@ use crate::traits::{Deserialize, Serialize}; use super::{address::aztec_address::AztecAddress, hash::poseidon2_hash}; use std::meta::derive; -pub global INDEXED_TAGGING_SECRET_LENGTH: u32 = 3; +pub global INDEXED_TAGGING_SECRET_LENGTH: u32 = 2; #[derive(Serialize, Deserialize)] pub struct IndexedTaggingSecret { secret: Field, - recipient: AztecAddress, index: u32, } impl IndexedTaggingSecret { - pub fn compute_tag(self) -> Field { - poseidon2_hash( - [self.secret, self.recipient.to_field(), self.index as Field], - ) + pub fn compute_tag(self, recipient: AztecAddress) -> Field { + poseidon2_hash([self.secret, recipient.to_field(), self.index as Field]) } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr index 90bbb47c139..25274b49b48 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/lib.nr @@ -1,34 +1,34 @@ -mod utils; -mod address; +pub mod utils; +pub mod address; pub mod debug_log; pub mod public_keys; -mod point; -mod scalar; -mod transaction; -mod abis; +pub mod point; +pub mod scalar; +pub mod transaction; +pub mod abis; pub mod constants; -mod contract_class_id; -mod merkle_tree; -mod contract_instance; +pub mod contract_class_id; +pub mod merkle_tree; +pub mod contract_instance; -mod messaging; +pub mod messaging; pub mod hash; pub mod traits; -mod type_serialization; +pub mod type_serialization; -mod content_commitment; -mod header; +pub mod content_commitment; +pub mod header; mod tests; -mod state_reference; -mod partial_state_reference; +pub mod state_reference; +pub mod partial_state_reference; pub mod proof; -mod data; -mod storage; -mod validate; -mod meta; -mod indexed_tagging_secret; +pub mod data; +pub mod storage; +pub mod validate; +pub mod meta; +pub mod indexed_tagging_secret; pub use abis::kernel_circuit_public_inputs::{ KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree.nr index 1a12382093b..f0cc741a909 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree.nr @@ -1,4 +1,4 @@ -mod check_valid_low_leaf; +pub mod check_valid_low_leaf; use crate::{ abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr index 1d3815dde9a..340be40393d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr @@ -7,8 +7,8 @@ use crate::{ }; pub struct MembershipWitness { - leaf_index: Field, - sibling_path: [Field; N], + pub leaf_index: Field, + pub sibling_path: [Field; N], } impl Empty for MembershipWitness { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/merkle_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/merkle_tree.nr index f1d52918883..f5c91ee75af 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/merkle_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/merkle_tree.nr @@ -1,8 +1,8 @@ use crate::{hash::merkle_hash, traits::Empty}; pub struct MerkleTree { - leaves: [Field; N], - nodes: [Field; N], + pub leaves: [Field; N], + pub nodes: [Field; N], } impl Empty for MerkleTree { @@ -32,7 +32,7 @@ impl MerkleTree { MerkleTree { leaves, nodes } } - fn get_root(self) -> Field { + pub fn get_root(self) -> Field { self.nodes[N - 2] } @@ -44,7 +44,7 @@ impl MerkleTree { } } - fn get_sibling_path(self, leaf_index: u32) -> [Field; K] { + pub fn get_sibling_path(self, leaf_index: u32) -> [Field; K] { assert_eq(2.pow_32(K as Field), N as Field, "Invalid path length"); let mut path = [0; K]; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/mod.nr index e3afdddb7f1..0b993e3bb22 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/mod.nr @@ -1,10 +1,10 @@ -mod append_only_tree; -mod indexed_tree; -mod leaf_preimage; -mod membership; +pub mod append_only_tree; +pub mod indexed_tree; +pub mod leaf_preimage; +pub mod membership; pub mod merkle_tree; -mod root; -mod variable_merkle_tree; +pub mod root; +pub mod variable_merkle_tree; pub use leaf_preimage::{IndexedTreeLeafPreimage, LeafPreimage}; pub use membership::{ diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/variable_merkle_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/variable_merkle_tree.nr index aec8dbe1cdb..9c353ab02ab 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/variable_merkle_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/variable_merkle_tree.nr @@ -3,7 +3,7 @@ use crate::hash::accumulate_sha256; // For now we only care about the root pub struct VariableMerkleTree { // leaves: [Field; N], - root: Field, + pub root: Field, } unconstrained fn get_height(input: u32, start: u8) -> u8 { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr b/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr index b3de63f26b0..0bde8f3684a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr @@ -8,9 +8,9 @@ use crate::{ // Note: Not to be confused with L2ToL1Msg in Solidity pub struct L2ToL1Message { - recipient: EthAddress, - content: Field, - counter: u32, + pub recipient: EthAddress, + pub content: Field, + pub counter: u32, } impl Ordered for L2ToL1Message { @@ -56,8 +56,8 @@ impl L2ToL1Message { } pub struct ScopedL2ToL1Message { - message: L2ToL1Message, - contract_address: AztecAddress, + pub message: L2ToL1Message, + pub contract_address: AztecAddress, } impl ScopedL2ToL1Message { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr b/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr index b85b9b3e328..baa83ae9015 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr @@ -5,9 +5,9 @@ use crate::{ }; pub struct PartialStateReference { - note_hash_tree: AppendOnlyTreeSnapshot, - nullifier_tree: AppendOnlyTreeSnapshot, - public_data_tree: AppendOnlyTreeSnapshot, + pub note_hash_tree: AppendOnlyTreeSnapshot, + pub nullifier_tree: AppendOnlyTreeSnapshot, + pub public_data_tree: AppendOnlyTreeSnapshot, } impl Eq for PartialStateReference { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/point.nr b/noir-projects/noir-protocol-circuits/crates/types/src/point.nr index 62a9212a7c9..eaa7bdd2c2a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/point.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/point.nr @@ -1,7 +1,7 @@ pub use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point; use crate::{hash::poseidon2_hash, traits::{Deserialize, Empty, Hash, Serialize}}; -global POINT_LENGTH: u32 = 3; +pub global POINT_LENGTH: u32 = 3; impl Serialize for Point { fn serialize(self: Self) -> [Field; POINT_LENGTH] { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/proof/recursive_proof.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/recursive_proof.nr index 2dafd8391d2..383d9786edc 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/proof/recursive_proof.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/proof/recursive_proof.nr @@ -4,7 +4,7 @@ use crate::{ }; pub struct RecursiveProof { - fields: [Field; RECURSIVE_PROOF_LENGTH], + pub fields: [Field; RECURSIVE_PROOF_LENGTH], } impl Serialize for RecursiveProof { @@ -26,7 +26,7 @@ impl Empty for RecursiveProof { } pub struct NestedRecursiveProof { - fields: [Field; NESTED_RECURSIVE_PROOF_LENGTH], + pub fields: [Field; NESTED_RECURSIVE_PROOF_LENGTH], } impl Serialize for NestedRecursiveProof { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr b/noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr index 18d5662968f..46572b1e69b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/proof/verification_key.nr @@ -7,8 +7,8 @@ use crate::{ }; pub struct VerificationKey { - key: [Field; N], - hash: Field, + pub key: [Field; N], + pub hash: Field, } impl VerificationKey { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/public_keys.nr b/noir-projects/noir-protocol-circuits/crates/types/src/public_keys.nr index 93e7d673ca6..ef369eaf2b5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/public_keys.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/public_keys.nr @@ -10,17 +10,15 @@ use crate::{ }; use dep::std::embedded_curve_ops::EmbeddedCurvePoint as Point; -use dep::std::embedded_curve_ops::fixed_base_scalar_mul as derive_public_key; use std::default::Default; -use std::embedded_curve_ops::EmbeddedCurveScalar; pub global PUBLIC_KEYS_LENGTH: u32 = 12; pub struct PublicKeys { - npk_m: NpkM, - ivpk_m: IvpkM, - ovpk_m: OvpkM, - tpk_m: TpkM, + pub npk_m: NpkM, + pub ivpk_m: IvpkM, + pub ovpk_m: OvpkM, + pub tpk_m: TpkM, } pub trait ToPoint { @@ -28,7 +26,7 @@ pub trait ToPoint { } pub struct NpkM { - inner: Point, + pub inner: Point, } impl ToPoint for NpkM { @@ -51,7 +49,7 @@ impl Hash for NpkM { } pub struct IvpkM { - inner: Point, + pub inner: Point, } impl ToPoint for IvpkM { @@ -67,7 +65,7 @@ impl Serialize for IvpkM { } pub struct OvpkM { - inner: Point, + pub inner: Point, } impl Hash for OvpkM { @@ -89,7 +87,7 @@ impl Serialize for OvpkM { } pub struct TpkM { - inner: Point, + pub inner: Point, } impl ToPoint for TpkM { @@ -196,7 +194,7 @@ impl Deserialize for PublicKeys { } pub struct AddressPoint { - inner: Point, + pub inner: Point, } impl ToPoint for AddressPoint { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr b/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr index 02f7eae0569..2af97314c02 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr @@ -7,8 +7,8 @@ use crate::{ }; pub struct StateReference { - l1_to_l2_message_tree: AppendOnlyTreeSnapshot, - partial: PartialStateReference, + pub l1_to_l2_message_tree: AppendOnlyTreeSnapshot, + pub partial: PartialStateReference, } impl Eq for StateReference { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/storage/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/storage/mod.nr index 4dc2dfd9153..1d7f53b094e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/storage/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/storage/mod.nr @@ -1 +1 @@ -mod map; +pub mod map; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index e75ebd6e413..96fd4a771d6 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -44,8 +44,8 @@ use crate::{ address::{AztecAddress, EthAddress, SaltedInitializationHash}, constants::{ CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS, FUNCTION_TREE_HEIGHT, - MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, MAX_FIELD_VALUE, - MAX_KEY_VALIDATION_REQUESTS_PER_TX, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, + MAX_CONTRACT_CLASS_LOGS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_ENQUEUED_CALLS_PER_TX, + MAX_FIELD_VALUE, MAX_KEY_VALIDATION_REQUESTS_PER_TX, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, @@ -87,101 +87,103 @@ fn vec_reverse(vec: BoundedVec) -> BoundedVec { let len = vec.len(); for i in 0..N { if i < len { - reversed.push(vec.storage[len - i - 1]); + reversed.push(vec.get_unchecked(len - i - 1)); } } reversed } pub struct FixtureBuilder { - contract_address: AztecAddress, - msg_sender: AztecAddress, - is_static_call: bool, + pub contract_address: AztecAddress, + pub msg_sender: AztecAddress, + pub is_static_call: bool, // Fees. - is_fee_payer: bool, - fee_payer: AztecAddress, - public_teardown_call_request: PublicCallRequest, - transaction_fee: Field, - start_gas_left: Gas, - end_gas_left: Gas, + pub is_fee_payer: bool, + pub fee_payer: AztecAddress, + pub public_teardown_call_request: PublicCallRequest, + pub transaction_fee: Field, + pub start_gas_left: Gas, + pub end_gas_left: Gas, // Constant data. - historical_header: Header, - tx_context: TxContext, - global_variables: GlobalVariables, + pub historical_header: Header, + pub tx_context: TxContext, + pub global_variables: GlobalVariables, // Accumulated data. - note_hashes: BoundedVec, - nullifiers: BoundedVec, - l2_to_l1_msgs: BoundedVec, - note_encrypted_logs_hashes: BoundedVec, - encrypted_logs_hashes: BoundedVec, - unencrypted_logs_hashes: BoundedVec, - note_encrypted_logs_hash: Field, - encrypted_logs_hash: Field, - unencrypted_logs_hash: Field, - note_encrypted_log_preimages_length: Field, - encrypted_log_preimages_length: Field, - unencrypted_log_preimages_length: Field, - public_data_writes: BoundedVec, - public_data_update_requests: BoundedVec, - private_call_requests: BoundedVec, - public_call_requests: BoundedVec, MAX_ENQUEUED_CALLS_PER_TX>, - public_inner_call_requests: BoundedVec, - gas_used: Gas, - revert_code: u8, + pub note_hashes: BoundedVec, + pub nullifiers: BoundedVec, + pub l2_to_l1_msgs: BoundedVec, + pub note_encrypted_logs_hashes: BoundedVec, + pub encrypted_logs_hashes: BoundedVec, + pub unencrypted_logs_hashes: BoundedVec, + pub contract_class_logs_hashes: BoundedVec, + pub note_encrypted_logs_hash: Field, + pub encrypted_logs_hash: Field, + pub unencrypted_logs_hash: Field, + pub note_encrypted_log_preimages_length: Field, + pub encrypted_log_preimages_length: Field, + pub unencrypted_log_preimages_length: Field, + pub contract_class_log_preimages_length: Field, + pub public_data_writes: BoundedVec, + pub public_data_update_requests: BoundedVec, + pub private_call_requests: BoundedVec, + pub public_call_requests: BoundedVec, MAX_ENQUEUED_CALLS_PER_TX>, + pub public_inner_call_requests: BoundedVec, + pub gas_used: Gas, + pub revert_code: u8, // Validation requests. - max_block_number: MaxBlockNumber, - note_hash_read_requests: BoundedVec, - note_hash_tree_leaf_read_requests: BoundedVec, - nullifier_read_requests: BoundedVec, - nullifier_non_existent_read_requests: BoundedVec, - l1_to_l2_msg_read_requests: BoundedVec, - scoped_key_validation_requests_and_generators: BoundedVec, - public_data_reads: BoundedVec, - validation_requests_split_counter: Option, + pub max_block_number: MaxBlockNumber, + pub note_hash_read_requests: BoundedVec, + pub note_hash_tree_leaf_read_requests: BoundedVec, + pub nullifier_read_requests: BoundedVec, + pub nullifier_non_existent_read_requests: BoundedVec, + pub l1_to_l2_msg_read_requests: BoundedVec, + pub scoped_key_validation_requests_and_generators: BoundedVec, + pub public_data_reads: BoundedVec, + pub validation_requests_split_counter: Option, // Function. - function_data: FunctionData, - args_hash: Field, - returns_hash: Field, + pub function_data: FunctionData, + pub args_hash: Field, + pub returns_hash: Field, // Private call. - salted_initialization_hash: SaltedInitializationHash, - public_keys: PublicKeys, - contract_class_artifact_hash: Field, - contract_class_public_bytecode_commitment: Field, - function_leaf_membership_witness: MembershipWitness, - acir_hash: Field, + pub salted_initialization_hash: SaltedInitializationHash, + pub public_keys: PublicKeys, + pub contract_class_artifact_hash: Field, + pub contract_class_public_bytecode_commitment: Field, + pub function_leaf_membership_witness: MembershipWitness, + pub acir_hash: Field, // Public call. - bytecode_hash: Field, - prover_address: AztecAddress, + pub bytecode_hash: Field, + pub prover_address: AztecAddress, // Proof. - proof: NestedRecursiveProof, - honk_vk: HonkVerificationKey, - client_ivc_vk: ClientIVCVerificationKey, - vk_index: u32, - vk_path: [Field; VK_TREE_HEIGHT], - vk_tree_root: Field, + pub proof: NestedRecursiveProof, + pub honk_vk: HonkVerificationKey, + pub client_ivc_vk: ClientIVCVerificationKey, + pub vk_index: u32, + pub vk_path: [Field; VK_TREE_HEIGHT], + pub vk_tree_root: Field, // Protocol contracts. - protocol_contract_tree_root: Field, - protocol_contract_sibling_path: [Field; PROTOCOL_CONTRACT_TREE_HEIGHT], + pub protocol_contract_tree_root: Field, + pub protocol_contract_sibling_path: [Field; PROTOCOL_CONTRACT_TREE_HEIGHT], // Counters. - min_revertible_side_effect_counter: u32, - counter_start: u32, - counter: u32, + pub min_revertible_side_effect_counter: u32, + pub counter_start: u32, + pub counter: u32, // States. - start_state: PartialStateReference, + pub start_state: PartialStateReference, // Mock data. - value_offset: Field, + pub value_offset: Field, } impl FixtureBuilder { @@ -347,35 +349,35 @@ impl FixtureBuilder { min_revertible_side_effect_counter: self.min_revertible_side_effect_counter, is_fee_payer: self.is_fee_payer, max_block_number: self.max_block_number, - note_hash_read_requests: subarray(self.note_hash_read_requests.storage.map( + note_hash_read_requests: subarray(self.note_hash_read_requests.storage().map( |r: ScopedReadRequest| r.read_request, )), - nullifier_read_requests: subarray(self.nullifier_read_requests.storage.map( + nullifier_read_requests: subarray(self.nullifier_read_requests.storage().map( |r: ScopedReadRequest| r.read_request, )), key_validation_requests_and_generators: subarray(self .scoped_key_validation_requests_and_generators - .storage + .storage() .map(|r: ScopedKeyValidationRequestAndGenerator| r.request)), note_hashes: subarray( - self.note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash), + self.note_hashes.storage().map(|n: ScopedNoteHash| n.note_hash), ), nullifiers: subarray( - self.nullifiers.storage.map(|n: ScopedNullifier| n.nullifier), + self.nullifiers.storage().map(|n: ScopedNullifier| n.nullifier), ), - private_call_requests: subarray(self.private_call_requests.storage), - public_call_requests: subarray(self.public_call_requests.storage), + private_call_requests: subarray(self.private_call_requests.storage()), + public_call_requests: subarray(self.public_call_requests.storage()), public_teardown_call_request: self.public_teardown_call_request, - l2_to_l1_msgs: subarray(self.l2_to_l1_msgs.storage.map(|r: ScopedL2ToL1Message| { + l2_to_l1_msgs: subarray(self.l2_to_l1_msgs.storage().map(|r: ScopedL2ToL1Message| { r.message })), start_side_effect_counter: self.counter_start, end_side_effect_counter: self.counter, - note_encrypted_logs_hashes: subarray(self.note_encrypted_logs_hashes.storage), - encrypted_logs_hashes: subarray(self.encrypted_logs_hashes.storage.map( + note_encrypted_logs_hashes: subarray(self.note_encrypted_logs_hashes.storage()), + encrypted_logs_hashes: subarray(self.encrypted_logs_hashes.storage().map( |l: ScopedEncryptedLogHash| l.log_hash, )), - unencrypted_logs_hashes: subarray(self.unencrypted_logs_hashes.storage.map( + contract_class_logs_hashes: subarray(self.contract_class_logs_hashes.storage().map( |l: ScopedLogHash| l.log_hash, )), historical_header: self.historical_header, @@ -405,7 +407,7 @@ impl FixtureBuilder { l2_to_l1_msgs: self.l2_to_l1_msgs, note_encrypted_logs_hashes: self.note_encrypted_logs_hashes, encrypted_logs_hashes: self.encrypted_logs_hashes, - unencrypted_logs_hashes: self.unencrypted_logs_hashes, + contract_class_logs_hashes: self.contract_class_logs_hashes, public_call_requests: self.public_call_requests, private_call_stack: vec_reverse(self.private_call_requests), } @@ -426,29 +428,20 @@ impl FixtureBuilder { } pub fn to_public_accumulated_data_builder(self) -> PublicAccumulatedDataBuilder { - let nullifiers = BoundedVec { - storage: self.nullifiers.storage.map(|n: ScopedNullifier| n.nullifier), - len: self.nullifiers.len(), - }; - let note_encrypted_logs_hashes = BoundedVec { - storage: self.note_encrypted_logs_hashes.storage.map(|l: NoteLogHash| { - LogHash { value: l.value, counter: l.counter, length: l.length } - }), - len: self.note_encrypted_logs_hashes.len(), - }; - let encrypted_logs_hashes = BoundedVec { - storage: self.encrypted_logs_hashes.storage.map(|l: ScopedEncryptedLogHash| { - ScopedLogHash { - log_hash: LogHash { - value: l.log_hash.value, - counter: l.log_hash.counter, - length: l.log_hash.length, - }, - contract_address: l.contract_address, - } - }), - len: self.encrypted_logs_hashes.len(), - }; + let nullifiers = self.nullifiers.map(|n: ScopedNullifier| n.nullifier); + let note_encrypted_logs_hashes = self.note_encrypted_logs_hashes.map(|l: NoteLogHash| { + LogHash { value: l.value, counter: l.counter, length: l.length } + }); + let encrypted_logs_hashes = self.encrypted_logs_hashes.map(|l: ScopedEncryptedLogHash| { + ScopedLogHash { + log_hash: LogHash { + value: l.log_hash.value, + counter: l.log_hash.counter, + length: l.log_hash.length, + }, + contract_address: l.contract_address, + } + }); PublicAccumulatedDataBuilder { note_hashes: self.note_hashes, @@ -471,59 +464,61 @@ impl FixtureBuilder { pub fn to_private_to_public_accumulated_data(self) -> PrivateToPublicAccumulatedData { PrivateToPublicAccumulatedData { - note_hashes: self.note_hashes.storage.map(|n: ScopedNoteHash| n.value()), - nullifiers: self.nullifiers.storage.map(|n: ScopedNullifier| n.value()), - l2_to_l1_msgs: self.l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| { + note_hashes: self.note_hashes.storage().map(|n: ScopedNoteHash| n.value()), + nullifiers: self.nullifiers.storage().map(|n: ScopedNullifier| n.value()), + l2_to_l1_msgs: self.l2_to_l1_msgs.storage().map(|m: ScopedL2ToL1Message| { m.expose_to_public() }), - note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage.map( + note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage().map( |l: NoteLogHash| l.expose_to_public(), ), - encrypted_logs_hashes: self.encrypted_logs_hashes.storage.map( + encrypted_logs_hashes: self.encrypted_logs_hashes.storage().map( |l: ScopedEncryptedLogHash| l.expose_to_public(), ), - unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage.map(|l: ScopedLogHash| { - l.expose_to_public() - }), - public_call_requests: self.public_call_requests.storage.map( + contract_class_logs_hashes: self.contract_class_logs_hashes.storage().map( + |l: ScopedLogHash| l.expose_to_public(), + ), + public_call_requests: self.public_call_requests.storage().map( |cr: Counted| cr.inner, ), - gas_used: self.gas_used, } } pub fn to_combined_accumulated_data(self) -> CombinedAccumulatedData { CombinedAccumulatedData { - note_hashes: self.note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash.value), - nullifiers: self.nullifiers.storage.map(|n: ScopedNullifier| n.nullifier.value), - l2_to_l1_msgs: self.l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| { + note_hashes: self.note_hashes.storage().map(|n: ScopedNoteHash| n.note_hash.value), + nullifiers: self.nullifiers.storage().map(|n: ScopedNullifier| n.nullifier.value), + l2_to_l1_msgs: self.l2_to_l1_msgs.storage().map(|m: ScopedL2ToL1Message| { m.expose_to_public() }), - note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage.map( + note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage().map( |l: NoteLogHash| l.expose_to_public(), ), - encrypted_logs_hashes: self.encrypted_logs_hashes.storage.map( + encrypted_logs_hashes: self.encrypted_logs_hashes.storage().map( |l: ScopedEncryptedLogHash| l.expose_to_public(), ), - unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage.map(|l: ScopedLogHash| { + unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage().map(|l: ScopedLogHash| { l.expose_to_public() }), + contract_class_logs_hashes: self.contract_class_logs_hashes.storage.map( + |l: ScopedLogHash| l.expose_to_public(), + ), note_encrypted_log_preimages_length: self.note_encrypted_log_preimages_length, encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, - public_data_writes: self.public_data_writes.storage, - gas_used: self.gas_used, + contract_class_log_preimages_length: self.contract_class_log_preimages_length, + public_data_writes: self.public_data_writes.storage(), } } pub fn to_private_validation_requests(self) -> PrivateValidationRequests { PrivateValidationRequests { for_rollup: self.to_rollup_validation_requests(), - note_hash_read_requests: self.note_hash_read_requests.storage, - nullifier_read_requests: self.nullifier_read_requests.storage, + note_hash_read_requests: self.note_hash_read_requests.storage(), + nullifier_read_requests: self.nullifier_read_requests.storage(), scoped_key_validation_requests_and_generators: self .scoped_key_validation_requests_and_generators - .storage, + .storage(), split_counter: self.validation_requests_split_counter, } } @@ -577,6 +572,7 @@ impl FixtureBuilder { non_revertible_accumulated_data, revertible_accumulated_data, public_teardown_call_request: self.public_teardown_call_request, + gas_used: self.gas_used, fee_payer: self.fee_payer, } } @@ -584,11 +580,11 @@ impl FixtureBuilder { pub fn to_public_validation_requests(self) -> PublicValidationRequests { PublicValidationRequests { for_rollup: self.to_rollup_validation_requests(), - note_hash_read_requests: self.note_hash_tree_leaf_read_requests.storage, - nullifier_read_requests: self.nullifier_read_requests.storage, - nullifier_non_existent_read_requests: self.nullifier_non_existent_read_requests.storage, - public_data_reads: self.public_data_reads.storage, - l1_to_l2_msg_read_requests: self.l1_to_l2_msg_read_requests.storage, + note_hash_read_requests: self.note_hash_tree_leaf_read_requests.storage(), + nullifier_read_requests: self.nullifier_read_requests.storage(), + nullifier_non_existent_read_requests: self.nullifier_non_existent_read_requests.storage(), + public_data_reads: self.public_data_reads.storage(), + l1_to_l2_msg_read_requests: self.l1_to_l2_msg_read_requests.storage(), } } @@ -596,7 +592,7 @@ impl FixtureBuilder { VMCircuitPublicInputs { constants: self.to_constant_data(), call_request: self.to_public_call_request(), - public_call_stack: subarray(self.public_inner_call_requests.storage), + public_call_stack: subarray(self.public_inner_call_requests.storage()), previous_validation_request_array_lengths: PublicValidationRequestArrayLengths::empty(), validation_requests: self.to_public_validation_requests(), previous_accumulated_data_array_lengths: PublicAccumulatedDataArrayLengths::empty(), @@ -668,6 +664,7 @@ impl FixtureBuilder { constants, start_state: self.start_state, revert_code: self.revert_code, + gas_used: self.gas_used, fee_payer: self.fee_payer, } } @@ -1009,13 +1006,6 @@ impl FixtureBuilder { } } - pub fn mask_encrypted_log_hashes(&mut self) { - for i in 0..self.encrypted_logs_hashes.max_len() { - self.encrypted_logs_hashes.storage[i].contract_address = - mask_encrypted_log_hash(self.encrypted_logs_hashes.storage[i]); - } - } - pub fn add_unencrypted_log_hash(&mut self, hash: Field, length: Field) { let log_hash = LogHash { value: hash, counter: self.next_counter(), length }; self.unencrypted_logs_hashes.push(log_hash.scope(self.contract_address)); @@ -1033,9 +1023,10 @@ impl FixtureBuilder { } pub fn hash_unencrypted_log_hashes(&mut self) { - let mut log_hashes = self.unencrypted_logs_hashes.storage.map(|l: ScopedLogHash| l.inner()); + let mut log_hashes = + self.unencrypted_logs_hashes.storage().map(|l: ScopedLogHash| l.inner()); for i in 0..self.unencrypted_logs_hashes.max_len() { - let log_hash = self.unencrypted_logs_hashes.storage[i]; + let log_hash = self.unencrypted_logs_hashes.get_unchecked(i); if !log_hash.contract_address.is_zero() { log_hashes[i].value = silo_unencrypted_log_hash(log_hash); } @@ -1043,6 +1034,12 @@ impl FixtureBuilder { self.unencrypted_logs_hash = compute_tx_logs_hash(log_hashes); } + pub fn add_contract_class_log_hash(&mut self, hash: Field, length: Field) { + let log_hash = LogHash { value: hash, counter: self.next_counter(), length }; + self.contract_class_logs_hashes.push(log_hash.scope(self.contract_address)); + self.contract_class_log_preimages_length += length; + } + pub fn set_encrypted_logs_hash(&mut self, hash: Field, preimages_length: Field) { self.encrypted_logs_hash = hash; self.encrypted_log_preimages_length = preimages_length; @@ -1262,12 +1259,14 @@ impl Empty for FixtureBuilder { note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), + contract_class_logs_hashes: BoundedVec::new(), note_encrypted_logs_hash: 0, encrypted_logs_hash: 0, unencrypted_logs_hash: 0, note_encrypted_log_preimages_length: 0, encrypted_log_preimages_length: 0, unencrypted_log_preimages_length: 0, + contract_class_log_preimages_length: 0, public_data_writes: BoundedVec::new(), public_data_update_requests: BoundedVec::new(), private_call_requests: BoundedVec::new(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr index 6e361b74752..1cdb5a4bd76 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures.nr @@ -1,15 +1,13 @@ -mod contract_functions; -mod contracts; -mod protocol_contract_tree; -pub mod vk_tree; +pub(crate) mod contract_functions; +pub(crate) mod contracts; +pub(crate) mod protocol_contract_tree; +pub(crate) mod vk_tree; -use crate::{address::AztecAddress, point::Point}; +use crate::address::AztecAddress; -global MSG_SENDER = AztecAddress { inner: 27 }; +pub(crate) global MSG_SENDER = AztecAddress { inner: 27 }; -global PUBLIC_KEY = Point { x: 123456789, y: 123456789, is_infinite: false }; +pub(crate) global CHAIN_ID = 1; -global CHAIN_ID = 1; - -global VERSION = 3; +pub(crate) global VERSION = 3; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_functions.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_functions.nr index 9a08c162fcc..733d8cde55c 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_functions.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contract_functions.nr @@ -3,16 +3,16 @@ use crate::constants::{CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS, FUNCTION_TR use crate::merkle_tree::membership::MembershipWitness; pub struct ContractFunction { - data: FunctionData, - vk_hash: Field, - acir_hash: Field, - membership_witness: MembershipWitness, + pub data: FunctionData, + pub vk_hash: Field, + pub acir_hash: Field, + pub membership_witness: MembershipWitness, } -global default_vk = [0; CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS]; +pub global default_vk = [0; CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS]; // sibling_path taken from __snapshots__/noir_test_gen.test.ts.snap -global default_private_function = ContractFunction { +pub global default_private_function = ContractFunction { data: FunctionData { selector: FunctionSelector { inner: 1010101 }, is_private: true }, vk_hash: crate::hash::verification_key_hash(default_vk), acir_hash: 1111, @@ -28,7 +28,7 @@ global default_private_function = ContractFunction { }, }; -global default_public_function = ContractFunction { +pub global default_public_function = ContractFunction { data: FunctionData { selector: FunctionSelector { inner: 3030303 }, is_private: false }, vk_hash: 0, acir_hash: 3333, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr index 462bc8fc975..b1671efeb28 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixtures/contracts.nr @@ -1,5 +1,5 @@ use crate::{ - address::{AztecAddress, PartialAddress, PublicKeysHash, SaltedInitializationHash}, + address::{AztecAddress, PartialAddress, SaltedInitializationHash}, contract_class_id::ContractClassId, hash::private_functions_root_from_siblings, public_keys::PublicKeys, @@ -7,20 +7,20 @@ use crate::{ }; pub struct ContractData { - address: AztecAddress, - artifact_hash: Field, - contract_address_salt: Field, - contract_class_id: ContractClassId, - private_functions_root: Field, - public_bytecode_commitment: Field, - public_keys: PublicKeys, - salted_initialization_hash: SaltedInitializationHash, - partial_address: PartialAddress, - deployer: AztecAddress, + pub address: AztecAddress, + pub artifact_hash: Field, + pub contract_address_salt: Field, + pub contract_class_id: ContractClassId, + pub private_functions_root: Field, + pub public_bytecode_commitment: Field, + pub public_keys: PublicKeys, + pub salted_initialization_hash: SaltedInitializationHash, + pub partial_address: PartialAddress, + pub deployer: AztecAddress, } // taken from __snapshots__/noir_test_gen.test.ts.snap -global default_contract = ContractData { +pub global default_contract = ContractData { contract_address_salt: 0x000000000000000000000000000000000000000000000000000000000000ddd5, artifact_hash: 0x0000000000000000000000000000000000000000000000000000000000003039, public_bytecode_commitment: 0x0000000000000000000000000000000000000000000000000000000000000005, @@ -44,7 +44,7 @@ global default_contract = ContractData { }; // taken from __snapshots__/noir_test_gen.test.ts.snap -global parent_contract = ContractData { +pub global parent_contract = ContractData { contract_address_salt: 0x0000000000000000000000000000000000000000000000000000000000001618, artifact_hash: 0x00000000000000000000000000000000000000000000000000000000000004bc, public_bytecode_commitment: 0x0000000000000000000000000000000000000000000000000000000000000005, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/merkle_tree_utils.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/merkle_tree_utils.nr index b4ff548be02..52290e27603 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/merkle_tree_utils.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/merkle_tree_utils.nr @@ -15,7 +15,7 @@ pub fn compute_zero_hashes(mut hashes: [Field; N]) -> [Field; N] { } impl MerkleTree { - fn update_leaf(&mut self, index: u32, value: Field, _tree_height: [Field; K]) { + pub fn update_leaf(&mut self, index: u32, value: Field, _tree_height: [Field; K]) { self.leaves[index] = value; let mut sibling_index = merkle_tree::sibling_index(index); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/mod.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/mod.nr index 29d53f6506e..9a749fb7777 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/mod.nr @@ -1,5 +1,5 @@ -mod fixture_builder; +pub mod fixture_builder; pub mod fixtures; -mod merkle_tree_utils; -mod types; -mod utils; +pub mod merkle_tree_utils; +pub mod types; +pub mod utils; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/types.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/types.nr index 87afcbc0f8f..b14e43c7145 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/types.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/types.nr @@ -1,8 +1,8 @@ use crate::{abis::side_effect::Ordered, traits::Empty}; pub(crate) struct TestValue { - value: Field, - counter: u32, + pub(crate) value: Field, + pub(crate) counter: u32, } impl Empty for TestValue { @@ -24,9 +24,9 @@ impl Ordered for TestValue { } pub(crate) struct TestTwoValues { - value_1: Field, - value_2: Field, - counter: u32, + pub(crate) value_1: Field, + pub(crate) value_2: Field, + pub(crate) counter: u32, } impl Empty for TestTwoValues { @@ -50,7 +50,7 @@ impl Ordered for TestTwoValues { } pub(crate) struct TestCombinedValue { - value: Field, + pub(crate) value: Field, } impl Empty for TestCombinedValue { @@ -65,18 +65,18 @@ impl Eq for TestCombinedValue { } } -pub fn sum_two_values(from: TestTwoValues) -> TestValue { +pub(crate) fn sum_two_values(from: TestTwoValues) -> TestValue { TestValue { value: from.value_1 + from.value_2, counter: from.counter } } -pub fn is_summed_from_two_values(from: TestTwoValues, to: TestValue) -> bool { +pub(crate) fn is_summed_from_two_values(from: TestTwoValues, to: TestValue) -> bool { ((from.value_1 + from.value_2) == to.value) & (from.counter == to.counter) } -pub fn combine_two_values(from: TestTwoValues) -> TestCombinedValue { +pub(crate) fn combine_two_values(from: TestTwoValues) -> TestCombinedValue { TestCombinedValue { value: from.value_1 + from.value_2 } } -pub fn is_combined_from_two_values(from: TestTwoValues, to: TestCombinedValue) -> bool { +pub(crate) fn is_combined_from_two_values(from: TestTwoValues, to: TestCombinedValue) -> bool { ((from.value_1 + from.value_2) == to.value) } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/utils.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/utils.nr index 8403596ec80..e6289ba6a9a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/utils.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/utils.nr @@ -14,9 +14,9 @@ where // Swap two items in a BoundedVec. // Useful when we want to shuffle side effects, which by default are ordered by counters when we add mock data to FixtureBuilder. pub fn swap_items(vec: &mut BoundedVec, from_index: u32, to_index: u32) { - let tmp = vec.storage[from_index]; - vec.storage[from_index] = vec.storage[to_index]; - vec.storage[to_index] = tmp; + let tmp = vec.get(from_index); + vec.set(from_index, vec.get(to_index)); + vec.set(to_index, tmp); } pub fn pad_end(items: [T; N], emptyItem: T) -> [T; M] { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr index aad7f1db2ff..2d86849101f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_request.nr @@ -9,10 +9,10 @@ use crate::{ }; pub struct TxRequest { - origin: AztecAddress, - args_hash: Field, - tx_context: TxContext, - function_data: FunctionData, + pub origin: AztecAddress, + pub args_hash: Field, + pub tx_context: TxContext, + pub function_data: FunctionData, } impl Empty for TxRequest { @@ -93,7 +93,7 @@ mod tests { #[test] fn compute_hash() { - let gas_settings = GasSettings::new(Gas::new(2, 2), Gas::new(1, 1), GasFees::new(3, 3), 10); + let gas_settings = GasSettings::new(Gas::new(2, 2), Gas::new(1, 1), GasFees::new(3, 3)); let tx_request = TxRequest { origin: AztecAddress::from_field(1), args_hash: 3, @@ -105,7 +105,7 @@ mod tests { }; // Value from tx_request.test.ts "compute hash" test let test_data_tx_request_hash = - 0x289d3f85f463f3449e2204433b860574d351e9fbd97a01a722239fdd9ce3ce9b; + 0x1b15ac8432c3c35718075a277d86f11263f057e2325afa208d6b19e37ff59a8d; assert(tx_request.hash() == test_data_tx_request_hash); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr index 6e6f28f3307..fdd6a184b54 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr @@ -1,18 +1,18 @@ -mod assert_array_appended; -mod assert_array_prepended; -mod assert_combined_array; -mod assert_combined_sorted_transformed_value_array; -mod assert_combined_transformed_array; -mod assert_deduped_array; -mod assert_exposed_sorted_transformed_value_array; -mod assert_sorted_array; -mod assert_sorted_transformed_value_array; -mod assert_split_sorted_transformed_value_arrays; -mod assert_split_transformed_value_arrays; -mod get_sorted_result; -mod get_sorted_tuple; -mod sort_by; -mod sort_by_counter; +pub mod assert_array_appended; +pub mod assert_array_prepended; +pub mod assert_combined_array; +pub mod assert_combined_sorted_transformed_value_array; +pub mod assert_combined_transformed_array; +pub mod assert_deduped_array; +pub mod assert_exposed_sorted_transformed_value_array; +pub mod assert_sorted_array; +pub mod assert_sorted_transformed_value_array; +pub mod assert_split_sorted_transformed_value_arrays; +pub mod assert_split_transformed_value_arrays; +pub mod get_sorted_result; +pub mod get_sorted_tuple; +pub mod sort_by; +pub mod sort_by_counter; // Re-exports. pub use assert_array_appended::{ diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array.nr index cac15101a86..4b4e7bd7499 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array.nr @@ -1,4 +1,4 @@ -mod get_combined_order_hints; +pub mod get_combined_order_hints; use crate::{ abis::side_effect::Ordered, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array/get_combined_order_hints.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array/get_combined_order_hints.nr index ac62b93bd14..9a16ea9896f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array/get_combined_order_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_combined_sorted_transformed_value_array/get_combined_order_hints.nr @@ -8,8 +8,8 @@ use crate::{ }; pub struct CombinedOrderHint { - counter: u32, - original_index: u32, + pub counter: u32, + pub original_index: u32, } impl CombinedOrderHint { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_deduped_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_deduped_array.nr index af7e9c4bdac..6912c7c0868 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_deduped_array.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_deduped_array.nr @@ -34,7 +34,7 @@ where deduped.push(original.inner()); } } - deduped.storage + deduped.storage() } mod tests { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array.nr index eba9fe575a2..e745c86f6c7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array.nr @@ -1,4 +1,4 @@ -mod get_order_hints; +pub mod get_order_hints; use crate::{ abis::side_effect::Ordered, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array/get_order_hints.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array/get_order_hints.nr index 145df154174..25071de486d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array/get_order_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_exposed_sorted_transformed_value_array/get_order_hints.nr @@ -10,8 +10,8 @@ use crate::{ }; pub struct OrderHint { - counter: u32, - sorted_index: u32, + pub counter: u32, + pub sorted_index: u32, } impl OrderHint { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr index 36cc3b3d07c..c9daa70eddf 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr @@ -1,4 +1,4 @@ -mod get_split_order_hints; +pub mod get_split_order_hints; use crate::{ abis::side_effect::Ordered, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays/get_split_order_hints.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays/get_split_order_hints.nr index 2a330cc2fe2..bf683c3cd97 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays/get_split_order_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays/get_split_order_hints.nr @@ -10,9 +10,9 @@ use crate::{ }; pub struct SplitOrderHints { - sorted_counters_lt: [u32; N], - sorted_counters_gte: [u32; N], - sorted_indexes: [u32; N], + pub sorted_counters_lt: [u32; N], + pub sorted_counters_gte: [u32; N], + pub sorted_indexes: [u32; N], } impl SplitOrderHints { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/get_sorted_tuple.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/get_sorted_tuple.nr index d638e5cf279..569983a9344 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/get_sorted_tuple.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/get_sorted_tuple.nr @@ -1,8 +1,8 @@ use crate::utils::arrays::sort_by::sort_by; pub struct SortedTuple { - elem: T, - original_index: u32, + pub elem: T, + pub original_index: u32, } pub unconstrained fn get_sorted_tuple( diff --git a/noir/noir-repo/.release-please-manifest.json b/noir/noir-repo/.release-please-manifest.json index 69d91ea64a2..138ef24bf73 100644 --- a/noir/noir-repo/.release-please-manifest.json +++ b/noir/noir-repo/.release-please-manifest.json @@ -1,4 +1,4 @@ { - ".": "0.37.0", - "acvm-repo": "0.53.0" + ".": "0.38.0", + "acvm-repo": "0.54.0" } diff --git a/noir/noir-repo/CHANGELOG.md b/noir/noir-repo/CHANGELOG.md index f2c9a76442b..076a36fc96b 100644 --- a/noir/noir-repo/CHANGELOG.md +++ b/noir/noir-repo/CHANGELOG.md @@ -1,5 +1,33 @@ # Changelog +## [0.38.0](https://github.com/noir-lang/noir/compare/v0.37.0...v0.38.0) (2024-11-08) + + +### ⚠ BREAKING CHANGES + +* Always Check Arithmetic Generics at Monomorphization ([#6329](https://github.com/noir-lang/noir/issues/6329)) + +### Features + +* Always Check Arithmetic Generics at Monomorphization ([#6329](https://github.com/noir-lang/noir/issues/6329)) ([2972db2](https://github.com/noir-lang/noir/commit/2972db20fc00ed0e43b662092f0d0712421d122f)) +* Ensure that generated ACIR is solvable ([#6415](https://github.com/noir-lang/noir/issues/6415)) ([b473d99](https://github.com/noir-lang/noir/commit/b473d99b2b70b595596b8392617256dbaf5d5642)) +* Nargo command to generate shell completions ([#6413](https://github.com/noir-lang/noir/issues/6413)) ([13856a1](https://github.com/noir-lang/noir/commit/13856a121125b1ccca15919942081a5d157d280e)) + + +### Bug Fixes + +* Check infix expression is valid in program input ([#6450](https://github.com/noir-lang/noir/issues/6450)) ([35dedb5](https://github.com/noir-lang/noir/commit/35dedb54a0853ba0fa85038d832a520f9ba01a98)) +* Discard optimisation that would change execution ordering or that is related to call outputs ([#6461](https://github.com/noir-lang/noir/issues/6461)) ([b8654f7](https://github.com/noir-lang/noir/commit/b8654f700b218cc09c5381af65df11ead9ffcdaf)) +* Don't crash on AsTraitPath with empty path ([#6454](https://github.com/noir-lang/noir/issues/6454)) ([fc72dcd](https://github.com/noir-lang/noir/commit/fc72dcdf3e8eeff73f72756e7ab87dddf2920657)) +* Fix Alias and Error kinds ([#6426](https://github.com/noir-lang/noir/issues/6426)) ([3cb259f](https://github.com/noir-lang/noir/commit/3cb259f419cf352f768728b15f849e520fc233cb)) +* Let formatter respect newlines between comments ([#6458](https://github.com/noir-lang/noir/issues/6458)) ([fb1a8ca](https://github.com/noir-lang/noir/commit/fb1a8ca67c58d87991358078e6c532b49824fdb8)) +* Right shift is not a regular division ([#6400](https://github.com/noir-lang/noir/issues/6400)) ([2247814](https://github.com/noir-lang/noir/commit/2247814f951f5d33257cd123a3bdcba857c9b167)) +* **sea:** Mem2reg to treat block input references as alias ([#6452](https://github.com/noir-lang/noir/issues/6452)) ([5310064](https://github.com/noir-lang/noir/commit/53100647bf1dc7917b66c9a7041c06b1e716fbe7)) +* **ssa:** Change array_set to not mutate slices coming from function inputs ([#6463](https://github.com/noir-lang/noir/issues/6463)) ([371bd45](https://github.com/noir-lang/noir/commit/371bd45130c9095e5dfb20dc79fbf41c02ed087c)) +* **ssa:** Resolve value IDs in terminator before comparing to array ([#6448](https://github.com/noir-lang/noir/issues/6448)) ([66f15ca](https://github.com/noir-lang/noir/commit/66f15caba8466501256a98cee289c49376b27097)) +* **tests:** Prevent EOF error while running test programs ([#6455](https://github.com/noir-lang/noir/issues/6455)) ([358e381](https://github.com/noir-lang/noir/commit/358e38107edbc4f40c97b88196456d82f5557e3f)) +* Type-check turbofish in trait before function call ([#6416](https://github.com/noir-lang/noir/issues/6416)) ([f8fd813](https://github.com/noir-lang/noir/commit/f8fd813b09ce870364700659e3ea8499ab51105e)) + ## [0.37.0](https://github.com/noir-lang/noir/compare/v0.36.0...v0.37.0) (2024-10-31) diff --git a/noir/noir-repo/Cargo.lock b/noir/noir-repo/Cargo.lock index 3659a264737..35ff97f55e3 100644 --- a/noir/noir-repo/Cargo.lock +++ b/noir/noir-repo/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "acir" -version = "0.53.0" +version = "0.54.0" dependencies = [ "acir_field", "base64 0.21.7", @@ -26,7 +26,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.53.0" +version = "0.54.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -40,7 +40,7 @@ dependencies = [ [[package]] name = "acvm" -version = "0.53.0" +version = "0.54.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -59,7 +59,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "0.53.0" +version = "0.54.0" dependencies = [ "acir", "blake2", @@ -89,14 +89,14 @@ dependencies = [ "proptest", "rand 0.8.5", "thiserror", - "toml 0.7.6", + "toml 0.7.8", "tracing-appender", "tracing-subscriber", ] [[package]] name = "acvm_js" -version = "0.53.0" +version = "0.54.0" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -117,9 +117,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -130,6 +130,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" version = "0.8.11" @@ -145,9 +151,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -175,9 +181,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -190,26 +196,26 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -224,9 +230,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "ark-bls12-381" @@ -359,26 +365,27 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "assert_cmd" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6" +checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d" dependencies = [ "anstyle", - "bstr 1.6.0", + "bstr", "doc-comment", - "predicates 3.0.3", + "libc", + "predicates 3.1.2", "predicates-core", "predicates-tree", "wait-timeout", @@ -386,14 +393,14 @@ dependencies = [ [[package]] name = "assert_fs" -version = "1.0.13" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f070617a68e5c2ed5d06ee8dd620ee18fb72b99f6c094bed34cf8ab07c875b48" +checksum = "7efdb1fdb47602827a342857666feb372712cbc64b414172bd6b167a02927674" dependencies = [ "anstyle", "doc-comment", "globwalk", - "predicates 3.0.3", + "predicates 3.1.2", "predicates-core", "predicates-tree", "tempfile", @@ -405,7 +412,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138985dd8aefbefeaa66b01b7f5b2b6b4c333fcef1cc5f32c63a2aabe37d6de3" dependencies = [ - "futures 0.3.30", + "futures 0.3.31", "lsp-types 0.94.1", "pin-project-lite", "rustix", @@ -421,21 +428,21 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", ] @@ -458,6 +465,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "base64ct" version = "1.6.0" @@ -496,9 +509,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitmaps" @@ -543,9 +556,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.5.0" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" dependencies = [ "arrayref", "arrayvec", @@ -578,7 +591,7 @@ dependencies = [ [[package]] name = "bn254_blackbox_solver" -version = "0.53.0" +version = "0.54.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -596,7 +609,7 @@ dependencies = [ [[package]] name = "brillig" -version = "0.53.0" +version = "0.54.0" dependencies = [ "acir_field", "serde", @@ -604,7 +617,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "0.53.0" +version = "0.54.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -615,31 +628,20 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata 0.1.10", -] - -[[package]] -name = "bstr" -version = "1.6.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", - "regex-automata 0.3.9", + "regex-automata 0.4.8", "serde", ] [[package]] name = "build-data" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac83c47416b2db78a5a8a45d7d229a730b62806fa41ac6b4dbde6d016798776" +checksum = "aed3884e2cab7c973c8fd2d150314b6a932df7fdc830edcaf1e8e7c4ae9db3c0" dependencies = [ "chrono", "safe-lock", @@ -648,42 +650,42 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.13.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "camino" -version = "1.1.6" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.3" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ "serde", ] @@ -710,11 +712,11 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.83" +version = "1.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" dependencies = [ - "libc", + "shlex", ] [[package]] @@ -746,9 +748,9 @@ dependencies = [ [[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -757,15 +759,15 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", "half", @@ -798,14 +800,14 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", + "strsim", ] [[package]] name = "clap_complete" -version = "4.5.36" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86bc73de94bc81e52f3bebec71bc4463e9748f7a59166663e32044669577b0e2" +checksum = "11611dca53440593f38e6b25ec629de50b14cdfa63adc0fb856115a2c6d97595" dependencies = [ "clap", ] @@ -819,7 +821,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] @@ -857,7 +859,7 @@ checksum = "fc4159b76af02757139baf42c0c971c6dc155330999fbfd8eddb29b97fb2db68" dependencies = [ "codespan-reporting", "lsp-types 0.88.0", - "url 2.5.0", + "url 2.5.3", ] [[package]] @@ -873,9 +875,9 @@ dependencies = [ [[package]] name = "color-eyre" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" dependencies = [ "backtrace", "color-spantrace", @@ -888,9 +890,9 @@ dependencies = [ [[package]] name = "color-spantrace" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" dependencies = [ "once_cell", "owo-colors", @@ -900,9 +902,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "comma" @@ -934,30 +936,30 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.4" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "const-str" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aca749d3d3f5b87a0d6100509879f9cf486ab510803a4a4e1001da1ff61c2bd6" +checksum = "3618cccc083bb987a415d85c02ca6c9994ea5b44731ec28b9ecf09658655fba9" [[package]] name = "const_format" -version = "0.2.31" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c990efc7a285731f9a4378d81aff2f0e85a2c8781a05ef0f8baa8dac54d0ff48" +checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.31" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e026b6ce194a874cb9cf32cd5772d1ef9767cc8fcb5765948d74f37a9d8b2bf6" +checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" dependencies = [ "proc-macro2", "quote", @@ -966,9 +968,9 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "convert_case" @@ -987,33 +989,33 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpp_demangle" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee34052ee3d93d6d8f3e6f81d85c47921f6653a19a7b70e939e3e602d893a674" +checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if 1.0.0", ] @@ -1056,43 +1058,43 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.9" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c3242926edf34aec4ac3a77108ad4854bffaa2e4ddc1824124ce59231302d5" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "cfg-if 1.0.0", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if 1.0.0", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if 1.0.0", "crossbeam-utils", - "memoffset 0.9.1", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" @@ -1118,9 +1120,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.2.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" dependencies = [ "csv-core", "itoa", @@ -1130,9 +1132,9 @@ dependencies = [ [[package]] name = "csv-core" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" dependencies = [ "memchr", ] @@ -1150,9 +1152,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.3" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", @@ -1160,40 +1162,41 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 2.0.64", + "strsim", + "syn 2.0.87", ] [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "dashmap" -version = "5.5.3" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ "cfg-if 1.0.0", + "crossbeam-utils", "hashbrown 0.14.5", "lock_api", "once_cell", - "parking_lot_core 0.9.8", + "parking_lot_core 0.9.10", ] [[package]] @@ -1217,10 +1220,11 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.7" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ + "powerfmt", "serde", ] @@ -1237,15 +1241,15 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case 0.4.0", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.87", ] [[package]] @@ -1306,6 +1310,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "doc-comment" version = "0.3.3" @@ -1341,9 +1356,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elliptic-curve" @@ -1383,12 +1398,22 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", +] + [[package]] name = "env_logger" -version = "0.10.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" dependencies = [ + "env_filter", "log", ] @@ -1420,9 +1445,9 @@ dependencies = [ [[package]] name = "eyre" -version = "0.6.8" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", @@ -1430,9 +1455,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "fd-lock" @@ -1478,23 +1503,23 @@ dependencies = [ [[package]] name = "file-id" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6584280525fb2059cba3db2c04abf947a1a29a45ddae89f3870f8281704fafc9" +checksum = "6bc904b9bbefcadbd8e3a9fb0d464a9b979de6324c03b3c663e8994f46a5be36" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.3.5", - "windows-sys 0.48.0", + "libredox 0.1.3", + "windows-sys 0.59.0", ] [[package]] @@ -1517,12 +1542,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1536,7 +1561,7 @@ dependencies = [ [[package]] name = "fm" -version = "0.37.0" +version = "0.38.0" dependencies = [ "codespan-reporting", "iter-extended", @@ -1581,9 +1606,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1596,9 +1621,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1606,15 +1631,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1624,38 +1649,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures 0.1.31", "futures-channel", @@ -1715,9 +1740,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" @@ -1727,24 +1752,24 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.11" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" dependencies = [ "aho-corasick", - "bstr 1.6.0", - "fnv", + "bstr", "log", - "regex", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] name = "globwalk" -version = "0.8.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "ignore", "walkdir", ] @@ -1787,9 +1812,13 @@ dependencies = [ [[package]] name = "half" -version = "1.8.2" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if 1.0.0", + "crunchy", +] [[package]] name = "halo2" @@ -1835,6 +1864,12 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "hashbrown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" + [[package]] name = "heck" version = "0.3.3" @@ -1858,9 +1893,15 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "hex" @@ -1879,9 +1920,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -1890,9 +1931,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -1901,21 +1942,21 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", @@ -1942,9 +1983,9 @@ checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678" [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1963,6 +2004,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1982,27 +2141,37 @@ dependencies = [ [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] name = "ignore" -version = "0.4.20" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" dependencies = [ + "crossbeam-deque", "globset", - "lazy_static", "log", "memchr", - "regex", + "regex-automata 0.4.8", "same-file", - "thread_local", "walkdir", "winapi-util", ] @@ -2065,20 +2234,20 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.1", "serde", ] [[package]] name = "inferno" -version = "0.11.19" +version = "0.11.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" +checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" dependencies = [ "ahash", "clap", @@ -2086,7 +2255,7 @@ dependencies = [ "crossbeam-utils", "dashmap", "env_logger", - "indexmap 2.2.6", + "indexmap 2.6.0", "is-terminal", "itoa", "log", @@ -2119,22 +2288,22 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi", - "rustix", - "windows-sys 0.48.0", + "hermit-abi 0.4.0", + "libc", + "windows-sys 0.52.0", ] [[package]] @@ -2145,7 +2314,7 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "iter-extended" -version = "0.37.0" +version = "0.38.0" [[package]] name = "itertools" @@ -2158,9 +2327,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" @@ -2190,7 +2359,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" dependencies = [ "derive_more", - "futures 0.3.30", + "futures 0.3.31", "jsonrpc-core", "jsonrpc-pubsub", "log", @@ -2205,7 +2374,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" dependencies = [ - "futures 0.3.30", + "futures 0.3.31", "futures-executor", "futures-util", "log", @@ -2220,7 +2389,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" dependencies = [ - "futures 0.3.30", + "futures 0.3.31", "jsonrpc-client-transports", ] @@ -2242,7 +2411,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ - "futures 0.3.30", + "futures 0.3.31", "hyper", "jsonrpc-core", "jsonrpc-server-utils", @@ -2258,7 +2427,7 @@ version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" dependencies = [ - "futures 0.3.30", + "futures 0.3.31", "jsonrpc-core", "lazy_static", "log", @@ -2274,7 +2443,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" dependencies = [ "bytes", - "futures 0.3.30", + "futures 0.3.31", "globset", "jsonrpc-core", "lazy_static", @@ -2313,9 +2482,9 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] @@ -2342,9 +2511,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ "spin", ] @@ -2357,15 +2526,15 @@ checksum = "82903360c009b816f5ab72a9b68158c27c301ee2c3f20655b55c5e589e7d3bb7" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libm" -version = "0.2.7" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" @@ -2373,11 +2542,22 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", "redox_syscall 0.4.1", ] +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall 0.5.7", +] + [[package]] name = "light-poseidon" version = "0.2.0" @@ -2396,11 +2576,17 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -2408,9 +2594,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "louds-rs" @@ -2431,7 +2617,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", - "url 2.5.0", + "url 2.5.3", ] [[package]] @@ -2444,7 +2630,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", - "url 2.5.0", + "url 2.5.3", ] [[package]] @@ -2464,15 +2650,15 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" -version = "0.5.10" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" dependencies = [ "libc", ] @@ -2486,15 +2672,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "memuse" version = "0.2.1" @@ -2510,11 +2687,20 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "minreq" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3371dfc7b772c540da1380123674a8e20583aca99907087d990ca58cf44203" +checksum = "763d142cdff44aaadd9268bebddb156ef6c65a0e13486bb81673cf2d8739f9b0" dependencies = [ "log", "serde", @@ -2533,9 +2719,21 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + [[package]] name = "nargo" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "fm", @@ -2562,7 +2760,7 @@ dependencies = [ [[package]] name = "nargo_cli" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "ark-bn254", @@ -2582,6 +2780,7 @@ dependencies = [ "fm", "iai", "iter-extended", + "lazy_static", "light-poseidon", "nargo", "nargo_fmt", @@ -2613,8 +2812,8 @@ dependencies = [ "test-case", "thiserror", "tokio", - "tokio-util 0.7.10", - "toml 0.7.6", + "tokio-util 0.7.12", + "toml 0.7.8", "tower", "tracing-appender", "tracing-subscriber", @@ -2622,18 +2821,18 @@ dependencies = [ [[package]] name = "nargo_fmt" -version = "0.37.0" +version = "0.38.0" dependencies = [ "noirc_frontend", "serde", "similar-asserts", "thiserror", - "toml 0.7.6", + "toml 0.7.8", ] [[package]] name = "nargo_toml" -version = "0.37.0" +version = "0.38.0" dependencies = [ "dirs", "fm", @@ -2643,8 +2842,8 @@ dependencies = [ "semver", "serde", "thiserror", - "toml 0.7.6", - "url 2.5.0", + "toml 0.7.8", + "url 2.5.3", ] [[package]] @@ -2677,7 +2876,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "libc", - "memoffset 0.6.5", + "memoffset", ] [[package]] @@ -2690,7 +2889,7 @@ dependencies = [ "bitflags 1.3.2", "cfg-if 1.0.0", "libc", - "memoffset 0.6.5", + "memoffset", "pin-utils", ] @@ -2707,7 +2906,7 @@ dependencies = [ [[package]] name = "noir_debugger" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "assert_cmd", @@ -2731,7 +2930,7 @@ dependencies = [ [[package]] name = "noir_fuzzer" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "noirc_abi", @@ -2754,7 +2953,7 @@ dependencies = [ [[package]] name = "noir_lsp" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "async-lsp", @@ -2781,7 +2980,7 @@ dependencies = [ [[package]] name = "noir_profiler" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acir", "bn254_blackbox_solver", @@ -2807,7 +3006,7 @@ dependencies = [ [[package]] name = "noir_wasm" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "build-data", @@ -2831,7 +3030,7 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "iter-extended", @@ -2839,18 +3038,18 @@ dependencies = [ "num-bigint", "num-traits", "proptest", - "proptest-derive", + "proptest-derive 0.4.0", "serde", "serde_json", "strum", "strum_macros", "thiserror", - "toml 0.7.6", + "toml 0.7.8", ] [[package]] name = "noirc_abi_wasm" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "build-data", @@ -2867,11 +3066,11 @@ dependencies = [ [[package]] name = "noirc_arena" -version = "0.37.0" +version = "0.38.0" [[package]] name = "noirc_artifacts" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "codespan-reporting", @@ -2886,7 +3085,7 @@ dependencies = [ [[package]] name = "noirc_driver" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "build-data", @@ -2905,7 +3104,7 @@ dependencies = [ [[package]] name = "noirc_errors" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "base64 0.21.7", @@ -2922,7 +3121,7 @@ dependencies = [ [[package]] name = "noirc_evaluator" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -2934,18 +3133,20 @@ dependencies = [ "noirc_errors", "noirc_frontend", "num-bigint", + "num-traits", "proptest", "rayon", "serde", "serde_json", "serde_with", + "similar-asserts", "thiserror", "tracing", ] [[package]] name = "noirc_frontend" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "base64 0.21.7", @@ -2960,6 +3161,8 @@ dependencies = [ "num-bigint", "num-traits", "petgraph", + "proptest", + "proptest-derive 0.5.0", "rangemap", "regex", "rustc-hash", @@ -2975,7 +3178,7 @@ dependencies = [ [[package]] name = "noirc_printable_type" -version = "0.37.0" +version = "0.38.0" dependencies = [ "acvm", "iter-extended", @@ -2998,7 +3201,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "crossbeam-channel", "filetime", "fsevent-sys", @@ -3006,22 +3209,22 @@ dependencies = [ "kqueue", "libc", "log", - "mio", + "mio 0.8.11", "walkdir", "windows-sys 0.48.0", ] [[package]] name = "notify-debouncer-full" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f5dab59c348b9b50cf7f261960a20e389feb2713636399cd9082cd4b536154" +checksum = "fb7fd166739789c9ff169e654dc1501373db9d80a4c3f972817c8a4d7cf8f34e" dependencies = [ "crossbeam-channel", "file-id", "log", "notify", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "walkdir", ] @@ -3045,6 +3248,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-format" version = "0.4.4" @@ -3080,7 +3289,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] @@ -3092,24 +3301,24 @@ checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" [[package]] name = "object" -version = "0.31.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "overload" @@ -3156,12 +3365,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", + "parking_lot_core 0.9.10", ] [[package]] @@ -3180,15 +3389,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.5.7", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -3223,9 +3432,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "percent-encoding" @@ -3241,12 +3450,12 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.2.6", + "indexmap 2.6.0", ] [[package]] @@ -3295,9 +3504,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -3317,15 +3526,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" dependencies = [ "num-traits", "plotters-backend", @@ -3336,19 +3545,25 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "pprof" version = "0.12.1" @@ -3364,7 +3579,7 @@ dependencies = [ "log", "nix 0.26.4", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "smallvec", "symbolic-demangle", "tempfile", @@ -3386,7 +3601,7 @@ dependencies = [ "log", "nix 0.26.4", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "smallvec", "symbolic-demangle", "tempfile", @@ -3395,9 +3610,12 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "predicates" @@ -3415,27 +3633,26 @@ dependencies = [ [[package]] name = "predicates" -version = "3.0.3" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9" +checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" dependencies = [ "anstyle", "difflib", - "itertools", "predicates-core", ] [[package]] name = "predicates-core" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" +checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" [[package]] name = "predicates-tree" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" dependencies = [ "predicates-core", "termtree", @@ -3472,28 +3689,28 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.5.0", + "bitflags 2.6.0", "lazy_static", "num-traits", "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.8.2", + "regex-syntax 0.8.5", "rusty-fork", "tempfile", "unarray", @@ -3510,6 +3727,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "proptest-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff7ff745a347b87471d859a377a9a404361e7efc2a971d73424a6d183c0fc77" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -3527,9 +3755,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -3641,9 +3869,9 @@ dependencies = [ [[package]] name = "rangemap" -version = "1.4.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "977b1e897f9d764566891689e642653e5ed90c6895106acd005eb4c1d0203991" +checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684" [[package]] name = "rayon" @@ -3676,20 +3904,20 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] @@ -3700,25 +3928,25 @@ checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb" [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom 0.2.15", - "redox_syscall 0.2.16", + "libredox 0.1.3", "thiserror", ] [[package]] name = "regex" -version = "1.10.3" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.2", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -3732,19 +3960,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" - -[[package]] -name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.5", ] [[package]] @@ -3755,9 +3977,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rexpect" @@ -3785,9 +4007,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.36" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" dependencies = [ "bytemuck", ] @@ -3812,7 +4034,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.64", + "syn 2.0.87", "walkdir", ] @@ -3828,9 +4050,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -3840,20 +4062,20 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -3862,9 +4084,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "rusty-fork" @@ -3914,23 +4136,23 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safe-lock" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "077d73db7973cccf63eb4aff1e5a34dc2459baa867512088269ea5f2f4253c90" +checksum = "f29841ed0a577196bca5b753cd4e4022fa50b718e56fc0d35919ed32e20ec65c" [[package]] name = "safe-proc-macro2" -version = "1.0.36" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "814c536dcd27acf03296c618dab7ad62d28e70abd7ba41d3f34a2ce707a2c666" +checksum = "7fd85be67db87168aa3c13fd0da99f48f2ab005dccad5af5626138dc1df20eb6" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -3944,18 +4166,18 @@ dependencies = [ [[package]] name = "safe-regex" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15289bf322e0673d52756a18194167f2378ec1a15fe884af6e2d2cb934822b0" +checksum = "e6ab4bc484ef480a9ce79b381efd7b6767700f514d47bc599036e9d6f7f3c49d" dependencies = [ "safe-regex-macro", ] [[package]] name = "safe-regex-compiler" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba76fae590a2aa665279deb1f57b5098cbace01a0c5e60e262fcf55f7c51542" +checksum = "6d71f8c78bffb07962595e1bfa5ed11d24dd855eedc50b6a735f5ef648ce621b" dependencies = [ "safe-proc-macro2", "safe-quote", @@ -3963,9 +4185,9 @@ dependencies = [ [[package]] name = "safe-regex-macro" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c2e96b5c03f158d1b16ba79af515137795f4ad4e8de3f790518aae91f1d127" +checksum = "0909ab4b77511df24201cd66541d6a028887c77ecc065f277c68a12a663274ef" dependencies = [ "safe-proc-macro2", "safe-regex-compiler", @@ -4008,18 +4230,18 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.209" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] @@ -4060,58 +4282,60 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_repr" -version = "0.1.14" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d89a8107374290037607734c0b73a85db7ed80cae314b3c5791f192a496e731" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] [[package]] name = "serde_with" -version = "3.2.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1402f54f9a3b9e2efe71c1cea24e648acce55887983553eeb858cf3115acfd49" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.6", + "indexmap 2.6.0", "serde", + "serde_derive", "serde_json", "serde_with_macros", "time", @@ -4119,21 +4343,21 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.2.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9197f1ad0e3c173a0222d3c4404fb04c3afe87e962bcb327af73e8301fa203c7" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -4152,9 +4376,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -4165,6 +4389,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signature" version = "1.6.4" @@ -4177,19 +4407,19 @@ dependencies = [ [[package]] name = "similar" -version = "2.3.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" dependencies = [ - "bstr 0.2.17", + "bstr", "unicode-segmentation", ] [[package]] name = "similar-asserts" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e041bb827d1bfca18f213411d51b665309f1afb37a04a5d1464530e13779fc0f" +checksum = "cfe85670573cd6f0fa97940f26e7e6601213c3b0555246c24234131f88c5709e" dependencies = [ "console", "similar", @@ -4213,9 +4443,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] @@ -4252,19 +4482,19 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "spin" -version = "0.5.2" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spki" @@ -4300,12 +4530,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strsim" version = "0.11.1" @@ -4333,15 +4557,15 @@ dependencies = [ [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "symbolic-common" -version = "12.3.0" +version = "12.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167a4ffd7c35c143fd1030aa3c2caf76ba42220bd5a6b5f4781896434723b8c3" +checksum = "3d4d73159efebfb389d819fd479afb2dbd57dcb3e3f4b7fcfa0e675f5a46c1cb" dependencies = [ "debugid", "memmap2", @@ -4351,9 +4575,9 @@ dependencies = [ [[package]] name = "symbolic-demangle" -version = "12.3.0" +version = "12.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e378c50e80686c1c5c205674e1f86a2858bec3d2a7dfdd690331a8a19330f293" +checksum = "a767859f6549c665011970874c3f541838b4835d5aaaa493d3ee383918be9f10" dependencies = [ "cpp_demangle", "rustc-demangle", @@ -4373,15 +4597,26 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.64" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "tap" version = "1.0.1" @@ -4390,15 +4625,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.8.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if 1.0.0", "fastrand", - "redox_syscall 0.3.5", + "once_cell", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -4414,9 +4649,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -4428,7 +4663,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "417813675a504dfbbf21bfde32c03e5bf9f2413999962b479023c02848c1c7a5" dependencies = [ "libc", - "libredox", + "libredox 0.0.2", "numtoa", "redox_termios", ] @@ -4470,7 +4705,7 @@ dependencies = [ "cfg-if 1.0.0", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] @@ -4481,7 +4716,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", "test-case-core", ] @@ -4508,29 +4743,29 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.43" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.43" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if 1.0.0", "once_cell", @@ -4538,12 +4773,14 @@ dependencies = [ [[package]] name = "time" -version = "0.3.25" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "num-conv", + "powerfmt", "serde", "time-core", "time-macros", @@ -4551,19 +4788,30 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.11" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -4576,9 +4824,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -4591,37 +4839,36 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.1" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", "libc", - "mio", - "num_cpus", + "mio 1.0.2", "pin-project-lite", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -4644,9 +4891,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -4667,9 +4914,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", "serde_spanned", @@ -4679,20 +4926,20 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.14" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -4712,15 +4959,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -4754,7 +5001,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", ] [[package]] @@ -4830,15 +5077,15 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unarray" @@ -4848,24 +5095,21 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-linebreak" @@ -4875,30 +5119,30 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "url" @@ -4913,27 +5157,39 @@ dependencies = [ [[package]] name = "url" -version = "2.5.0" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna 1.0.3", "percent-encoding 2.3.1", "serde", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.4.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" [[package]] name = "valuable" @@ -4943,9 +5199,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wait-timeout" @@ -4958,12 +5214,12 @@ dependencies = [ [[package]] name = "waitpid-any" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54f8c3c56044fc359f905b72879576a15d49c46d085ed6266a98826716f14033" +checksum = "0189157c93c54d86e5c61ddf0c1223baa25e5bfb2f6f9983c678985b028d7c12" dependencies = [ "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -5020,7 +5276,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -5054,7 +5310,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5117,11 +5373,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -5132,11 +5388,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.50.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af6041b3f84485c21b57acdc0fee4f4f0c93f426053dc05fa5d6fc262537bbff" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -5289,13 +5545,25 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.5.0" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "wyz" version = "0.5.1" @@ -5305,31 +5573,77 @@ dependencies = [ "tap", ] +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure", +] + [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure", ] [[package]] name = "zeroize" -version = "1.6.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -5342,7 +5656,29 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.64", + "syn 2.0.87", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", ] [[package]] diff --git a/noir/noir-repo/Cargo.toml b/noir/noir-repo/Cargo.toml index d819c37daeb..214ed9a5bcb 100644 --- a/noir/noir-repo/Cargo.toml +++ b/noir/noir-repo/Cargo.toml @@ -40,7 +40,7 @@ resolver = "2" [workspace.package] # x-release-please-start-version -version = "0.37.0" +version = "0.38.0" # x-release-please-end authors = ["The Noir Team "] edition = "2021" @@ -57,13 +57,13 @@ unused_qualifications = "warn" [workspace.dependencies] # ACVM workspace dependencies -acir_field = { version = "0.53.0", path = "acvm-repo/acir_field", default-features = false } -acir = { version = "0.53.0", path = "acvm-repo/acir", default-features = false } -acvm = { version = "0.53.0", path = "acvm-repo/acvm" } -brillig = { version = "0.53.0", path = "acvm-repo/brillig", default-features = false } -brillig_vm = { version = "0.53.0", path = "acvm-repo/brillig_vm", default-features = false } -acvm_blackbox_solver = { version = "0.53.0", path = "acvm-repo/blackbox_solver", default-features = false } -bn254_blackbox_solver = { version = "0.53.0", path = "acvm-repo/bn254_blackbox_solver", default-features = false } +acir_field = { version = "0.54.0", path = "acvm-repo/acir_field", default-features = false } +acir = { version = "0.54.0", path = "acvm-repo/acir", default-features = false } +acvm = { version = "0.54.0", path = "acvm-repo/acvm" } +brillig = { version = "0.54.0", path = "acvm-repo/brillig", default-features = false } +brillig_vm = { version = "0.54.0", path = "acvm-repo/brillig_vm", default-features = false } +acvm_blackbox_solver = { version = "0.54.0", path = "acvm-repo/blackbox_solver", default-features = false } +bn254_blackbox_solver = { version = "0.54.0", path = "acvm-repo/bn254_blackbox_solver", default-features = false } # Noir compiler workspace dependencies fm = { path = "compiler/fm" } @@ -142,6 +142,7 @@ build-data = "0.1.3" bincode = "1.3.3" hex = "0.4.2" const_format = "0.2.30" +lazy_static = "1.4" num-bigint = "0.4" num-traits = "0.2" similar-asserts = "1.5.0" diff --git a/noir/noir-repo/acvm-repo/CHANGELOG.md b/noir/noir-repo/acvm-repo/CHANGELOG.md index aa25221a477..919653c0eba 100644 --- a/noir/noir-repo/acvm-repo/CHANGELOG.md +++ b/noir/noir-repo/acvm-repo/CHANGELOG.md @@ -5,6 +5,131 @@ 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.54.0](https://github.com/noir-lang/noir/compare/v0.53.0...v0.54.0) (2024-11-08) + + +### ⚠ BREAKING CHANGES + +* **avm/brillig:** revert/rethrow oracle (https://github.com/AztecProtocol/aztec-packages/pull/9408) +* use Brillig opcode when possible for less-than operations on fields (https://github.com/AztecProtocol/aztec-packages/pull/9416) +* remove noir_js_backend_barretenberg (https://github.com/AztecProtocol/aztec-packages/pull/9338) +* replace usage of vector in keccakf1600 input with array (https://github.com/AztecProtocol/aztec-packages/pull/9350) +* **profiler:** New flamegraph command that profiles the opcodes executed ([#6327](https://github.com/noir-lang/noir/issues/6327)) +* remove pedersen commitment (https://github.com/AztecProtocol/aztec-packages/pull/9107) +* remove pedersen hash opcode (https://github.com/AztecProtocol/aztec-packages/pull/9245) +* Brillig and AVM default all uninitialized memory cells to Field 0 (https://github.com/AztecProtocol/aztec-packages/pull/9057) +* remove keccak256 opcode from ACIR/Brillig (https://github.com/AztecProtocol/aztec-packages/pull/9104) +* Brillig with a stack and conditional inlining (https://github.com/AztecProtocol/aztec-packages/pull/8989) +* **avm:** remove CMOV opcode (https://github.com/AztecProtocol/aztec-packages/pull/9030) +* remove sha256 opcode (https://github.com/AztecProtocol/aztec-packages/pull/4571) +* add support for u1 in the avm, ToRadix's radix arg is a memory addr (https://github.com/AztecProtocol/aztec-packages/pull/8570) +* 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) + +### 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 support for u1 in the avm, ToRadix's radix arg is a memory addr (https://github.com/AztecProtocol/aztec-packages/pull/8570) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* 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:** Revert/rethrow oracle (https://github.com/AztecProtocol/aztec-packages/pull/9408) ([321a493](https://github.com/noir-lang/noir/commit/321a493216e19a2f077007c3447a3030db0df0d0)) +* **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)) +* Brillig and AVM default all uninitialized memory cells to Field 0 (https://github.com/AztecProtocol/aztec-packages/pull/9057) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Brillig with a stack and conditional inlining (https://github.com/AztecProtocol/aztec-packages/pull/8989) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* 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)) +* Ensure that generated ACIR is solvable ([#6415](https://github.com/noir-lang/noir/issues/6415)) ([b473d99](https://github.com/noir-lang/noir/commit/b473d99b2b70b595596b8392617256dbaf5d5642)) +* 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 databus in the private kernels (https://github.com/AztecProtocol/aztec-packages/pull/9028) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* 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)) +* 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 allocating immediate amounts of memory (https://github.com/AztecProtocol/aztec-packages/pull/8579) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* 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)) +* **profiler:** New flamegraph command that profiles the opcodes executed ([#6327](https://github.com/noir-lang/noir/issues/6327)) ([4d87c9a](https://github.com/noir-lang/noir/commit/4d87c9ac78b48b4bd0ae81316df28aab390d004e)) +* Remove 'single use' intermediate variables ([#6268](https://github.com/noir-lang/noir/issues/6268)) ([ec75e8e](https://github.com/noir-lang/noir/commit/ec75e8ec59e0f2a2169aea67372411ede4074d09)) +* Remove sha256 opcode (https://github.com/AztecProtocol/aztec-packages/pull/4571) ([e8bbce7](https://github.com/noir-lang/noir/commit/e8bbce71fde3fc7af410c30920c2a547389d8248)) +* 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)) +* 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/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)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/8934) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9034) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9099) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/9275) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* **test:** Fuzz test poseidon2 hash equivalence ([#6265](https://github.com/noir-lang/noir/issues/6265)) ([f61ba03](https://github.com/noir-lang/noir/commit/f61ba037c6726e19be4f894d9447fe396df95417)) +* **test:** Fuzz test stdlib hash functions ([#6233](https://github.com/noir-lang/noir/issues/6233)) ([1a2ca46](https://github.com/noir-lang/noir/commit/1a2ca46af0d1c05813dbe28670a2bc39b79e4c9f)) +* 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 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)) +* **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)) +* Discard optimisation that would change execution ordering or that is related to call outputs ([#6461](https://github.com/noir-lang/noir/issues/6461)) ([b8654f7](https://github.com/noir-lang/noir/commit/b8654f700b218cc09c5381af65df11ead9ffcdaf)) +* Display every bit in integer tokens ([#6360](https://github.com/noir-lang/noir/issues/6360)) ([b985fdf](https://github.com/noir-lang/noir/commit/b985fdf6e635570b8db3af83d9ec14e7cd749062)) +* 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)) +* Homogeneous input points for EC ADD ([#6241](https://github.com/noir-lang/noir/issues/6241)) ([f6a7306](https://github.com/noir-lang/noir/commit/f6a7306436ea1a37ec7f3b884721b50467e9a063)) +* Reject invalid expression with in CLI parser ([#6287](https://github.com/noir-lang/noir/issues/6287)) ([052aee8](https://github.com/noir-lang/noir/commit/052aee80ff3e1e4fd2ca45310d7bb8b980af126a)) +* Remove need for duplicate attributes on each function (https://github.com/AztecProtocol/aztec-packages/pull/9244) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* 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)) +* **tests:** Prevent EOF error while running test programs ([#6455](https://github.com/noir-lang/noir/issues/6455)) ([358e381](https://github.com/noir-lang/noir/commit/358e38107edbc4f40c97b88196456d82f5557e3f)) + + +### Miscellaneous Chores + +* Remove keccak256 opcode from ACIR/Brillig (https://github.com/AztecProtocol/aztec-packages/pull/9104) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Remove noir_js_backend_barretenberg (https://github.com/AztecProtocol/aztec-packages/pull/9338) ([3925228](https://github.com/noir-lang/noir/commit/392522880e102e275ebcf42f16651a8ffa0bbbd2)) +* Remove pedersen commitment (https://github.com/AztecProtocol/aztec-packages/pull/9107) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Remove pedersen hash opcode (https://github.com/AztecProtocol/aztec-packages/pull/9245) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) +* Replace usage of vector in keccakf1600 input with array (https://github.com/AztecProtocol/aztec-packages/pull/9350) ([3925228](https://github.com/noir-lang/noir/commit/392522880e102e275ebcf42f16651a8ffa0bbbd2)) +* Use Brillig opcode when possible for less-than operations on fields (https://github.com/AztecProtocol/aztec-packages/pull/9416) ([321a493](https://github.com/noir-lang/noir/commit/321a493216e19a2f077007c3447a3030db0df0d0)) + + +### Code Refactoring + +* **avm:** Remove CMOV opcode (https://github.com/AztecProtocol/aztec-packages/pull/9030) ([70dcf4a](https://github.com/noir-lang/noir/commit/70dcf4a25dcad10daeb427f0887d3a0bf10c9916)) + ## [0.53.0](https://github.com/noir-lang/noir/compare/v0.52.0...v0.53.0) (2024-10-31) diff --git a/noir/noir-repo/acvm-repo/acir/Cargo.toml b/noir/noir-repo/acvm-repo/acir/Cargo.toml index 2d164e3a983..ff6c9b1954e 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.53.0" +version = "0.54.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp index 8fa471e57ba..d237f2ab3b4 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp @@ -702,8 +702,7 @@ namespace Program { }; struct Stop { - uint64_t return_data_offset; - uint64_t return_data_size; + Program::HeapVector return_data; friend bool operator==(const Stop&, const Stop&); std::vector bincodeSerialize() const; @@ -5333,8 +5332,7 @@ Program::BrilligOpcode::Trap serde::Deserializable namespace Program { inline bool operator==(const BrilligOpcode::Stop &lhs, const BrilligOpcode::Stop &rhs) { - if (!(lhs.return_data_offset == rhs.return_data_offset)) { return false; } - if (!(lhs.return_data_size == rhs.return_data_size)) { return false; } + if (!(lhs.return_data == rhs.return_data)) { return false; } return true; } @@ -5358,16 +5356,14 @@ namespace Program { template <> template void serde::Serializable::serialize(const Program::BrilligOpcode::Stop &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.return_data_offset, serializer); - serde::Serializable::serialize(obj.return_data_size, serializer); + serde::Serializable::serialize(obj.return_data, serializer); } template <> template Program::BrilligOpcode::Stop serde::Deserializable::deserialize(Deserializer &deserializer) { Program::BrilligOpcode::Stop obj; - obj.return_data_offset = serde::Deserializable::deserialize(deserializer); - obj.return_data_size = serde::Deserializable::deserialize(deserializer); + obj.return_data = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs index 9ab153b9f61..b463d4d1fe5 100644 --- a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs +++ b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs @@ -20,7 +20,9 @@ use acir::{ native_types::{Expression, Witness}, }; use acir_field::{AcirField, FieldElement}; -use brillig::{BitSize, HeapArray, HeapValueType, IntegerBitSize, MemoryAddress, ValueOrArray}; +use brillig::{ + BitSize, HeapArray, HeapValueType, HeapVector, IntegerBitSize, MemoryAddress, ValueOrArray, +}; #[test] fn addition_circuit() { @@ -162,31 +164,37 @@ fn simple_brillig_foreign_call() { let w_input = Witness(1); let w_inverted = Witness(2); + let value_address = MemoryAddress::direct(0); + let zero_usize = MemoryAddress::direct(1); + let one_usize = MemoryAddress::direct(2); + let brillig_bytecode = BrilligBytecode { bytecode: vec![ brillig::Opcode::Const { - destination: MemoryAddress::direct(0), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(1_usize), + value: FieldElement::from(0_usize), }, brillig::Opcode::Const { - destination: MemoryAddress::direct(1), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0_usize), + value: FieldElement::from(1_usize), }, brillig::Opcode::CalldataCopy { - destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + destination_address: value_address, + size_address: one_usize, + offset_address: zero_usize, }, brillig::Opcode::ForeignCall { function: "invert".into(), - destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], + destinations: vec![ValueOrArray::MemoryAddress(value_address)], destination_value_types: vec![HeapValueType::field()], - inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], + inputs: vec![ValueOrArray::MemoryAddress(value_address)], input_value_types: vec![HeapValueType::field()], }, - brillig::Opcode::Stop { return_data_offset: 0, return_data_size: 1 }, + brillig::Opcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: one_usize }, + }, ], }; @@ -214,12 +222,12 @@ fn simple_brillig_foreign_call() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 79, 73, 10, 128, 48, 12, 236, 40, 46, 5, 111, 126, - 36, 254, 192, 207, 120, 240, 226, 65, 196, 247, 91, 48, 129, 80, 186, 28, 154, 129, 144, - 201, 132, 44, 3, 247, 99, 14, 1, 230, 3, 103, 169, 53, 68, 219, 57, 83, 27, 54, 216, 237, - 34, 253, 111, 23, 19, 104, 177, 96, 76, 204, 251, 68, 191, 55, 52, 238, 163, 187, 198, 251, - 105, 114, 101, 200, 221, 37, 196, 200, 252, 188, 222, 227, 126, 80, 153, 200, 213, 57, 125, - 77, 244, 62, 112, 171, 6, 33, 119, 2, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 81, 203, 10, 128, 48, 12, 179, 19, 31, 3, 111, 254, + 200, 246, 7, 254, 140, 7, 47, 30, 68, 252, 126, 39, 182, 80, 70, 182, 203, 26, 40, 73, 3, + 43, 9, 163, 238, 199, 156, 134, 88, 15, 204, 178, 107, 136, 183, 49, 135, 54, 68, 178, 187, + 21, 116, 94, 151, 11, 210, 102, 165, 152, 148, 247, 153, 255, 113, 111, 24, 214, 131, 124, + 134, 247, 227, 4, 58, 58, 208, 119, 73, 51, 178, 62, 206, 103, 191, 110, 244, 237, 250, 69, + 105, 47, 249, 43, 240, 37, 201, 11, 205, 95, 230, 87, 127, 2, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -304,7 +312,22 @@ fn complex_brillig_foreign_call() { HeapValueType::field(), ], }, - brillig::Opcode::Stop { return_data_offset: 32, return_data_size: 5 }, + brillig::Opcode::Const { + destination: MemoryAddress::direct(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(32_usize), + }, + brillig::Opcode::Const { + destination: MemoryAddress::direct(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(5_usize), + }, + brillig::Opcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(1), + }, + }, ], }; @@ -344,17 +367,17 @@ fn complex_brillig_foreign_call() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 93, 10, 194, 48, 12, 78, 219, 233, 54, 240, - 205, 11, 8, 122, 128, 76, 47, 176, 187, 136, 111, 138, 62, 122, 124, 45, 75, 88, 140, 197, - 9, 38, 224, 62, 24, 89, 75, 242, 229, 159, 6, 24, 208, 60, 191, 64, 255, 11, 146, 145, 100, - 190, 79, 240, 10, 214, 237, 73, 226, 111, 232, 130, 29, 23, 122, 197, 24, 103, 16, 99, 114, - 136, 17, 68, 255, 255, 176, 223, 150, 125, 49, 173, 95, 42, 236, 79, 5, 195, 126, 45, 233, - 92, 147, 108, 116, 161, 179, 81, 132, 247, 197, 147, 224, 225, 105, 149, 4, 229, 184, 183, - 73, 232, 208, 42, 191, 198, 252, 200, 197, 216, 192, 119, 249, 250, 228, 185, 71, 230, 79, - 46, 252, 216, 49, 127, 229, 212, 167, 90, 213, 75, 230, 34, 253, 174, 96, 28, 192, 227, - 245, 114, 59, 159, 238, 169, 96, 170, 205, 51, 182, 234, 188, 43, 148, 108, 138, 131, 33, - 223, 153, 79, 250, 161, 160, 63, 101, 179, 134, 113, 156, 248, 93, 123, 0, 142, 67, 44, - 107, 244, 6, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 205, 14, 130, 48, 12, 238, 54, 20, 136, 222, + 124, 1, 19, 125, 128, 161, 241, 238, 187, 24, 111, 26, 61, 250, 248, 186, 208, 198, 89, 26, + 56, 216, 18, 248, 18, 82, 6, 237, 215, 255, 204, 65, 139, 234, 243, 56, 124, 95, 160, 244, + 40, 211, 247, 0, 191, 32, 221, 51, 202, 248, 31, 26, 167, 199, 21, 173, 98, 244, 51, 136, + 49, 24, 196, 8, 89, 255, 39, 216, 111, 205, 190, 168, 214, 47, 8, 251, 83, 64, 187, 95, 75, + 60, 151, 40, 43, 94, 232, 100, 228, 161, 187, 120, 57, 104, 120, 86, 40, 107, 225, 191, 98, + 66, 199, 154, 249, 85, 230, 143, 84, 140, 45, 244, 231, 107, 155, 231, 33, 18, 127, 48, + 225, 143, 13, 241, 23, 70, 125, 42, 89, 189, 242, 92, 114, 191, 107, 248, 14, 224, 229, + 113, 127, 222, 174, 175, 32, 152, 114, 243, 132, 29, 59, 239, 133, 146, 13, 113, 16, 242, + 123, 166, 79, 223, 9, 250, 67, 54, 99, 141, 138, 209, 74, 156, 54, 208, 5, 249, 122, 3, 73, + 2, 62, 54, 188, 7, 0, 0, ]; assert_eq!(bytes, expected_serialization) diff --git a/noir/noir-repo/acvm-repo/acir_field/Cargo.toml b/noir/noir-repo/acvm-repo/acir_field/Cargo.toml index a8e7f34a374..66a01848a54 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.53.0" +version = "0.54.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 145c07a4a00..2b143ebe475 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.53.0" +version = "0.54.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs index 7c0be0fc3fe..a5258a494a2 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -1,7 +1,12 @@ use std::collections::{BTreeMap, BTreeSet, HashMap}; use acir::{ - circuit::{brillig::BrilligInputs, directives::Directive, opcodes::BlockId, Circuit, Opcode}, + circuit::{ + brillig::{BrilligInputs, BrilligOutputs}, + directives::Directive, + opcodes::BlockId, + Circuit, Opcode, + }, native_types::{Expression, Witness}, AcirField, }; @@ -72,23 +77,31 @@ impl MergeExpressionsOptimizer { if let (Opcode::AssertZero(expr_define), Opcode::AssertZero(expr_use)) = (opcode.clone(), second_gate) { - if let Some(expr) = Self::merge(&expr_use, &expr_define, w) { - // sanity check - assert!(i < b); - modified_gates.insert(b, Opcode::AssertZero(expr)); - to_keep = false; - // Update the 'used_witness' map to account for the merge. - for w2 in CircuitSimulator::expr_wit(&expr_define) { - if !circuit_inputs.contains(&w2) { - let mut v = used_witness[&w2].clone(); - v.insert(b); - v.remove(&i); - used_witness.insert(w2, v); + // We cannot merge an expression into an earlier opcode, because this + // would break the 'execution ordering' of the opcodes + // This case can happen because a previous merge would change an opcode + // and eliminate a witness from it, giving new opportunities for this + // witness to be used in only two expressions + // TODO: the missed optimization for the i>b case can be handled by + // - doing this pass again until there is no change, or + // - merging 'b' into 'i' instead + if i < b { + if let Some(expr) = Self::merge(&expr_use, &expr_define, w) { + modified_gates.insert(b, Opcode::AssertZero(expr)); + to_keep = false; + // Update the 'used_witness' map to account for the merge. + for w2 in CircuitSimulator::expr_wit(&expr_define) { + if !circuit_inputs.contains(&w2) { + let mut v = used_witness[&w2].clone(); + v.insert(b); + v.remove(&i); + used_witness.insert(w2, v); + } } + // We need to stop here and continue with the next opcode + // because the merge invalidates the current opcode. + break; } - // We need to stop here and continue with the next opcode - // because the merge invalidate the current opcode - break; } } } @@ -125,6 +138,19 @@ impl MergeExpressionsOptimizer { result } + fn brillig_output_wit(&self, output: &BrilligOutputs) -> BTreeSet { + let mut result = BTreeSet::new(); + match output { + BrilligOutputs::Simple(witness) => { + result.insert(*witness); + } + BrilligOutputs::Array(witnesses) => { + result.extend(witnesses); + } + } + result + } + // Returns the input witnesses used by the opcode fn witness_inputs(&self, opcode: &Opcode) -> BTreeSet { let mut witnesses = BTreeSet::new(); @@ -146,16 +172,22 @@ impl MergeExpressionsOptimizer { Opcode::MemoryInit { block_id: _, init, block_type: _ } => { init.iter().cloned().collect() } - Opcode::BrilligCall { inputs, .. } => { + Opcode::BrilligCall { inputs, outputs, .. } => { for i in inputs { witnesses.extend(self.brillig_input_wit(i)); } + for i in outputs { + witnesses.extend(self.brillig_output_wit(i)); + } witnesses } - Opcode::Call { id: _, inputs, outputs: _, predicate } => { + Opcode::Call { id: _, inputs, outputs, predicate } => { for i in inputs { witnesses.insert(*i); } + for i in outputs { + witnesses.insert(*i); + } if let Some(p) = predicate { witnesses.extend(CircuitSimulator::expr_wit(p)); } @@ -195,3 +227,127 @@ impl MergeExpressionsOptimizer { None } } + +#[cfg(test)] +mod tests { + use crate::compiler::{optimizers::MergeExpressionsOptimizer, CircuitSimulator}; + use acir::{ + acir_field::AcirField, + circuit::{ + brillig::{BrilligFunctionId, BrilligOutputs}, + opcodes::FunctionInput, + Circuit, ExpressionWidth, Opcode, PublicInputs, + }, + native_types::{Expression, Witness}, + FieldElement, + }; + use std::collections::BTreeSet; + + fn check_circuit(circuit: Circuit) { + assert!(CircuitSimulator::default().check_circuit(&circuit)); + let mut merge_optimizer = MergeExpressionsOptimizer::new(); + let acir_opcode_positions = vec![0; 20]; + let (opcodes, _) = + merge_optimizer.eliminate_intermediate_variable(&circuit, acir_opcode_positions); + let mut optimized_circuit = circuit; + optimized_circuit.opcodes = opcodes; + // check that the circuit is still valid after optimization + assert!(CircuitSimulator::default().check_circuit(&optimized_circuit)); + } + + #[test] + fn does_not_eliminate_witnesses_returned_from_brillig() { + let opcodes = vec![ + Opcode::BrilligCall { + id: BrilligFunctionId::default(), + inputs: Vec::new(), + outputs: vec![BrilligOutputs::Simple(Witness(1))], + predicate: None, + }, + Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (FieldElement::from(2_u128), Witness(0)), + (FieldElement::from(3_u128), Witness(1)), + (FieldElement::from(1_u128), Witness(2)), + ], + q_c: FieldElement::one(), + }), + Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (FieldElement::from(2_u128), Witness(0)), + (FieldElement::from(2_u128), Witness(1)), + (FieldElement::from(1_u128), Witness(5)), + ], + q_c: FieldElement::one(), + }), + ]; + + let mut private_parameters = BTreeSet::new(); + private_parameters.insert(Witness(0)); + + let circuit = Circuit { + current_witness_index: 1, + expression_width: ExpressionWidth::Bounded { width: 4 }, + opcodes, + private_parameters, + public_parameters: PublicInputs::default(), + return_values: PublicInputs::default(), + assert_messages: Default::default(), + }; + check_circuit(circuit); + } + + #[test] + fn does_not_attempt_to_merge_into_previous_opcodes() { + let opcodes = vec![ + Opcode::AssertZero(Expression { + mul_terms: vec![(FieldElement::one(), Witness(0), Witness(0))], + linear_combinations: vec![(-FieldElement::one(), Witness(4))], + q_c: FieldElement::zero(), + }), + Opcode::AssertZero(Expression { + mul_terms: vec![(FieldElement::one(), Witness(0), Witness(1))], + linear_combinations: vec![(FieldElement::one(), Witness(5))], + q_c: FieldElement::zero(), + }), + Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (-FieldElement::one(), Witness(2)), + (FieldElement::one(), Witness(4)), + (FieldElement::one(), Witness(5)), + ], + q_c: FieldElement::zero(), + }), + Opcode::AssertZero(Expression { + mul_terms: Vec::new(), + linear_combinations: vec![ + (FieldElement::one(), Witness(2)), + (-FieldElement::one(), Witness(3)), + (FieldElement::one(), Witness(4)), + (FieldElement::one(), Witness(5)), + ], + q_c: FieldElement::zero(), + }), + Opcode::BlackBoxFuncCall(acir::circuit::opcodes::BlackBoxFuncCall::RANGE { + input: FunctionInput::witness(Witness(3), 32), + }), + ]; + + let mut private_parameters = BTreeSet::new(); + private_parameters.insert(Witness(0)); + private_parameters.insert(Witness(1)); + let circuit = Circuit { + current_witness_index: 5, + expression_width: ExpressionWidth::Bounded { width: 4 }, + opcodes, + private_parameters, + public_parameters: PublicInputs::default(), + return_values: PublicInputs::default(), + assert_messages: Default::default(), + }; + check_circuit(circuit); + } +} diff --git a/noir/noir-repo/acvm-repo/acvm/tests/solver.rs b/noir/noir-repo/acvm-repo/acvm/tests/solver.rs index 2828ea3d79e..8b164b7c0f2 100644 --- a/noir/noir-repo/acvm-repo/acvm/tests/solver.rs +++ b/noir/noir-repo/acvm-repo/acvm/tests/solver.rs @@ -77,13 +77,6 @@ fn inversion_brillig_oracle_equivalence() { let w_x_plus_y = Witness(6); let w_equal_res = Witness(7); - let equal_opcode = BrilligOpcode::BinaryFieldOp { - op: BinaryFieldOp::Equals, - lhs: MemoryAddress::direct(0), - rhs: MemoryAddress::direct(1), - destination: MemoryAddress::direct(2), - }; - let opcodes = vec![ Opcode::BrilligCall { id: BrilligFunctionId(0), @@ -122,22 +115,38 @@ fn inversion_brillig_oracle_equivalence() { }), ]; + let equal_opcode = BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Equals, + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(2), + }; + + let zero_usize = MemoryAddress::direct(3); + let two_usize = MemoryAddress::direct(4); + let three_usize = MemoryAddress::direct(5); + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress::direct(0), + destination: zero_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::Const { + destination: two_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(2u64), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(1), + destination: three_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0u64), + value: FieldElement::from(3u64), }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + size_address: two_usize, + offset_address: zero_usize, }, equal_opcode, // Oracles are named 'foreign calls' in brillig @@ -148,7 +157,9 @@ fn inversion_brillig_oracle_equivalence() { inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], input_value_types: vec![HeapValueType::field()], }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 3 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: three_usize }, + }, ], }; @@ -216,13 +227,6 @@ fn double_inversion_brillig_oracle() { let w_ij_oracle = Witness(10); let w_i_plus_j = Witness(11); - let equal_opcode = BrilligOpcode::BinaryFieldOp { - op: BinaryFieldOp::Equals, - lhs: MemoryAddress::direct(0), - rhs: MemoryAddress::direct(1), - destination: MemoryAddress::direct(4), - }; - let opcodes = vec![ Opcode::BrilligCall { id: BrilligFunctionId(0), @@ -268,22 +272,38 @@ fn double_inversion_brillig_oracle() { }), ]; + let zero_usize = MemoryAddress::direct(5); + let three_usize = MemoryAddress::direct(6); + let five_usize = MemoryAddress::direct(7); + + let equal_opcode = BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Equals, + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(4), + }; + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress::direct(0), + destination: zero_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::Const { + destination: three_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(3u64), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(1), + destination: five_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0u64), + value: FieldElement::from(5u64), }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + size_address: three_usize, + offset_address: zero_usize, }, equal_opcode, // Oracles are named 'foreign calls' in brillig @@ -301,7 +321,9 @@ fn double_inversion_brillig_oracle() { inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(2))], input_value_types: vec![HeapValueType::field()], }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 5 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: five_usize }, + }, ], }; @@ -386,22 +408,31 @@ fn oracle_dependent_execution() { let w_x_inv = Witness(3); let w_y_inv = Witness(4); + let zero_usize = MemoryAddress::direct(4); + let three_usize = MemoryAddress::direct(5); + let four_usize = MemoryAddress::direct(6); + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress::direct(0), + destination: zero_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::Const { + destination: three_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(3u64), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(1), + destination: four_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0u64), + value: FieldElement::from(4u64), }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + size_address: three_usize, + offset_address: zero_usize, }, // Oracles are named 'foreign calls' in brillig BrilligOpcode::ForeignCall { function: "invert".into(), @@ -417,7 +448,9 @@ fn oracle_dependent_execution() { inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(2))], input_value_types: vec![HeapValueType::field()], }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 4 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: four_usize }, + }, ], }; @@ -662,7 +695,7 @@ fn unsatisfied_opcode_resolved_brillig() { }; // Jump pass the trap if the values are equal, else // jump to the trap - let location_of_stop = 3; + let location_of_stop = 7; let jmp_if_opcode = BrilligOpcode::JumpIf { condition: MemoryAddress::direct(2), location: location_of_stop }; @@ -673,7 +706,12 @@ fn unsatisfied_opcode_resolved_brillig() { size: MemoryAddress::direct(3), }, }; - let stop_opcode = BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }; + let stop_opcode = BrilligOpcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(3), + }, + }; let brillig_bytecode = BrilligBytecode { bytecode: vec![ diff --git a/noir/noir-repo/acvm-repo/acvm_js/Cargo.toml b/noir/noir-repo/acvm-repo/acvm_js/Cargo.toml index 0e5fdf8b5c7..db34458ad88 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.53.0" +version = "0.54.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acvm_js/package.json b/noir/noir-repo/acvm-repo/acvm_js/package.json index 163ea553169..b68aa023086 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.53.0", + "version": "0.54.0", "publishConfig": { "access": "public" }, diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts index b2b0aff6ed3..755b5a7587b 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts @@ -2,14 +2,14 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `complex_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 93, 10, 194, 48, 12, 78, 219, 233, 54, 240, 205, 11, 8, 122, 128, 76, 47, - 176, 187, 136, 111, 138, 62, 122, 124, 45, 75, 88, 140, 197, 9, 38, 224, 62, 24, 89, 75, 242, 229, 159, 6, 24, 208, - 60, 191, 64, 255, 11, 146, 145, 100, 190, 79, 240, 10, 214, 237, 73, 226, 111, 232, 130, 29, 23, 122, 197, 24, 103, - 16, 99, 114, 136, 17, 68, 255, 255, 176, 223, 150, 125, 49, 173, 95, 42, 236, 79, 5, 195, 126, 45, 233, 92, 147, 108, - 116, 161, 179, 81, 132, 247, 197, 147, 224, 225, 105, 149, 4, 229, 184, 183, 73, 232, 208, 42, 191, 198, 252, 200, - 197, 216, 192, 119, 249, 250, 228, 185, 71, 230, 79, 46, 252, 216, 49, 127, 229, 212, 167, 90, 213, 75, 230, 34, 253, - 174, 96, 28, 192, 227, 245, 114, 59, 159, 238, 169, 96, 170, 205, 51, 182, 234, 188, 43, 148, 108, 138, 131, 33, 223, - 153, 79, 250, 161, 160, 63, 101, 179, 134, 113, 156, 248, 93, 123, 0, 142, 67, 44, 107, 244, 6, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 205, 14, 130, 48, 12, 238, 54, 20, 136, 222, 124, 1, 19, 125, 128, 161, + 241, 238, 187, 24, 111, 26, 61, 250, 248, 186, 208, 198, 89, 26, 56, 216, 18, 248, 18, 82, 6, 237, 215, 255, 204, 65, + 139, 234, 243, 56, 124, 95, 160, 244, 40, 211, 247, 0, 191, 32, 221, 51, 202, 248, 31, 26, 167, 199, 21, 173, 98, 244, + 51, 136, 49, 24, 196, 8, 89, 255, 39, 216, 111, 205, 190, 168, 214, 47, 8, 251, 83, 64, 187, 95, 75, 60, 151, 40, 43, + 94, 232, 100, 228, 161, 187, 120, 57, 104, 120, 86, 40, 107, 225, 191, 98, 66, 199, 154, 249, 85, 230, 143, 84, 140, + 45, 244, 231, 107, 155, 231, 33, 18, 127, 48, 225, 143, 13, 241, 23, 70, 125, 42, 89, 189, 242, 92, 114, 191, 107, + 248, 14, 224, 229, 113, 127, 222, 174, 175, 32, 152, 114, 243, 132, 29, 59, 239, 133, 146, 13, 113, 16, 242, 123, 166, + 79, 223, 9, 250, 67, 54, 99, 141, 138, 209, 74, 156, 54, 208, 5, 249, 122, 3, 73, 2, 62, 54, 188, 7, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts index 6cec99a636d..37b70e23a3a 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts @@ -2,11 +2,11 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `simple_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 79, 73, 10, 128, 48, 12, 236, 40, 46, 5, 111, 126, 36, 254, 192, 207, 120, - 240, 226, 65, 196, 247, 91, 48, 129, 80, 186, 28, 154, 129, 144, 201, 132, 44, 3, 247, 99, 14, 1, 230, 3, 103, 169, - 53, 68, 219, 57, 83, 27, 54, 216, 237, 34, 253, 111, 23, 19, 104, 177, 96, 76, 204, 251, 68, 191, 55, 52, 238, 163, - 187, 198, 251, 105, 114, 101, 200, 221, 37, 196, 200, 252, 188, 222, 227, 126, 80, 153, 200, 213, 57, 125, 77, 244, - 62, 112, 171, 6, 33, 119, 2, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 81, 203, 10, 128, 48, 12, 179, 19, 31, 3, 111, 254, 200, 246, 7, 254, 140, 7, + 47, 30, 68, 252, 126, 39, 182, 80, 70, 182, 203, 26, 40, 73, 3, 43, 9, 163, 238, 199, 156, 134, 88, 15, 204, 178, 107, + 136, 183, 49, 135, 54, 68, 178, 187, 21, 116, 94, 151, 11, 210, 102, 165, 152, 148, 247, 153, 255, 113, 111, 24, 214, + 131, 124, 134, 247, 227, 4, 58, 58, 208, 119, 73, 51, 178, 62, 206, 103, 191, 110, 244, 237, 250, 69, 105, 47, 249, + 43, 240, 37, 201, 11, 205, 95, 230, 87, 127, 2, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000005'], diff --git a/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml b/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml index 4c341a42a04..944b17c7dc6 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.53.0" +version = "0.54.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 97f6b76a9a3..7541fe239c9 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.53.0" +version = "0.54.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -19,10 +19,10 @@ workspace = true acir.workspace = true acvm_blackbox_solver.workspace = true hex.workspace = true -lazy_static = "1.4" +lazy_static.workspace = true ark-bn254.workspace = true -grumpkin.workspace = true +grumpkin.workspace = true ark-ec.workspace = true ark-ff.workspace = true num-bigint.workspace = true diff --git a/noir/noir-repo/acvm-repo/brillig/Cargo.toml b/noir/noir-repo/acvm-repo/brillig/Cargo.toml index c0e50150b78..7b48ff318d3 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.53.0" +version = "0.54.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/brillig/src/opcodes.rs b/noir/noir-repo/acvm-repo/brillig/src/opcodes.rs index 0d87c5b9410..8b72b5a9b41 100644 --- a/noir/noir-repo/acvm-repo/brillig/src/opcodes.rs +++ b/noir/noir-repo/acvm-repo/brillig/src/opcodes.rs @@ -309,8 +309,7 @@ pub enum BrilligOpcode { }, /// Stop execution, returning data after the offset Stop { - return_data_offset: usize, - return_data_size: usize, + return_data: HeapVector, }, } diff --git a/noir/noir-repo/acvm-repo/brillig_vm/Cargo.toml b/noir/noir-repo/acvm-repo/brillig_vm/Cargo.toml index 3cfedd1a1fb..a9cb409a6f4 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.53.0" +version = "0.54.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs b/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs index 89d72c4614b..0a1614a98fc 100644 --- a/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs +++ b/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs @@ -357,8 +357,16 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { self.trap(0, 0) } } - Opcode::Stop { return_data_offset, return_data_size } => { - self.finish(*return_data_offset, *return_data_size) + Opcode::Stop { return_data } => { + let return_data_size = self.memory.read(return_data.size).to_usize(); + if return_data_size > 0 { + self.finish( + self.memory.read_ref(return_data.pointer).unwrap_direct(), + return_data_size, + ) + } else { + self.finish(0, 0) + } } Opcode::Load { destination: destination_address, source_pointer } => { // Convert our source_pointer to an address @@ -1005,28 +1013,37 @@ mod tests { fn cast_opcode() { let calldata: Vec = vec![((2_u128.pow(32)) - 1).into()]; + let value_address = MemoryAddress::direct(1); + let one_usize = MemoryAddress::direct(2); + let zero_usize = MemoryAddress::direct(3); + let opcodes = &[ Opcode::Const { - destination: MemoryAddress::direct(0), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(1u64), }, Opcode::Const { - destination: MemoryAddress::direct(1), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, Opcode::CalldataCopy { - destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + destination_address: value_address, + size_address: one_usize, + offset_address: zero_usize, }, Opcode::Cast { - destination: MemoryAddress::direct(1), - source: MemoryAddress::direct(0), + destination: value_address, + source: value_address, bit_size: BitSize::Integer(IntegerBitSize::U8), }, - Opcode::Stop { return_data_offset: 1, return_data_size: 1 }, + Opcode::Stop { + return_data: HeapVector { + pointer: one_usize, // Since value_address is direct(1) + size: one_usize, + }, + }, ]; let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); @@ -1051,33 +1068,42 @@ mod tests { fn not_opcode() { let calldata: Vec = vec![(1_usize).into()]; + let value_address = MemoryAddress::direct(1); + let one_usize = MemoryAddress::direct(2); + let zero_usize = MemoryAddress::direct(3); + let opcodes = &[ Opcode::Const { - destination: MemoryAddress::direct(0), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(1u64), }, Opcode::Const { - destination: MemoryAddress::direct(1), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, Opcode::CalldataCopy { - destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + destination_address: value_address, + size_address: one_usize, + offset_address: zero_usize, }, Opcode::Cast { - destination: MemoryAddress::direct(1), - source: MemoryAddress::direct(0), + destination: value_address, + source: value_address, bit_size: BitSize::Integer(IntegerBitSize::U128), }, Opcode::Not { - destination: MemoryAddress::direct(1), - source: MemoryAddress::direct(1), + destination: value_address, + source: value_address, bit_size: IntegerBitSize::U128, }, - Opcode::Stop { return_data_offset: 1, return_data_size: 1 }, + Opcode::Stop { + return_data: HeapVector { + pointer: one_usize, // Since value_address is direct(1) + size: one_usize, + }, + }, ]; let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); 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 bf64c9c920c..625a35c8d15 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs @@ -6,6 +6,7 @@ use iter_extended::vecmap; use noirc_abi::{ Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue, AbiVisibility, Sign, }; +use noirc_errors::Span; use noirc_evaluator::ErrorType; use noirc_frontend::ast::{Signedness, Visibility}; use noirc_frontend::TypeBinding; @@ -40,11 +41,21 @@ pub(super) fn gen_abi( Abi { parameters, return_type, error_types } } +// Get the Span of the root crate's main function, or else a dummy span if that fails +fn get_main_function_span(context: &Context) -> Span { + if let Some(func_id) = context.get_main_function(context.root_crate_id()) { + context.function_meta(&func_id).location.span + } else { + Span::default() + } +} + fn build_abi_error_type(context: &Context, typ: ErrorType) -> AbiErrorType { match typ { ErrorType::Dynamic(typ) => { if let Type::FmtString(len, item_types) = typ { - let length = len.evaluate_to_u32().expect("Cannot evaluate fmt length"); + let span = get_main_function_span(context); + let length = len.evaluate_to_u32(span).expect("Cannot evaluate fmt length"); let Type::Tuple(item_types) = item_types.as_ref() else { unreachable!("FmtString items must be a tuple") }; @@ -63,8 +74,9 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType { match typ { Type::FieldElement => AbiType::Field, Type::Array(size, typ) => { + let span = get_main_function_span(context); let length = size - .evaluate_to_u32() + .evaluate_to_u32(span) .expect("Cannot have variable sized arrays as a parameter to main"); let typ = typ.as_ref(); AbiType::Array { length, typ: Box::new(abi_type_from_hir_type(context, typ)) } @@ -91,8 +103,9 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType { } Type::Bool => AbiType::Boolean, Type::String(size) => { + let span = get_main_function_span(context); let size = size - .evaluate_to_u32() + .evaluate_to_u32(span) .expect("Cannot have variable sized strings as a parameter to main"); AbiType::String { length: size } } @@ -107,6 +120,7 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType { AbiType::Struct { fields, path } } Type::Alias(def, args) => abi_type_from_hir_type(context, &def.borrow().get_type(args)), + Type::CheckedCast { to, .. } => abi_type_from_hir_type(context, to), Type::Tuple(fields) => { let fields = vecmap(fields, |typ| abi_type_from_hir_type(context, typ)); AbiType::Tuple { fields } diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index c4e2491a5fe..d10029d81e6 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -456,9 +456,8 @@ fn compile_contract_inner( .secondary .iter() .filter_map(|attr| match attr { - SecondaryAttribute::Tag(attribute) | SecondaryAttribute::Meta(attribute) => { - Some(attribute.contents.clone()) - } + SecondaryAttribute::Tag(attribute) => Some(attribute.contents.clone()), + SecondaryAttribute::Meta(attribute) => Some(attribute.to_string()), _ => None, }) .collect(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/Cargo.toml b/noir/noir-repo/compiler/noirc_evaluator/Cargo.toml index 1db6af2ae85..aac07339dd6 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/Cargo.toml +++ b/noir/noir-repo/compiler/noirc_evaluator/Cargo.toml @@ -20,6 +20,7 @@ fxhash.workspace = true iter-extended.workspace = true thiserror.workspace = true num-bigint = "0.4" +num-traits.workspace = true im.workspace = true serde.workspace = true serde_json.workspace = true @@ -31,7 +32,8 @@ cfg-if.workspace = true [dev-dependencies] proptest.workspace = true +similar-asserts.workspace = true [features] bn254 = ["noirc_frontend/bn254"] -bls12_381= [] +bls12_381 = [] 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 48914c6219d..40224e132ab 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 @@ -2,6 +2,7 @@ use crate::brillig::brillig_ir::artifact::Label; use crate::brillig::brillig_ir::brillig_variable::{ type_to_heap_value_type, BrilligArray, BrilligVariable, SingleAddrVariable, }; + use crate::brillig::brillig_ir::registers::Stack; use crate::brillig::brillig_ir::{ BrilligBinaryOp, BrilligContext, ReservedRegisters, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, @@ -1202,7 +1203,7 @@ impl<'block> BrilligBlock<'block> { let brillig_binary_op = match binary.operator { BinaryOp::Div => { if is_signed { - self.convert_signed_division(left, right, result_variable); + self.brillig_context.convert_signed_division(left, right, result_variable); return; } else if is_field { BrilligBinaryOp::FieldDiv @@ -1234,7 +1235,14 @@ impl<'block> BrilligBlock<'block> { BinaryOp::Or => BrilligBinaryOp::Or, BinaryOp::Xor => BrilligBinaryOp::Xor, BinaryOp::Shl => BrilligBinaryOp::Shl, - BinaryOp::Shr => BrilligBinaryOp::Shr, + BinaryOp::Shr => { + if is_signed { + self.convert_signed_shr(left, right, result_variable); + return; + } else { + BrilligBinaryOp::Shr + } + } }; self.brillig_context.binary_instruction(left, right, result_variable, brillig_binary_op); @@ -1250,98 +1258,6 @@ impl<'block> BrilligBlock<'block> { ); } - /// Splits a two's complement signed integer in the sign bit and the absolute value. - /// For example, -6 i8 (11111010) is split to 00000110 (6, absolute value) and 1 (is_negative). - fn absolute_value( - &mut self, - num: SingleAddrVariable, - absolute_value: SingleAddrVariable, - result_is_negative: SingleAddrVariable, - ) { - let max_positive = self - .brillig_context - .make_constant_instruction(((1_u128 << (num.bit_size - 1)) - 1).into(), num.bit_size); - - // Compute if num is negative - self.brillig_context.binary_instruction( - max_positive, - num, - result_is_negative, - BrilligBinaryOp::LessThan, - ); - - // Two's complement of num - let zero = self.brillig_context.make_constant_instruction(0_usize.into(), num.bit_size); - let twos_complement = - SingleAddrVariable::new(self.brillig_context.allocate_register(), num.bit_size); - self.brillig_context.binary_instruction(zero, num, twos_complement, BrilligBinaryOp::Sub); - - // absolute_value = result_is_negative ? twos_complement : num - self.brillig_context.codegen_branch(result_is_negative.address, |ctx, is_negative| { - if is_negative { - ctx.mov_instruction(absolute_value.address, twos_complement.address); - } else { - ctx.mov_instruction(absolute_value.address, num.address); - } - }); - - self.brillig_context.deallocate_single_addr(zero); - self.brillig_context.deallocate_single_addr(max_positive); - self.brillig_context.deallocate_single_addr(twos_complement); - } - - fn convert_signed_division( - &mut self, - left: SingleAddrVariable, - right: SingleAddrVariable, - result: SingleAddrVariable, - ) { - let left_is_negative = SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); - let left_abs_value = - SingleAddrVariable::new(self.brillig_context.allocate_register(), left.bit_size); - - let right_is_negative = - SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); - let right_abs_value = - SingleAddrVariable::new(self.brillig_context.allocate_register(), right.bit_size); - - let result_is_negative = - SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); - - // Compute both absolute values - self.absolute_value(left, left_abs_value, left_is_negative); - self.absolute_value(right, right_abs_value, right_is_negative); - - // Perform the division on the absolute values - self.brillig_context.binary_instruction( - left_abs_value, - right_abs_value, - result, - BrilligBinaryOp::UnsignedDiv, - ); - - // Compute result sign - self.brillig_context.binary_instruction( - left_is_negative, - right_is_negative, - result_is_negative, - BrilligBinaryOp::Xor, - ); - - // If result has to be negative, perform two's complement - self.brillig_context.codegen_if(result_is_negative.address, |ctx| { - let zero = ctx.make_constant_instruction(0_usize.into(), result.bit_size); - ctx.binary_instruction(zero, result, result, BrilligBinaryOp::Sub); - ctx.deallocate_single_addr(zero); - }); - - self.brillig_context.deallocate_single_addr(left_is_negative); - self.brillig_context.deallocate_single_addr(left_abs_value); - self.brillig_context.deallocate_single_addr(right_is_negative); - self.brillig_context.deallocate_single_addr(right_abs_value); - self.brillig_context.deallocate_single_addr(result_is_negative); - } - fn convert_signed_modulo( &mut self, left: SingleAddrVariable, @@ -1354,7 +1270,7 @@ impl<'block> BrilligBlock<'block> { SingleAddrVariable::new(self.brillig_context.allocate_register(), left.bit_size); // i = left / right - self.convert_signed_division(left, right, scratch_var_i); + self.brillig_context.convert_signed_division(left, right, scratch_var_i); // j = i * right self.brillig_context.binary_instruction( @@ -1401,6 +1317,56 @@ impl<'block> BrilligBlock<'block> { self.brillig_context.deallocate_single_addr(bias); } + fn convert_signed_shr( + &mut self, + left: SingleAddrVariable, + right: SingleAddrVariable, + result: SingleAddrVariable, + ) { + // Check if left is negative + let left_is_negative = SingleAddrVariable::new(self.brillig_context.allocate_register(), 1); + let max_positive = self + .brillig_context + .make_constant_instruction(((1_u128 << (left.bit_size - 1)) - 1).into(), left.bit_size); + self.brillig_context.binary_instruction( + max_positive, + left, + left_is_negative, + BrilligBinaryOp::LessThan, + ); + + self.brillig_context.codegen_branch(left_is_negative.address, |ctx, is_negative| { + if is_negative { + let one = ctx.make_constant_instruction(1_u128.into(), left.bit_size); + + // computes 2^right + let two = ctx.make_constant_instruction(2_u128.into(), left.bit_size); + let two_pow = ctx.make_constant_instruction(1_u128.into(), left.bit_size); + let right_u32 = SingleAddrVariable::new(ctx.allocate_register(), 32); + ctx.cast(right_u32, right); + let pow_body = |ctx: &mut BrilligContext<_, _>, _: SingleAddrVariable| { + ctx.binary_instruction(two_pow, two, two_pow, BrilligBinaryOp::Mul); + }; + ctx.codegen_for_loop(None, right_u32.address, None, pow_body); + + // Right shift using division on 1-complement + ctx.binary_instruction(left, one, result, BrilligBinaryOp::Add); + ctx.convert_signed_division(result, two_pow, result); + ctx.binary_instruction(result, one, result, BrilligBinaryOp::Sub); + + // Clean-up + ctx.deallocate_single_addr(one); + ctx.deallocate_single_addr(two); + ctx.deallocate_single_addr(two_pow); + ctx.deallocate_single_addr(right_u32); + } else { + ctx.binary_instruction(left, right, result, BrilligBinaryOp::Shr); + } + }); + + self.brillig_context.deallocate_single_addr(left_is_negative); + } + #[allow(clippy::too_many_arguments)] fn add_overflow_check( &mut self, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs index 854014eb1d2..d5529c00d6c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs @@ -1,5 +1,7 @@ use acvm::acir::{ - brillig::{BinaryFieldOp, BitSize, IntegerBitSize, MemoryAddress, Opcode as BrilligOpcode}, + brillig::{ + BinaryFieldOp, BitSize, HeapVector, IntegerBitSize, MemoryAddress, Opcode as BrilligOpcode, + }, AcirField, }; @@ -18,25 +20,27 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { let one_const = MemoryAddress::direct(1); let zero_const = MemoryAddress::direct(2); let input_is_zero = MemoryAddress::direct(3); + let zero_usize = MemoryAddress::direct(20); + let one_usize = MemoryAddress::direct(21); // Location of the stop opcode let stop_location = 8; GeneratedBrillig { byte_code: vec![ BrilligOpcode::Const { - destination: MemoryAddress::direct(20), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: F::from(1_usize), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(21), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: F::from(0_usize), }, BrilligOpcode::CalldataCopy { destination_address: input, - size_address: MemoryAddress::direct(20), - offset_address: MemoryAddress::direct(21), + size_address: one_usize, + offset_address: zero_usize, }, // Put value zero in register (2) BrilligOpcode::Const { @@ -65,10 +69,10 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { rhs: input, destination: input, }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 1 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: one_usize }, + }, ], - error_types: Default::default(), - locations: Default::default(), name: "directive_invert".to_string(), ..Default::default() } @@ -131,10 +135,13 @@ pub(crate) fn directive_quotient() -> GeneratedBrillig { destination: MemoryAddress::direct(0), source: MemoryAddress::direct(2), }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 2 }, + BrilligOpcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(11), + size: MemoryAddress::direct(10), + }, + }, ], - error_types: Default::default(), - locations: Default::default(), name: "directive_integer_quotient".to_string(), ..Default::default() } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index 3633700a795..b4e10035af6 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -25,6 +25,7 @@ mod entry_point; mod instructions; use artifact::Label; +use brillig_variable::SingleAddrVariable; pub(crate) use instructions::BrilligBinaryOp; use registers::{RegisterAllocator, ScratchSpace}; @@ -109,6 +110,87 @@ impl BrilligContext { can_call_procedures: true, } } + + /// Splits a two's complement signed integer in the sign bit and the absolute value. + /// For example, -6 i8 (11111010) is split to 00000110 (6, absolute value) and 1 (is_negative). + pub(crate) fn absolute_value( + &mut self, + num: SingleAddrVariable, + absolute_value: SingleAddrVariable, + result_is_negative: SingleAddrVariable, + ) { + let max_positive = self + .make_constant_instruction(((1_u128 << (num.bit_size - 1)) - 1).into(), num.bit_size); + + // Compute if num is negative + self.binary_instruction(max_positive, num, result_is_negative, BrilligBinaryOp::LessThan); + + // Two's complement of num + let zero = self.make_constant_instruction(0_usize.into(), num.bit_size); + let twos_complement = SingleAddrVariable::new(self.allocate_register(), num.bit_size); + self.binary_instruction(zero, num, twos_complement, BrilligBinaryOp::Sub); + + // absolute_value = result_is_negative ? twos_complement : num + self.codegen_branch(result_is_negative.address, |ctx, is_negative| { + if is_negative { + ctx.mov_instruction(absolute_value.address, twos_complement.address); + } else { + ctx.mov_instruction(absolute_value.address, num.address); + } + }); + + self.deallocate_single_addr(zero); + self.deallocate_single_addr(max_positive); + self.deallocate_single_addr(twos_complement); + } + + pub(crate) fn convert_signed_division( + &mut self, + left: SingleAddrVariable, + right: SingleAddrVariable, + result: SingleAddrVariable, + ) { + let left_is_negative = SingleAddrVariable::new(self.allocate_register(), 1); + let left_abs_value = SingleAddrVariable::new(self.allocate_register(), left.bit_size); + + let right_is_negative = SingleAddrVariable::new(self.allocate_register(), 1); + let right_abs_value = SingleAddrVariable::new(self.allocate_register(), right.bit_size); + + let result_is_negative = SingleAddrVariable::new(self.allocate_register(), 1); + + // Compute both absolute values + self.absolute_value(left, left_abs_value, left_is_negative); + self.absolute_value(right, right_abs_value, right_is_negative); + + // Perform the division on the absolute values + self.binary_instruction( + left_abs_value, + right_abs_value, + result, + BrilligBinaryOp::UnsignedDiv, + ); + + // Compute result sign + self.binary_instruction( + left_is_negative, + right_is_negative, + result_is_negative, + BrilligBinaryOp::Xor, + ); + + // If result has to be negative, perform two's complement + self.codegen_if(result_is_negative.address, |ctx| { + let zero = ctx.make_constant_instruction(0_usize.into(), result.bit_size); + ctx.binary_instruction(zero, result, result, BrilligBinaryOp::Sub); + ctx.deallocate_single_addr(zero); + }); + + self.deallocate_single_addr(left_is_negative); + self.deallocate_single_addr(left_abs_value); + self.deallocate_single_addr(right_is_negative); + self.deallocate_single_addr(right_abs_value); + self.deallocate_single_addr(result_is_negative); + } } /// Special brillig context to codegen compiler intrinsic shared procedures @@ -296,12 +378,12 @@ pub(crate) mod tests { // We push a JumpIf and Trap opcode directly as the constrain instruction // uses unresolved jumps which requires a block to be constructed in SSA and // we don't need this for Brillig IR tests - context.push_opcode(BrilligOpcode::JumpIf { condition: r_equality, location: 9 }); context.push_opcode(BrilligOpcode::Const { destination: MemoryAddress::direct(0), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }); + context.push_opcode(BrilligOpcode::JumpIf { condition: r_equality, location: 9 }); context.push_opcode(BrilligOpcode::Trap { revert_data: HeapVector { pointer: MemoryAddress::direct(0), @@ -309,7 +391,10 @@ pub(crate) mod tests { }, }); - context.stop_instruction(); + context.stop_instruction(HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(0), + }); let bytecode: Vec> = context.artifact().finish().byte_code; let number_sequence: Vec = diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs index 40a133d5e38..0e5b72c0b85 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs @@ -180,17 +180,7 @@ impl BrilligArtifact { self.error_types.insert(*error_selector, error_type.clone()); } - let mut byte_code = obj.byte_code.clone(); - - // Replace STOP with RETURN because this is not the end of the program now. - let stop_position = byte_code - .iter() - .position(|opcode| matches!(opcode, BrilligOpcode::Stop { .. })) - .expect("Trying to link with a function that does not have a stop opcode"); - - byte_code[stop_position] = BrilligOpcode::Return; - - self.byte_code.append(&mut byte_code); + self.byte_code.append(&mut obj.byte_code.clone()); // Remove all resolved external calls and transform them to jumps let is_resolved = |label: &Label| self.labels.contains_key(label); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs index 777acfc4da3..da310873cff 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs @@ -73,6 +73,6 @@ impl BrilligContext { .iter() .for_each(|destination| self.registers.ensure_register_is_allocated(*destination)); self.codegen_mov_registers_to_registers(sources, destinations); - self.stop_instruction(); + self.return_instruction(); } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs index 77661fba3a1..9512a60e699 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs @@ -6,7 +6,7 @@ use acvm::{ AcirField, }; -use crate::ErrorType; +use crate::ssa::ir::instruction::ErrorType; use super::{ artifact::BrilligParameter, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs index 4e82a0d3af5..55a24264fbb 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs @@ -211,23 +211,14 @@ impl DebugShow { debug_println!(self.enable_debug_trace, " STORE *{} = {}", destination_pointer, source); } - /// Emits a stop instruction - pub(crate) fn stop_instruction(&self) { - debug_println!(self.enable_debug_trace, " STOP"); + /// Emits a return instruction + pub(crate) fn return_instruction(&self) { + debug_println!(self.enable_debug_trace, " RETURN"); } - /// Emits a external stop instruction (returns data) - pub(crate) fn external_stop_instruction( - &self, - return_data_offset: usize, - return_data_size: usize, - ) { - debug_println!( - self.enable_debug_trace, - " EXT_STOP {}..{}", - return_data_offset, - return_data_offset + return_data_size - ); + /// Emits a stop instruction + pub(crate) fn stop_instruction(&self, return_data: HeapVector) { + debug_println!(self.enable_debug_trace, " STOP {}", return_data); } /// Debug function for enter_context diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs index b78dcb09d9a..2dbee48b277 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs @@ -7,7 +7,10 @@ use super::{ registers::Stack, BrilligBinaryOp, BrilligContext, ReservedRegisters, }; -use acvm::acir::{brillig::MemoryAddress, AcirField}; +use acvm::acir::{ + brillig::{HeapVector, MemoryAddress}, + AcirField, +}; pub(crate) const MAX_STACK_SIZE: usize = 16 * MAX_STACK_FRAME_SIZE; pub(crate) const MAX_STACK_FRAME_SIZE: usize = 2048; @@ -363,7 +366,12 @@ impl BrilligContext { } } - self.external_stop_instruction(return_data_offset, return_data_size); + let return_data = HeapVector { + pointer: self.make_usize_constant_instruction(return_data_offset.into()).address, + size: self.make_usize_constant_instruction(return_data_size.into()).address, + }; + + self.stop_instruction(return_data); } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs index 873b47b8694..2bf5364414c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs @@ -257,20 +257,16 @@ impl BrilligContext< self.compute_section_label(self.current_section) } - /// Emits a stop instruction - pub(crate) fn stop_instruction(&mut self) { - self.debug_show.stop_instruction(); - self.push_opcode(BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }); + /// Emits a return instruction + pub(crate) fn return_instruction(&mut self) { + self.debug_show.return_instruction(); + self.push_opcode(BrilligOpcode::Return); } - /// Emits a external stop instruction (returns data) - pub(crate) fn external_stop_instruction( - &mut self, - return_data_offset: usize, - return_data_size: usize, - ) { - self.debug_show.external_stop_instruction(return_data_offset, return_data_size); - self.push_opcode(BrilligOpcode::Stop { return_data_offset, return_data_size }); + /// Emits a stop instruction with return data + pub(crate) fn stop_instruction(&mut self, return_data: HeapVector) { + self.debug_show.stop_instruction(return_data); + self.push_opcode(BrilligOpcode::Stop { return_data }); } /// Issues a blackbox operation. diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs index cbcf0543efb..2fa51f3db59 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs @@ -18,6 +18,7 @@ use noirc_errors::debug_info::ProcedureDebugId; use prepare_vector_insert::compile_prepare_vector_insert_procedure; use prepare_vector_push::compile_prepare_vector_push_procedure; use revert_with_string::compile_revert_with_string_procedure; +use serde::{Deserialize, Serialize}; use vector_copy::compile_vector_copy_procedure; use vector_pop_back::compile_vector_pop_back_procedure; use vector_pop_front::compile_vector_pop_front_procedure; @@ -34,7 +35,7 @@ use super::{ /// Procedures are a set of complex operations that are common in the noir language. /// Extracting them to reusable procedures allows us to reduce the size of the generated Brillig. /// Procedures receive their arguments on scratch space to avoid stack dumping&restoring. -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord, Deserialize, Serialize)] pub enum ProcedureId { ArrayCopy, ArrayReverse, @@ -138,7 +139,7 @@ pub(crate) fn compile_procedure( } }; - brillig_context.stop_instruction(); + brillig_context.return_instruction(); brillig_context.artifact() } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/lib.rs b/noir/noir-repo/compiler/noirc_evaluator/src/lib.rs index 3fddd9da056..b2b4762723f 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/lib.rs @@ -14,3 +14,21 @@ pub mod brillig; pub use ssa::create_program; pub use ssa::ir::instruction::ErrorType; + +/// Trims leading whitespace from each line of the input string, according to +/// how much leading whitespace there is on the first non-empty line. +#[cfg(test)] +pub(crate) fn trim_leading_whitespace_from_lines(src: &str) -> String { + let mut lines = src.trim_end().lines(); + let mut first_line = lines.next().unwrap(); + while first_line.is_empty() { + first_line = lines.next().unwrap(); + } + let indent = first_line.len() - first_line.trim_start().len(); + let mut result = first_line.trim_start().to_string(); + for line in lines { + result.push('\n'); + result.push_str(&line[indent..]); + } + result +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index 67d7ad70cbc..5e2c0f0827d 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -43,6 +43,7 @@ mod checks; pub(super) mod function_builder; pub mod ir; mod opt; +mod parser; pub mod ssa_gen; pub struct SsaEvaluatorOptions { @@ -370,8 +371,8 @@ fn split_public_and_private_inputs( func_sig .0 .iter() - .map(|(_, typ, visibility)| { - let num_field_elements_needed = typ.field_count() as usize; + .map(|(pattern, typ, visibility)| { + let num_field_elements_needed = typ.field_count(&pattern.location()) as usize; let witnesses = input_witnesses[idx..idx + num_field_elements_needed].to_vec(); idx += num_field_elements_needed; (visibility, witnesses) 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 b32d6d11f03..ecf7561321f 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 @@ -1009,13 +1009,13 @@ impl<'a> Context<'a> { }; entry_point.link_with(artifact); // Insert the range of opcode locations occupied by a procedure - if let Some(procedure_id) = artifact.procedure.clone() { + if let Some(procedure_id) = &artifact.procedure { let num_opcodes = entry_point.byte_code.len(); let previous_num_opcodes = entry_point.byte_code.len() - artifact.byte_code.len(); // We subtract one as to keep the range inclusive on both ends entry_point .procedure_locations - .insert(procedure_id, (previous_num_opcodes, num_opcodes - 1)); + .insert(procedure_id.clone(), (previous_num_opcodes, num_opcodes - 1)); } } // Generate the final bytecode diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs index de9ae8a24d7..5a62e9c8e9a 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs @@ -48,7 +48,7 @@ impl DataBusBuilder { ast::Visibility::CallData(id) => DatabusVisibility::CallData(id), ast::Visibility::ReturnData => DatabusVisibility::ReturnData, }; - let len = param.1.field_count() as usize; + let len = param.1.field_count(¶m.0.location()) as usize; params_is_databus.extend(vec![is_databus; len]); } params_is_databus diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index 7b39f7041e4..63a9453a430 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -328,6 +328,16 @@ impl FunctionBuilder { .first() } + pub(crate) fn insert_mutable_array_set( + &mut self, + array: ValueId, + index: ValueId, + value: ValueId, + ) -> ValueId { + self.insert_instruction(Instruction::ArraySet { array, index, value, mutable: true }, None) + .first() + } + /// Insert an instruction to increment an array's reference count. This only has an effect /// in unconstrained code where arrays are reference counted and copy on write. pub(crate) fn insert_inc_rc(&mut self, value: ValueId) { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs index d79916a9e11..2be9ffa9afa 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs @@ -74,8 +74,9 @@ pub(crate) struct DataFlowGraph { blocks: DenseMap, /// Debugging information about which `ValueId`s have had their underlying `Value` substituted - /// for that of another. This information is purely used for printing the SSA, and has no - /// material effect on the SSA itself. + /// for that of another. In theory this information is purely used for printing the SSA, + /// and has no material effect on the SSA itself, however in practice the IDs can get out of + /// sync and may need this resolution before they can be compared. #[serde(skip)] replaced_value_ids: HashMap, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs index 03262be0a06..487370488b9 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs @@ -281,15 +281,7 @@ impl Binary { let zero = dfg.make_constant(FieldElement::zero(), operand_type); return SimplifyResult::SimplifiedTo(zero); } - - // `two_pow_rhs` is limited to be at most `2 ^ {operand_bitsize - 1}` so it fits in `operand_type`. - let two_pow_rhs = FieldElement::from(2u128).pow(&rhs_const); - let two_pow_rhs = dfg.make_constant(two_pow_rhs, operand_type); - return SimplifyResult::SimplifiedToInstruction(Instruction::binary( - BinaryOp::Div, - self.lhs, - two_pow_rhs, - )); + return SimplifyResult::None; } } }; diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/printer.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/printer.rs index 93d69f255c3..3bbe14f866a 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/printer.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/printer.rs @@ -69,9 +69,16 @@ fn value(function: &Function, id: ValueId) -> String { } Value::Function(id) => id.to_string(), Value::Intrinsic(intrinsic) => intrinsic.to_string(), - Value::Array { array, .. } => { + Value::Array { array, typ } => { let elements = vecmap(array, |element| value(function, *element)); - format!("[{}]", elements.join(", ")) + let element_types = &typ.clone().element_types(); + let element_types_str = + element_types.iter().map(|typ| typ.to_string()).collect::>().join(", "); + if element_types.len() == 1 { + format!("[{}] of {}", elements.join(", "), element_types_str) + } else { + format!("[{}] of ({})", elements.join(", "), element_types_str) + } } Value::Param { .. } | Value::Instruction { .. } | Value::ForeignFunction(_) => { id.to_string() @@ -119,7 +126,11 @@ pub(crate) fn display_terminator( ) } Some(TerminatorInstruction::Return { return_values, .. }) => { - writeln!(f, " return {}", value_list(function, return_values)) + if return_values.is_empty() { + writeln!(f, " return") + } else { + writeln!(f, " return {}", value_list(function, return_values)) + } } None => writeln!(f, " (no terminator instruction)"), } @@ -139,12 +150,13 @@ pub(crate) fn display_instruction( write!(f, "{} = ", value_list(function, results))?; } - display_instruction_inner(function, &function.dfg[instruction], f) + display_instruction_inner(function, &function.dfg[instruction], results, f) } fn display_instruction_inner( function: &Function, instruction: &Instruction, + results: &[ValueId], f: &mut Formatter, ) -> Result { let show = |id| value(function, id); @@ -168,10 +180,15 @@ fn display_instruction_inner( } } Instruction::Call { func, arguments } => { - writeln!(f, "call {}({})", show(*func), value_list(function, arguments)) + let arguments = value_list(function, arguments); + writeln!(f, "call {}({}){}", show(*func), arguments, result_types(function, results)) + } + Instruction::Allocate => { + writeln!(f, "allocate{}", result_types(function, results)) + } + Instruction::Load { address } => { + writeln!(f, "load {}{}", show(*address), result_types(function, results)) } - Instruction::Allocate => writeln!(f, "allocate"), - Instruction::Load { address } => writeln!(f, "load {}", show(*address)), Instruction::Store { address, value } => { writeln!(f, "store {} at {}", show(*value), show(*address)) } @@ -179,7 +196,13 @@ fn display_instruction_inner( writeln!(f, "enable_side_effects {}", show(*condition)) } Instruction::ArrayGet { array, index } => { - writeln!(f, "array_get {}, index {}", show(*array), show(*index)) + writeln!( + f, + "array_get {}, index {}{}", + show(*array), + show(*index), + result_types(function, results) + ) } Instruction::ArraySet { array, index, value, mutable } => { let array = show(*array); @@ -210,6 +233,17 @@ fn display_instruction_inner( } } +fn result_types(function: &Function, results: &[ValueId]) -> String { + let types = vecmap(results, |result| function.dfg.type_of_value(*result).to_string()); + if types.is_empty() { + String::new() + } else if types.len() == 1 { + format!(" -> {}", types[0]) + } else { + format!(" -> ({})", types.join(", ")) + } +} + /// Tries to extract a constant string from an error payload. pub(crate) fn try_to_extract_string_from_error_payload( is_string_type: bool, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/types.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/types.rs index b7ee37ba17a..130f1d59e46 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/types.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/types.rs @@ -204,6 +204,17 @@ impl Type { Type::Slice(element_types) | Type::Array(element_types, _) => element_types[0].first(), } } + + /// True if this is a reference type or if it is a composite type which contains a reference. + pub(crate) fn contains_reference(&self) -> bool { + match self { + Type::Reference(_) => true, + Type::Numeric(_) | Type::Function => false, + Type::Array(elements, _) | Type::Slice(elements) => { + elements.iter().any(|elem| elem.contains_reference()) + } + } + } } /// Composite Types are essentially flattened struct or tuple types. @@ -218,7 +229,11 @@ impl std::fmt::Display for Type { Type::Reference(element) => write!(f, "&mut {element}"), Type::Array(element, length) => { let elements = vecmap(element.iter(), |element| element.to_string()); - write!(f, "[{}; {length}]", elements.join(", ")) + if elements.len() == 1 { + write!(f, "[{}; {length}]", elements.join(", ")) + } else { + write!(f, "[({}); {length}]", elements.join(", ")) + } } Type::Slice(element) => { let elements = vecmap(element.iter(), |element| element.to_string()); 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 7035345436e..ed3accae15a 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 @@ -186,135 +186,47 @@ fn make_mutable( #[cfg(test)] mod tests { - use std::sync::Arc; - - use im::vector; - use noirc_frontend::monomorphization::ast::InlineType; - - use crate::ssa::{ - function_builder::FunctionBuilder, - ir::{ - function::RuntimeType, - instruction::{BinaryOp, Instruction}, - map::Id, - types::Type, - }, - }; + use crate::ssa::{opt::assert_normalized_ssa_equals, Ssa}; #[test] fn array_set_in_loop_with_conditional_clone() { // We want to make sure that we do not mark a single array set mutable which is loaded // from and cloned in a loop. If the array is inadvertently marked mutable, and is cloned in a previous iteration // of the loop, its clone will also be altered. - // - // brillig fn main f0 { - // b0(): - // v3 = allocate - // store [[Field 0, Field 0, Field 0, Field 0, Field 0], [Field 0, Field 0, Field 0, Field 0, Field 0]] at v3 - // v4 = allocate - // store [[Field 0, Field 0, Field 0, Field 0, Field 0], [Field 0, Field 0, Field 0, Field 0, Field 0]] at v4 - // jmp b1(u32 0) - // b1(v6: u32): - // v8 = lt v6, u32 5 - // jmpif v8 then: b3, else: b2 - // b3(): - // v9 = eq v6, u32 5 - // jmpif v9 then: b4, else: b5 - // b4(): - // v10 = load v3 - // store v10 at v4 - // jmp b5() - // b5(): - // v11 = load v3 - // v13 = array_get v11, index Field 0 - // v14 = array_set v13, index v6, value Field 20 - // v15 = array_set v11, index v6, value v14 - // store v15 at v3 - // v17 = add v6, u32 1 - // jmp b1(v17) - // b2(): - // return - // } - let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id); - builder.set_runtime(RuntimeType::Brillig(InlineType::default())); - - let array_type = Type::Array(Arc::new(vec![Type::field()]), 5); - let zero = builder.field_constant(0u128); - let array_constant = - builder.array_constant(vector![zero, zero, zero, zero, zero], array_type.clone()); - let nested_array_type = Type::Array(Arc::new(vec![array_type.clone()]), 2); - let nested_array_constant = builder - .array_constant(vector![array_constant, array_constant], nested_array_type.clone()); - - let v3 = builder.insert_allocate(array_type.clone()); - - builder.insert_store(v3, nested_array_constant); - - let v4 = builder.insert_allocate(array_type.clone()); - builder.insert_store(v4, nested_array_constant); - - let b1 = builder.insert_block(); - let zero_u32 = builder.numeric_constant(0u128, Type::unsigned(32)); - builder.terminate_with_jmp(b1, vec![zero_u32]); - - // Loop header - builder.switch_to_block(b1); - let v5 = builder.add_block_parameter(b1, Type::unsigned(32)); - let five = builder.numeric_constant(5u128, Type::unsigned(32)); - let v8 = builder.insert_binary(v5, BinaryOp::Lt, five); - - let b2 = builder.insert_block(); - let b3 = builder.insert_block(); - let b4 = builder.insert_block(); - let b5 = builder.insert_block(); - builder.terminate_with_jmpif(v8, b3, b2); - - // Loop body - // b3 is the if statement conditional - builder.switch_to_block(b3); - let two = builder.numeric_constant(5u128, Type::unsigned(32)); - let v9 = builder.insert_binary(v5, BinaryOp::Eq, two); - builder.terminate_with_jmpif(v9, b4, b5); - - // b4 is the rest of the loop after the if statement - builder.switch_to_block(b4); - let v10 = builder.insert_load(v3, nested_array_type.clone()); - builder.insert_store(v4, v10); - builder.terminate_with_jmp(b5, vec![]); - - builder.switch_to_block(b5); - let v11 = builder.insert_load(v3, nested_array_type.clone()); - let twenty = builder.field_constant(20u128); - let v13 = builder.insert_array_get(v11, zero, array_type.clone()); - let v14 = builder.insert_array_set(v13, v5, twenty); - let v15 = builder.insert_array_set(v11, v5, v14); - - builder.insert_store(v3, v15); - let one = builder.numeric_constant(1u128, Type::unsigned(32)); - let v17 = builder.insert_binary(v5, BinaryOp::Add, one); - builder.terminate_with_jmp(b1, vec![v17]); - - builder.switch_to_block(b2); - builder.terminate_with_return(vec![]); + let src = " + brillig(inline) fn main f0 { + b0(): + v1 = allocate -> &mut [Field; 5] + store [[Field 0, Field 0, Field 0, Field 0, Field 0] of Field, [Field 0, Field 0, Field 0, Field 0, Field 0] of Field] of [Field; 5] at v1 + v6 = allocate -> &mut [Field; 5] + store [[Field 0, Field 0, Field 0, Field 0, Field 0] of Field, [Field 0, Field 0, Field 0, Field 0, Field 0] of Field] of [Field; 5] at v6 + jmp b1(u32 0) + b1(v0: u32): + v12 = lt v0, u32 5 + jmpif v12 then: b3, else: b2 + b3(): + v13 = eq v0, u32 5 + jmpif v13 then: b4, else: b5 + b4(): + v14 = load v1 -> [[Field; 5]; 2] + store v14 at v6 + jmp b5() + b5(): + v15 = load v1 -> [[Field; 5]; 2] + v16 = array_get v15, index Field 0 -> [Field; 5] + v18 = array_set v16, index v0, value Field 20 + v19 = array_set v15, index v0, value v18 + store v19 at v1 + v21 = add v0, u32 1 + jmp b1(v21) + b2(): + return + } + "; + let ssa = Ssa::from_str(src).unwrap(); - let ssa = builder.finish(); // We expect the same result as above let ssa = ssa.array_set_optimization(); - - let main = ssa.main(); - assert_eq!(main.reachable_blocks().len(), 6); - - let array_set_instructions = main.dfg[b5] - .instructions() - .iter() - .filter(|instruction| matches!(&main.dfg[**instruction], Instruction::ArraySet { .. })) - .collect::>(); - - assert_eq!(array_set_instructions.len(), 2); - if let Instruction::ArraySet { mutable, .. } = &main.dfg[*array_set_instructions[0]] { - // The single array set should not be marked mutable - assert!(!mutable); - } + assert_normalized_ssa_equals(ssa, src); } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/as_slice_length.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/as_slice_length.rs index 59917e8589b..76705dcc9db 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/as_slice_length.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/as_slice_length.rs @@ -75,3 +75,34 @@ fn replace_known_slice_lengths( func.dfg.set_value_from_id(original_slice_length, known_length); }); } + +#[cfg(test)] +mod test { + use crate::ssa::opt::assert_normalized_ssa_equals; + + use super::Ssa; + + #[test] + fn as_slice_length_optimization() { + // In this code we expect `return v2` to be replaced with `return u32 3` because + // that's the length of the v0 array. + let src = " + acir(inline) fn main f0 { + b0(v0: [Field; 3]): + v2, v3 = call as_slice(v0) -> (u32, [Field]) + return v2 + } + "; + let ssa = Ssa::from_str(src).unwrap(); + + let expected = " + acir(inline) fn main f0 { + b0(v0: [Field; 3]): + v2, v3 = call as_slice(v0) -> (u32, [Field]) + return u32 3 + } + "; + let ssa = ssa.as_slice_optimization(); + assert_normalized_ssa_equals(ssa, expected); + } +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs index 3b86ded4a87..b5ab688cb2c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs @@ -317,531 +317,305 @@ mod test { use crate::ssa::{ function_builder::FunctionBuilder, - ir::{ - instruction::{Binary, BinaryOp, Instruction, TerminatorInstruction}, - map::Id, - types::Type, - value::{Value, ValueId}, - }, + ir::{map::Id, types::Type}, + opt::assert_normalized_ssa_equals, + Ssa, }; - use acvm::{acir::AcirField, FieldElement}; #[test] fn simple_constant_fold() { - // fn main f0 { - // b0(v0: Field): - // v1 = add v0, Field 1 - // v2 = mul v1, Field 3 - // return v2 - // } - // // After constructing this IR, we set the value of v0 to 2. // The expected return afterwards should be 9. - 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::Mul, three); - builder.terminate_with_return(vec![v2]); - - let mut ssa = builder.finish(); + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + v1 = add v0, Field 1 + v2 = mul v1, Field 3 + return v2 + } + "; + let mut ssa = Ssa::from_str(src).unwrap(); let main = ssa.main_mut(); + let instructions = main.dfg[main.entry_block()].instructions(); assert_eq!(instructions.len(), 2); // The final return is not counted - // Expected output: - // - // fn main f0 { - // b0(Field 2: Field): - // return Field 9 - // } + let v0 = main.parameters()[0]; + let two = main.dfg.make_constant(2_u128.into(), Type::field()); + main.dfg.set_value_from_id(v0, two); - let ssa = ssa.fold_constants(); - let main = ssa.main(); - let block = &main.dfg[main.entry_block()]; - assert_eq!(block.instructions().len(), 0); - - match block.terminator() { - Some(TerminatorInstruction::Return { return_values, .. }) => { - let value = main - .dfg - .get_numeric_constant(return_values[0]) - .expect("Expected constant 9") - .to_u128(); - assert_eq!(value, 9); + let expected = " + acir(inline) fn main f0 { + b0(v0: Field): + return Field 9 } - _ => unreachable!("b0 should have a return terminator"), - } + "; + let ssa = ssa.fold_constants(); + assert_normalized_ssa_equals(ssa, expected); } #[test] fn redundant_truncation() { - // fn main f0 { - // b0(v0: u16, v1: u16): - // v2 = div v0, v1 - // v3 = truncate v2 to 8 bits, max_bit_size: 16 - // return v3 - // } - // // After constructing this IR, we set the value of v1 to 2^8. // The expected return afterwards should be v2. - let main_id = Id::test_new(0); - - // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id); - let v0 = builder.add_parameter(Type::unsigned(16)); - let v1 = builder.add_parameter(Type::unsigned(16)); - - // Note that this constant guarantees that `v0/constant < 2^8`. We then do not need to truncate the result. - let constant = 2_u128.pow(8); - let constant = builder.numeric_constant(constant, Type::field()); - - let v2 = builder.insert_binary(v0, BinaryOp::Div, v1); - let v3 = builder.insert_truncate(v2, 8, 16); - builder.terminate_with_return(vec![v3]); - - let mut ssa = builder.finish(); + let src = " + acir(inline) fn main f0 { + b0(v0: u16, v1: u16): + v2 = div v0, v1 + v3 = truncate v2 to 8 bits, max_bit_size: 16 + return v3 + } + "; + let mut ssa = Ssa::from_str(src).unwrap(); let main = ssa.main_mut(); + let instructions = main.dfg[main.entry_block()].instructions(); assert_eq!(instructions.len(), 2); // The final return is not counted - // Expected output: - // - // fn main f0 { - // b0(Field 2: Field): - // return Field 9 - // } - main.dfg.set_value_from_id(v1, constant); + let v1 = main.parameters()[1]; - let ssa = ssa.fold_constants(); - let main = ssa.main(); + // Note that this constant guarantees that `v0/constant < 2^8`. We then do not need to truncate the result. + let constant = 2_u128.pow(8); + let constant = main.dfg.make_constant(constant.into(), Type::unsigned(16)); - println!("{ssa}"); + main.dfg.set_value_from_id(v1, constant); - let instructions = main.dfg[main.entry_block()].instructions(); - assert_eq!(instructions.len(), 1); - let instruction = &main.dfg[instructions[0]]; + let expected = " + acir(inline) fn main f0 { + b0(v0: u16, v1: u16): + v3 = div v0, u16 256 + return v3 + } + "; - assert_eq!( - instruction, - &Instruction::Binary(Binary { lhs: v0, operator: BinaryOp::Div, rhs: constant }) - ); + let ssa = ssa.fold_constants(); + assert_normalized_ssa_equals(ssa, expected); } #[test] fn non_redundant_truncation() { - // fn main f0 { - // b0(v0: u16, v1: u16): - // v2 = div v0, v1 - // v3 = truncate v2 to 8 bits, max_bit_size: 16 - // return v3 - // } - // // After constructing this IR, we set the value of v1 to 2^8 - 1. // This should not result in the truncation being removed. - let main_id = Id::test_new(0); + let src = " + acir(inline) fn main f0 { + b0(v0: u16, v1: u16): + v2 = div v0, v1 + v3 = truncate v2 to 8 bits, max_bit_size: 16 + return v3 + } + "; + let mut ssa = Ssa::from_str(src).unwrap(); + let main = ssa.main_mut(); - // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id); - let v0 = builder.add_parameter(Type::unsigned(16)); - let v1 = builder.add_parameter(Type::unsigned(16)); + let instructions = main.dfg[main.entry_block()].instructions(); + assert_eq!(instructions.len(), 2); // The final return is not counted + + let v1 = main.parameters()[1]; // Note that this constant does not guarantee that `v0/constant < 2^8`. We must then truncate the result. let constant = 2_u128.pow(8) - 1; - let constant = builder.numeric_constant(constant, Type::field()); - - let v2 = builder.insert_binary(v0, BinaryOp::Div, v1); - let v3 = builder.insert_truncate(v2, 8, 16); - builder.terminate_with_return(vec![v3]); - - let mut ssa = builder.finish(); - let main = ssa.main_mut(); - let instructions = main.dfg[main.entry_block()].instructions(); - assert_eq!(instructions.len(), 2); // The final return is not counted + let constant = main.dfg.make_constant(constant.into(), Type::unsigned(16)); - // Expected output: - // - // fn main f0 { - // b0(v0: u16, Field 255: Field): - // v6 = div v0, Field 255 - // v7 = truncate v6 to 8 bits, max_bit_size: 16 - // return v7 - // } main.dfg.set_value_from_id(v1, constant); - let ssa = ssa.fold_constants(); - let main = ssa.main(); - - let instructions = main.dfg[main.entry_block()].instructions(); - assert_eq!(instructions.len(), 2); + let expected = " + acir(inline) fn main f0 { + b0(v0: u16, v1: u16): + v3 = div v0, u16 255 + v4 = truncate v3 to 8 bits, max_bit_size: 16 + return v4 + } + "; - assert_eq!( - &main.dfg[instructions[0]], - &Instruction::Binary(Binary { lhs: v0, operator: BinaryOp::Div, rhs: constant }) - ); - assert_eq!( - &main.dfg[instructions[1]], - &Instruction::Truncate { value: ValueId::test_new(6), bit_size: 8, max_bit_size: 16 } - ); + let ssa = ssa.fold_constants(); + assert_normalized_ssa_equals(ssa, expected); } #[test] fn arrays_elements_are_updated() { - // fn main f0 { - // b0(v0: Field): - // v1 = add v0, Field 1 - // return [v1] - // } - // // After constructing this IR, we run constant folding with no expected benefit, but to // ensure that all new values ids are correctly propagated. - 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 v1 = builder.insert_binary(v0, BinaryOp::Add, one); - - let array_type = Type::Array(Arc::new(vec![Type::field()]), 1); - let arr = builder.current_function.dfg.make_array(vec![v1].into(), array_type); - builder.terminate_with_return(vec![arr]); - - let ssa = builder.finish().fold_constants(); - let main = ssa.main(); - let entry_block_id = main.entry_block(); - let entry_block = &main.dfg[entry_block_id]; - assert_eq!(entry_block.instructions().len(), 1); - let new_add_instr = entry_block.instructions().first().unwrap(); - let new_add_instr_result = main.dfg.instruction_results(*new_add_instr)[0]; - assert_ne!(new_add_instr_result, v1); - - let return_value_id = match entry_block.unwrap_terminator() { - TerminatorInstruction::Return { return_values, .. } => return_values[0], - _ => unreachable!("Should have terminator instruction"), - }; - let return_element = match &main.dfg[return_value_id] { - Value::Array { array, .. } => array[0], - _ => unreachable!("Return type should be array"), - }; - // The return element is expected to refer to the new add instruction result. - assert_eq!(main.dfg.resolve(new_add_instr_result), main.dfg.resolve(return_element)); + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + v2 = add v0, Field 1 + return [v2] of Field + } + "; + let ssa = Ssa::from_str(src).unwrap(); + let ssa = ssa.fold_constants(); + assert_normalized_ssa_equals(ssa, src); } #[test] fn instruction_deduplication() { - // fn main f0 { - // b0(v0: u16): - // v1 = cast v0 as u32 - // v2 = cast v0 as u32 - // constrain v1 v2 - // } - // // After constructing this IR, we run constant folding which should replace the second cast // with a reference to the results to the first. This then allows us to optimize away // the constrain instruction as both inputs are known to be equal. // // The first cast instruction is retained and will be removed in the dead instruction elimination pass. - let main_id = Id::test_new(0); - - // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id); - let v0 = builder.add_parameter(Type::unsigned(16)); - - let v1 = builder.insert_cast(v0, Type::unsigned(32)); - let v2 = builder.insert_cast(v0, Type::unsigned(32)); - builder.insert_constrain(v1, v2, None); - - let mut ssa = builder.finish(); - let main = ssa.main_mut(); - let instructions = main.dfg[main.entry_block()].instructions(); - assert_eq!(instructions.len(), 3); - - // Expected output: - // - // fn main f0 { - // b0(v0: u16): - // v1 = cast v0 as u32 - // } + let src = " + acir(inline) fn main f0 { + b0(v0: u16): + v1 = cast v0 as u32 + v2 = cast v0 as u32 + constrain v1 == v2 + return + } + "; + let expected = " + acir(inline) fn main f0 { + b0(v0: u16): + v1 = cast v0 as u32 + return + } + "; + let ssa = Ssa::from_str(src).unwrap(); let ssa = ssa.fold_constants(); - let main = ssa.main(); - let instructions = main.dfg[main.entry_block()].instructions(); - - assert_eq!(instructions.len(), 1); - let instruction = &main.dfg[instructions[0]]; - - assert_eq!(instruction, &Instruction::Cast(v0, Type::unsigned(32))); + assert_normalized_ssa_equals(ssa, expected); } #[test] fn constant_index_array_access_deduplication() { - // fn main f0 { - // b0(v0: [Field; 4], v1: u32, v2: bool, v3: bool): - // enable_side_effects v2 - // v4 = array_get v0 u32 0 - // v5 = array_get v0 v1 - // enable_side_effects v3 - // v6 = array_get v0 u32 0 - // v7 = array_get v0 v1 - // constrain v4 v6 - // } - // // After constructing this IR, we run constant folding which should replace the second constant-index array get // with a reference to the results to the first. This then allows us to optimize away // the constrain instruction as both inputs are known to be equal. - // - let main_id = Id::test_new(0); - - // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id); - - let v0 = builder.add_parameter(Type::Array(Arc::new(vec![Type::field()]), 4)); - let v1 = builder.add_parameter(Type::unsigned(32)); - let v2 = builder.add_parameter(Type::unsigned(1)); - let v3 = builder.add_parameter(Type::unsigned(1)); - - let zero = builder.numeric_constant(FieldElement::zero(), Type::length_type()); - - builder.insert_enable_side_effects_if(v2); - let v4 = builder.insert_array_get(v0, zero, Type::field()); - let _v5 = builder.insert_array_get(v0, v1, Type::field()); - - builder.insert_enable_side_effects_if(v3); - let v6 = builder.insert_array_get(v0, zero, Type::field()); - let _v7 = builder.insert_array_get(v0, v1, Type::field()); - - builder.insert_constrain(v4, v6, None); - - let ssa = builder.finish(); - - println!("{ssa}"); - - let main = ssa.main(); - let instructions = main.dfg[main.entry_block()].instructions(); - assert_eq!(instructions.len(), 7); + let src = " + acir(inline) fn main f0 { + b0(v0: [Field; 4], v1: u32, v2: bool, v3: bool): + enable_side_effects v2 + v4 = array_get v0, index u32 0 -> Field + v5 = array_get v0, index v1 -> Field + enable_side_effects v3 + v6 = array_get v0, index u32 0 -> Field + v7 = array_get v0, index v1 -> Field + constrain v4 == v6 + return + } + "; + let expected = " + acir(inline) fn main f0 { + b0(v0: [Field; 4], v1: u32, v2: u1, v3: u1): + enable_side_effects v2 + v5 = array_get v0, index u32 0 -> Field + v6 = array_get v0, index v1 -> Field + enable_side_effects v3 + v7 = array_get v0, index v1 -> Field + return + } + "; - // Expected output: - // - // fn main f0 { - // b0(v0: [Field; 4], v1: u32, v2: bool, v3: bool): - // enable_side_effects v2 - // v10 = array_get v0 u32 0 - // v11 = array_get v0 v1 - // enable_side_effects v3 - // v12 = array_get v0 v1 - // } + let ssa = Ssa::from_str(src).unwrap(); let ssa = ssa.fold_constants(); - - println!("{ssa}"); - - let main = ssa.main(); - let instructions = main.dfg[main.entry_block()].instructions(); - - assert_eq!(instructions.len(), 5); + assert_normalized_ssa_equals(ssa, expected); } #[test] fn constraint_decomposition() { - // fn main f0 { - // b0(v0: u1, v1: u1, v2: u1): - // v3 = mul v0 v1 - // v4 = not v2 - // v5 = mul v3 v4 - // constrain v4 u1 1 - // } - // // When constructing this IR, we should automatically decompose the constraint to be in terms of `v0`, `v1` and `v2`. // // The mul instructions are retained and will be removed in the dead instruction elimination pass. - let main_id = Id::test_new(0); - - // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id); - let v0 = builder.add_parameter(Type::bool()); - let v1 = builder.add_parameter(Type::bool()); - let v2 = builder.add_parameter(Type::bool()); - - let v3 = builder.insert_binary(v0, BinaryOp::Mul, v1); - let v4 = builder.insert_not(v2); - let v5 = builder.insert_binary(v3, BinaryOp::Mul, v4); - - // This constraint is automatically decomposed when it is inserted. - let v_true = builder.numeric_constant(true, Type::bool()); - builder.insert_constrain(v5, v_true, None); - - let v_false = builder.numeric_constant(false, Type::bool()); - - // Expected output: - // - // fn main f0 { - // b0(v0: u1, v1: u1, v2: u1): - // v3 = mul v0 v1 - // v4 = not v2 - // v5 = mul v3 v4 - // constrain v0 u1 1 - // constrain v1 u1 1 - // constrain v2 u1 0 - // } - - let ssa = builder.finish(); - let main = ssa.main(); - let instructions = main.dfg[main.entry_block()].instructions(); - - assert_eq!(instructions.len(), 6); - - assert_eq!( - main.dfg[instructions[0]], - Instruction::Binary(Binary { lhs: v0, operator: BinaryOp::Mul, rhs: v1 }) - ); - assert_eq!(main.dfg[instructions[1]], Instruction::Not(v2)); - assert_eq!( - main.dfg[instructions[2]], - Instruction::Binary(Binary { lhs: v3, operator: BinaryOp::Mul, rhs: v4 }) - ); - assert_eq!(main.dfg[instructions[3]], Instruction::Constrain(v0, v_true, None)); - assert_eq!(main.dfg[instructions[4]], Instruction::Constrain(v1, v_true, None)); - assert_eq!(main.dfg[instructions[5]], Instruction::Constrain(v2, v_false, None)); + let src = " + acir(inline) fn main f0 { + b0(v0: u1, v1: u1, v2: u1): + v3 = mul v0, v1 + v4 = not v2 + v5 = mul v3, v4 + constrain v5 == u1 1 + return + } + "; + let ssa = Ssa::from_str(src).unwrap(); + + let expected = " + acir(inline) fn main f0 { + b0(v0: u1, v1: u1, v2: u1): + v3 = mul v0, v1 + v4 = not v2 + v5 = mul v3, v4 + constrain v0 == u1 1 + constrain v1 == u1 1 + constrain v2 == u1 0 + return + } + "; + assert_normalized_ssa_equals(ssa, expected); } // Regression for #4600 #[test] fn array_get_regression() { - // fn main f0 { - // b0(v0: u1, v1: u64): - // enable_side_effects_if v0 - // v2 = array_get [Field 0, Field 1], index v1 - // v3 = not v0 - // enable_side_effects_if v3 - // v4 = array_get [Field 0, Field 1], index v1 - // } - // // We want to make sure after constant folding both array_gets remain since they are // under different enable_side_effects_if contexts and thus one may be disabled while // the other is not. If one is removed, it is possible e.g. v4 is replaced with v2 which // is disabled (only gets from index 0) and thus returns the wrong result. - let main_id = Id::test_new(0); - - // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id); - let v0 = builder.add_parameter(Type::bool()); - let v1 = builder.add_parameter(Type::unsigned(64)); - - builder.insert_enable_side_effects_if(v0); - - let zero = builder.field_constant(0u128); - let one = builder.field_constant(1u128); - - let typ = Type::Array(Arc::new(vec![Type::field()]), 2); - let array = builder.array_constant(vec![zero, one].into(), typ); - - let _v2 = builder.insert_array_get(array, v1, Type::field()); - let v3 = builder.insert_not(v0); - - builder.insert_enable_side_effects_if(v3); - let _v4 = builder.insert_array_get(array, v1, Type::field()); + let src = " + acir(inline) fn main f0 { + b0(v0: u1, v1: u64): + enable_side_effects v0 + v5 = array_get [Field 0, Field 1] of Field, index v1 -> Field + v6 = not v0 + enable_side_effects v6 + v8 = array_get [Field 0, Field 1] of Field, index v1 -> Field + return + } + "; + let ssa = Ssa::from_str(src).unwrap(); // Expected output is unchanged - let ssa = builder.finish(); - let main = ssa.main(); - let instructions = main.dfg[main.entry_block()].instructions(); - let starting_instruction_count = instructions.len(); - assert_eq!(starting_instruction_count, 5); - let ssa = ssa.fold_constants(); - let main = ssa.main(); - let instructions = main.dfg[main.entry_block()].instructions(); - let ending_instruction_count = instructions.len(); - assert_eq!(starting_instruction_count, ending_instruction_count); + assert_normalized_ssa_equals(ssa, src); } #[test] fn deduplicate_instructions_with_predicates() { - // fn main f0 { - // b0(v0: bool, v1: bool, v2: [u32; 2]): - // enable_side_effects v0 - // v3 = array_get v2, index u32 0 - // v4 = array_set v2, index u32 1, value: u32 2 - // v5 = array_get v4, index u32 0 - // constrain_eq v3, v5 - // enable_side_effects v1 - // v6 = array_get v2, index u32 0 - // v7 = array_set v2, index u32 1, value: u32 2 - // v8 = array_get v7, index u32 0 - // constrain_eq v6, v8 - // enable_side_effects v0 - // v9 = array_get v2, index u32 0 - // v10 = array_set v2, index u32 1, value: u32 2 - // v11 = array_get v10, index u32 0 - // constrain_eq v9, v11 - // } - let main_id = Id::test_new(0); - - // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id); - - let v0 = builder.add_parameter(Type::bool()); - let v1 = builder.add_parameter(Type::bool()); - let v2 = builder.add_parameter(Type::Array(Arc::new(vec![Type::field()]), 2)); - - let zero = builder.numeric_constant(0u128, Type::length_type()); - let one = builder.numeric_constant(1u128, Type::length_type()); - let two = builder.numeric_constant(2u128, Type::length_type()); - - builder.insert_enable_side_effects_if(v0); - let v3 = builder.insert_array_get(v2, zero, Type::length_type()); - let v4 = builder.insert_array_set(v2, one, two); - let v5 = builder.insert_array_get(v4, zero, Type::length_type()); - builder.insert_constrain(v3, v5, None); - - builder.insert_enable_side_effects_if(v1); - let v6 = builder.insert_array_get(v2, zero, Type::length_type()); - let v7 = builder.insert_array_set(v2, one, two); - let v8 = builder.insert_array_get(v7, zero, Type::length_type()); - builder.insert_constrain(v6, v8, None); - - // We expect all these instructions after the 'enable side effects' instruction to be removed. - builder.insert_enable_side_effects_if(v0); - let v9 = builder.insert_array_get(v2, zero, Type::length_type()); - let v10 = builder.insert_array_set(v2, one, two); - let v11 = builder.insert_array_get(v10, zero, Type::length_type()); - builder.insert_constrain(v9, v11, None); - - let ssa = builder.finish(); - println!("{ssa}"); + let src = " + acir(inline) fn main f0 { + b0(v0: u1, v1: u1, v2: [Field; 2]): + enable_side_effects v0 + v6 = array_get v2, index u32 0 -> u32 + v7 = array_set v2, index u32 1, value u32 2 + v8 = array_get v7, index u32 0 -> u32 + constrain v6 == v8 + enable_side_effects v1 + v9 = array_get v2, index u32 0 -> u32 + v10 = array_set v2, index u32 1, value u32 2 + v11 = array_get v10, index u32 0 -> u32 + constrain v9 == v11 + enable_side_effects v0 + v12 = array_get v2, index u32 0 -> u32 + v13 = array_set v2, index u32 1, value u32 2 + v14 = array_get v13, index u32 0 -> u32 + constrain v12 == v14 + return + } + "; + let ssa = Ssa::from_str(src).unwrap(); let main = ssa.main(); let instructions = main.dfg[main.entry_block()].instructions(); assert_eq!(instructions.len(), 15); - // Expected output: - // - // fn main f0 { - // b0(v0: bool, v1: bool, v2: [Field; 2]): - // enable_side_effects v0 - // v3 = array_get v2, index Field 0 - // v4 = array_set v2, index Field 1, value: Field 2 - // v5 = array_get v4, index Field 0 - // constrain_eq v3, v5 - // enable_side_effects v1 - // v7 = array_set v2, index Field 1, value: Field 2 - // v8 = array_get v7, index Field 0 - // constrain_eq v3, v8 - // enable_side_effects v0 - // } - let ssa = ssa.fold_constants_using_constraints(); - println!("{ssa}"); + let expected = " + acir(inline) fn main f0 { + b0(v0: u1, v1: u1, v2: [Field; 2]): + enable_side_effects v0 + v4 = array_get v2, index u32 0 -> u32 + v7 = array_set v2, index u32 1, value u32 2 + v8 = array_get v7, index u32 0 -> u32 + constrain v4 == v8 + enable_side_effects v1 + v9 = array_set v2, index u32 1, value u32 2 + v10 = array_get v9, index u32 0 -> u32 + constrain v4 == v10 + enable_side_effects v0 + return + } + "; - let main = ssa.main(); - let instructions = main.dfg[main.entry_block()].instructions(); - assert_eq!(instructions.len(), 10); + let ssa = ssa.fold_constants_using_constraints(); + assert_normalized_ssa_equals(ssa, expected); } // This test currently fails. It being fixed will address the issue https://github.com/noir-lang/noir/issues/5756 @@ -878,7 +652,8 @@ mod test { let _v10 = builder.insert_call(keccakf1600, vec![array1], vec![typ.clone()]); let _v11 = builder.insert_call(keccakf1600, vec![array2], vec![typ.clone()]); - let ssa = builder.finish(); + let mut ssa = builder.finish(); + ssa.normalize_ids(); println!("{ssa}"); 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 beca7c41e5c..f28b076a5f9 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 @@ -3,6 +3,7 @@ use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; use im::Vector; use noirc_errors::Location; +use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator}; use crate::ssa::{ ir::{ @@ -24,9 +25,8 @@ impl Ssa { /// unused results. #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn dead_instruction_elimination(mut self) -> Ssa { - for function in self.functions.values_mut() { - function.dead_instruction_elimination(true); - } + self.functions.par_iter_mut().for_each(|(_, func)| func.dead_instruction_elimination(true)); + self } } @@ -622,210 +622,118 @@ mod test { use crate::ssa::{ function_builder::FunctionBuilder, - ir::{ - instruction::{BinaryOp, Instruction, Intrinsic}, - map::Id, - types::Type, - }, + ir::{instruction::Instruction, map::Id, types::Type}, + opt::assert_normalized_ssa_equals, + Ssa, }; #[test] fn dead_instruction_elimination() { - // fn main f0 { - // b0(v0: Field): - // v1 = add v0, Field 1 - // v2 = add v0, Field 2 - // jmp b1(v2) - // b1(v3: Field): - // v4 = allocate 1 field - // v5 = load v4 - // v6 = allocate 1 field - // store Field 1 in v6 - // v7 = load v6 - // v8 = add v7, Field 1 - // v9 = add v7, Field 2 - // v10 = add v7, Field 3 - // v11 = add v10, v10 - // call assert_constant(v8) - // return v9 - // } - 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 b1 = builder.insert_block(); - - 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(v0, BinaryOp::Add, two); - builder.terminate_with_jmp(b1, vec![v2]); - - builder.switch_to_block(b1); - let _v3 = builder.add_block_parameter(b1, Type::field()); - - let v4 = builder.insert_allocate(Type::field()); - let _v5 = builder.insert_load(v4, Type::field()); - - let v6 = builder.insert_allocate(Type::field()); - builder.insert_store(v6, one); - let v7 = builder.insert_load(v6, Type::field()); - let v8 = builder.insert_binary(v7, BinaryOp::Add, one); - let v9 = builder.insert_binary(v7, BinaryOp::Add, two); - let v10 = builder.insert_binary(v7, BinaryOp::Add, three); - let _v11 = builder.insert_binary(v10, BinaryOp::Add, v10); - - let assert_constant_id = builder.import_intrinsic_id(Intrinsic::AssertConstant); - builder.insert_call(assert_constant_id, vec![v8], vec![]); - builder.terminate_with_return(vec![v9]); - - let ssa = builder.finish(); - let main = ssa.main(); - - // The instruction count never includes the terminator instruction - assert_eq!(main.dfg[main.entry_block()].instructions().len(), 2); - assert_eq!(main.dfg[b1].instructions().len(), 10); - - // Expected output: - // - // fn main f0 { - // b0(v0: Field): - // v2 = add v0, Field 2 - // jmp b1(v2) - // b1(v3: Field): - // v6 = allocate 1 field - // store Field 1 in v6 - // v7 = load v6 - // v8 = add v7, Field 1 - // v9 = add v7, Field 2 - // call assert_constant(v8) - // return v9 - // } + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + v3 = add v0, Field 1 + v5 = add v0, Field 2 + jmp b1(v5) + b1(v1: Field): + v6 = allocate -> &mut Field + v7 = load v6 -> Field + v8 = allocate -> &mut Field + store Field 1 at v8 + v9 = load v8 -> Field + v10 = add v9, Field 1 + v11 = add v9, Field 2 + v13 = add v9, Field 3 + v14 = add v13, v13 + call assert_constant(v10) + return v11 + } + "; + let ssa = Ssa::from_str(src).unwrap(); + + let expected = " + acir(inline) fn main f0 { + b0(v0: Field): + v3 = add v0, Field 2 + jmp b1(v3) + b1(v1: Field): + v4 = allocate -> &mut Field + store Field 1 at v4 + v6 = load v4 -> Field + v7 = add v6, Field 1 + v8 = add v6, Field 2 + call assert_constant(v7) + return v8 + } + "; let ssa = ssa.dead_instruction_elimination(); - let main = ssa.main(); - - assert_eq!(main.dfg[main.entry_block()].instructions().len(), 1); - assert_eq!(main.dfg[b1].instructions().len(), 6); + assert_normalized_ssa_equals(ssa, expected); } #[test] fn as_witness_die() { - // fn main f0 { - // b0(v0: Field): - // v1 = add v0, Field 1 - // v2 = add v0, Field 2 - // call as_witness(v2) - // return v1 - // } - 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 v1 = builder.insert_binary(v0, BinaryOp::Add, one); - let v2 = builder.insert_binary(v0, BinaryOp::Add, two); - let as_witness = builder.import_intrinsic("as_witness").unwrap(); - builder.insert_call(as_witness, vec![v2], Vec::new()); - builder.terminate_with_return(vec![v1]); - - let ssa = builder.finish(); - let main = ssa.main(); - - // The instruction count never includes the terminator instruction - assert_eq!(main.dfg[main.entry_block()].instructions().len(), 3); - - // Expected output: - // - // acir(inline) fn main f0 { - // b0(v0: Field): - // v3 = add v0, Field 1 - // return v3 - // } + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + v2 = add v0, Field 1 + v4 = add v0, Field 2 + call as_witness(v4) + return v2 + } + "; + let ssa = Ssa::from_str(src).unwrap(); + + let expected = " + acir(inline) fn main f0 { + b0(v0: Field): + v2 = add v0, Field 1 + return v2 + } + "; let ssa = ssa.dead_instruction_elimination(); - let main = ssa.main(); - - assert_eq!(main.dfg[main.entry_block()].instructions().len(), 1); + assert_normalized_ssa_equals(ssa, expected); } #[test] fn remove_useless_paired_rcs_even_when_used() { - // acir(inline) fn main f0 { - // b0(v0: [Field; 2]): - // inc_rc v0 - // v2 = array_get v0, index u32 0 - // dec_rc v0 - // return v2 - // } - let main_id = Id::test_new(0); - - // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id); - let v0 = builder.add_parameter(Type::Array(Arc::new(vec![Type::field()]), 2)); - builder.increment_array_reference_count(v0); - let zero = builder.numeric_constant(0u128, Type::unsigned(32)); - let v1 = builder.insert_array_get(v0, zero, Type::field()); - builder.decrement_array_reference_count(v0); - builder.terminate_with_return(vec![v1]); - - let ssa = builder.finish(); - let main = ssa.main(); - - // The instruction count never includes the terminator instruction - assert_eq!(main.dfg[main.entry_block()].instructions().len(), 3); - - // Expected output: - // - // acir(inline) fn main f0 { - // b0(v0: [Field; 2]): - // v2 = array_get v0, index u32 0 - // return v2 - // } + let src = " + acir(inline) fn main f0 { + b0(v0: [Field; 2]): + inc_rc v0 + v2 = array_get v0, index u32 0 -> Field + dec_rc v0 + return v2 + } + "; + let ssa = Ssa::from_str(src).unwrap(); + + let expected = " + acir(inline) fn main f0 { + b0(v0: [Field; 2]): + v2 = array_get v0, index u32 0 -> Field + return v2 + } + "; let ssa = ssa.dead_instruction_elimination(); - let main = ssa.main(); - - let instructions = main.dfg[main.entry_block()].instructions(); - assert_eq!(instructions.len(), 1); - assert!(matches!(&main.dfg[instructions[0]], Instruction::ArrayGet { .. })); + assert_normalized_ssa_equals(ssa, expected); } #[test] fn keep_paired_rcs_with_array_set() { - // acir(inline) fn main f0 { - // b0(v0: [Field; 2]): - // inc_rc v0 - // v2 = array_set v0, index u32 0, value u32 0 - // dec_rc v0 - // return v2 - // } - let main_id = Id::test_new(0); - - // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id); - let v0 = builder.add_parameter(Type::Array(Arc::new(vec![Type::field()]), 2)); - builder.increment_array_reference_count(v0); - let zero = builder.numeric_constant(0u128, Type::unsigned(32)); - let v1 = builder.insert_array_set(v0, zero, zero); - builder.decrement_array_reference_count(v0); - builder.terminate_with_return(vec![v1]); - - let ssa = builder.finish(); - let main = ssa.main(); - - // The instruction count never includes the terminator instruction - assert_eq!(main.dfg[main.entry_block()].instructions().len(), 3); + let src = " + acir(inline) fn main f0 { + b0(v0: [Field; 2]): + inc_rc v0 + v2 = array_set v0, index u32 0, value u32 0 + dec_rc v0 + return v2 + } + "; + let ssa = Ssa::from_str(src).unwrap(); // We expect the output to be unchanged let ssa = ssa.dead_instruction_elimination(); - let main = ssa.main(); - - assert_eq!(main.dfg[main.entry_block()].instructions().len(), 3); + assert_normalized_ssa_equals(ssa, src); } #[test] @@ -940,47 +848,31 @@ mod test { #[test] fn remove_inc_rcs_that_are_never_mutably_borrowed() { - // acir(inline) fn main f0 { - // b0(v0: [Field; 2]): - // inc_rc v0 - // inc_rc v0 - // inc_rc v0 - // v2 = array_get v0, index u32 0 - // inc_rc v0 - // return v2 - // } - let main_id = Id::test_new(0); - - // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id); - let v0 = builder.add_parameter(Type::Array(Arc::new(vec![Type::field()]), 2)); - builder.increment_array_reference_count(v0); - builder.increment_array_reference_count(v0); - builder.increment_array_reference_count(v0); - - let zero = builder.numeric_constant(0u128, Type::unsigned(32)); - let v2 = builder.insert_array_get(v0, zero, Type::field()); - builder.increment_array_reference_count(v0); - builder.terminate_with_return(vec![v2]); - - let ssa = builder.finish(); + let src = " + acir(inline) fn main f0 { + b0(v0: [Field; 2]): + inc_rc v0 + inc_rc v0 + inc_rc v0 + v2 = array_get v0, index u32 0 -> Field + inc_rc v0 + return v2 + } + "; + let ssa = Ssa::from_str(src).unwrap(); let main = ssa.main(); // The instruction count never includes the terminator instruction assert_eq!(main.dfg[main.entry_block()].instructions().len(), 5); - // Expected output: - // - // acir(inline) fn main f0 { - // b0(v0: [Field; 2]): - // v2 = array_get v0, index u32 0 - // return v2 - // } + let expected = " + acir(inline) fn main f0 { + b0(v0: [Field; 2]): + v2 = array_get v0, index u32 0 -> Field + return v2 + } + "; let ssa = ssa.dead_instruction_elimination(); - let main = ssa.main(); - - let instructions = main.dfg[main.entry_block()].instructions(); - assert_eq!(instructions.len(), 1); - assert!(matches!(&main.dfg[instructions[0]], Instruction::ArrayGet { .. })); + assert_normalized_ssa_equals(ssa, expected); } } 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 984f639df00..db2d96aac81 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 @@ -930,237 +930,156 @@ mod test { types::Type, value::{Value, ValueId}, }, + opt::assert_normalized_ssa_equals, + Ssa, }; #[test] fn basic_jmpif() { - // fn main f0 { - // b0(v0: b1): - // jmpif v0, then: b1, else: b2 - // b1(): - // jmp b3(Field 3) - // b2(): - // jmp b3(Field 4) - // b3(v1: Field): - // return v1 - // } - let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id); - - let b1 = builder.insert_block(); - let b2 = builder.insert_block(); - let b3 = builder.insert_block(); - - let v0 = builder.add_parameter(Type::bool()); - let v1 = builder.add_block_parameter(b3, Type::field()); - - let three = builder.field_constant(3u128); - let four = builder.field_constant(4u128); - - builder.terminate_with_jmpif(v0, b1, b2); - - builder.switch_to_block(b1); - builder.terminate_with_jmp(b3, vec![three]); - - builder.switch_to_block(b2); - builder.terminate_with_jmp(b3, vec![four]); - - builder.switch_to_block(b3); - builder.terminate_with_return(vec![v1]); - - let ssa = builder.finish(); + let src = " + acir(inline) fn main f0 { + b0(v0: u1): + jmpif v0 then: b1, else: b2 + b1(): + jmp b3(Field 3) + b3(v1: Field): + return v1 + b2(): + jmp b3(Field 4) + } + "; + let ssa = Ssa::from_str(src).unwrap(); assert_eq!(ssa.main().reachable_blocks().len(), 4); - // Expected output: - // fn main f0 { - // b0(v0: u1): - // enable_side_effects v0 - // v5 = not v0 - // enable_side_effects v5 - // enable_side_effects u1 1 - // v7 = mul v0, Field 3 - // v8 = mul v5, Field 4 - // v9 = add v7, v8 - // return v9 - // } + let expected = " + acir(inline) fn main f0 { + b0(v0: u1): + enable_side_effects v0 + v1 = not v0 + enable_side_effects u1 1 + v3 = cast v0 as Field + v4 = cast v1 as Field + v6 = mul v3, Field 3 + v8 = mul v4, Field 4 + v9 = add v6, v8 + return v9 + } + "; + let ssa = ssa.flatten_cfg(); - assert_eq!(ssa.main().reachable_blocks().len(), 1); + assert_normalized_ssa_equals(ssa, expected); } #[test] fn modify_constrain() { - // fn main f0 { - // b0(v0: u1, v1: u1): - // jmpif v0, then: b1, else: b2 - // b1(): - // constrain v1 - // jmp b2() - // b2(): - // return - // } - let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id); - - let b1 = builder.insert_block(); - let b2 = builder.insert_block(); - - let v0 = builder.add_parameter(Type::bool()); - let v1 = builder.add_parameter(Type::bool()); - let v_true = builder.numeric_constant(true, Type::bool()); - - builder.terminate_with_jmpif(v0, b1, b2); - - builder.switch_to_block(b1); - builder.insert_constrain(v1, v_true, None); - builder.terminate_with_jmp(b2, vec![]); - - builder.switch_to_block(b2); - builder.terminate_with_return(vec![]); - - let ssa = builder.finish(); + let src = " + acir(inline) fn main f0 { + b0(v0: u1, v1: u1): + jmpif v0 then: b1, else: b2 + b1(): + constrain v1 == u1 1 + jmp b2() + b2(): + return + } + "; + let ssa = Ssa::from_str(src).unwrap(); assert_eq!(ssa.main().reachable_blocks().len(), 3); - // Expected output: - // fn main f0 { - // b0(v0: u1, v1: u1): - // enable_side_effects v0 - // v3 = mul v1, v0 - // v4 = eq v3, v0 - // constrain v4 - // v5 = not v0 - // enable_side_effects v5 - // enable_side_effects u1 1 - // return - // } + let expected = " + acir(inline) fn main f0 { + b0(v0: u1, v1: u1): + enable_side_effects v0 + v2 = mul v1, v0 + constrain v2 == v0 + v3 = not v0 + enable_side_effects u1 1 + return + } + "; let ssa = ssa.flatten_cfg(); assert_eq!(ssa.main().reachable_blocks().len(), 1); + assert_normalized_ssa_equals(ssa, expected); } #[test] fn merge_stores() { - // fn main f0 { - // b0(v0: u1, v1: &mut Field): - // jmpif v0, then: b1, else: b2 - // b1(): - // store v1, Field 5 - // jmp b2() - // b2(): - // return - // } - let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id); - - let b1 = builder.insert_block(); - let b2 = builder.insert_block(); - - let v0 = builder.add_parameter(Type::bool()); - let v1 = builder.add_parameter(Type::Reference(Arc::new(Type::field()))); - - builder.terminate_with_jmpif(v0, b1, b2); - - builder.switch_to_block(b1); - let five = builder.field_constant(5u128); - builder.insert_store(v1, five); - builder.terminate_with_jmp(b2, vec![]); - - builder.switch_to_block(b2); - builder.terminate_with_return(vec![]); - - let ssa = builder.finish(); - - // Expected output: - // fn main f0 { - // b0(v0: u1, v1: reference): - // enable_side_effects v0 - // v4 = load v1 - // store Field 5 at v1 - // v5 = not v0 - // store v4 at v1 - // enable_side_effects u1 1 - // v6 = cast v0 as Field - // v7 = cast v5 as Field - // v8 = mul v6, Field 5 - // v9 = mul v7, v4 - // v10 = add v8, v9 - // store v10 at v1 - // return - // } + let src = " + acir(inline) fn main f0 { + b0(v0: u1, v1: &mut Field): + jmpif v0 then: b1, else: b2 + b1(): + store Field 5 at v1 + jmp b2() + b2(): + return + } + "; + let ssa = Ssa::from_str(src).unwrap(); + + let expected = " + acir(inline) fn main f0 { + b0(v0: u1, v1: &mut Field): + enable_side_effects v0 + v2 = load v1 -> Field + store Field 5 at v1 + v4 = not v0 + store v2 at v1 + enable_side_effects u1 1 + v6 = cast v0 as Field + v7 = cast v4 as Field + v8 = mul v6, Field 5 + v9 = mul v7, v2 + v10 = add v8, v9 + store v10 at v1 + return + } + "; let ssa = ssa.flatten_cfg(); - let main = ssa.main(); - - assert_eq!(main.reachable_blocks().len(), 1); - - let store_count = count_instruction(main, |ins| matches!(ins, Instruction::Store { .. })); - assert_eq!(store_count, 3); + assert_normalized_ssa_equals(ssa, expected); } #[test] fn merge_stores_with_else_block() { - // fn main f0 { - // b0(v0: u1, v1: ref): - // jmpif v0, then: b1, else: b2 - // b1(): - // store Field 5 in v1 - // jmp b3() - // b2(): - // store Field 6 in v1 - // jmp b3() - // b3(): - // return - // } - let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id); - - let b1 = builder.insert_block(); - let b2 = builder.insert_block(); - let b3 = builder.insert_block(); - - let v0 = builder.add_parameter(Type::bool()); - let v1 = builder.add_parameter(Type::Reference(Arc::new(Type::field()))); - - builder.terminate_with_jmpif(v0, b1, b2); - - builder.switch_to_block(b1); - let five = builder.field_constant(5u128); - builder.insert_store(v1, five); - builder.terminate_with_jmp(b3, vec![]); - - builder.switch_to_block(b2); - let six = builder.field_constant(6u128); - builder.insert_store(v1, six); - builder.terminate_with_jmp(b3, vec![]); - - builder.switch_to_block(b3); - builder.terminate_with_return(vec![]); - - let ssa = builder.finish(); - - // Expected output: - // fn main f0 { - // b0(v0: u1, v1: reference): - // enable_side_effects v0 - // v5 = load v1 - // store Field 5 at v1 - // v6 = not v0 - // store v5 at v1 - // enable_side_effects v6 - // v8 = load v1 - // store Field 6 at v1 - // enable_side_effects u1 1 - // v9 = cast v0 as Field - // v10 = cast v6 as Field - // v11 = mul v9, Field 5 - // v12 = mul v10, Field 6 - // v13 = add v11, v12 - // store v13 at v1 - // return - // } + let src = " + acir(inline) fn main f0 { + b0(v0: u1, v1: &mut Field): + jmpif v0 then: b1, else: b2 + b1(): + store Field 5 at v1 + jmp b3() + b2(): + store Field 6 at v1 + jmp b3() + b3(): + return + } + "; + let ssa = Ssa::from_str(src).unwrap(); + + let expected = " + acir(inline) fn main f0 { + b0(v0: u1, v1: &mut Field): + enable_side_effects v0 + v2 = load v1 -> Field + store Field 5 at v1 + v4 = not v0 + store v2 at v1 + enable_side_effects v4 + v5 = load v1 -> Field + store Field 6 at v1 + enable_side_effects u1 1 + v8 = cast v0 as Field + v9 = cast v4 as Field + v10 = mul v8, Field 5 + v11 = mul v9, Field 6 + v12 = add v10, v11 + store v12 at v1 + return + } + "; let ssa = ssa.flatten_cfg(); - let main = ssa.main(); - assert_eq!(main.reachable_blocks().len(), 1); - - let store_count = count_instruction(main, |ins| matches!(ins, Instruction::Store { .. })); - assert_eq!(store_count, 4); + assert_normalized_ssa_equals(ssa, expected); } fn count_instruction(function: &Function, f: impl Fn(&Instruction) -> bool) -> usize { @@ -1445,40 +1364,29 @@ mod test { // Very simplified derived regression test for #1792 // Tests that it does not simplify to a true constraint an always-false constraint // The original function is replaced by the following: - // fn main f1 { - // b0(): - // jmpif u1 0 then: b1, else: b2 - // b1(): - // jmp b2() - // b2(): - // constrain u1 0 // was incorrectly removed - // return - // } - let main_id = Id::test_new(1); - let mut builder = FunctionBuilder::new("main".into(), main_id); - - builder.insert_block(); // entry - - let b1 = builder.insert_block(); - let b2 = builder.insert_block(); - let v_true = builder.numeric_constant(true, Type::bool()); - let v_false = builder.numeric_constant(false, Type::bool()); - builder.terminate_with_jmpif(v_false, b1, b2); - - builder.switch_to_block(b1); - builder.terminate_with_jmp(b2, vec![]); - - builder.switch_to_block(b2); - builder.insert_constrain(v_false, v_true, None); // should not be removed - builder.terminate_with_return(vec![]); - - let ssa = builder.finish().flatten_cfg(); - let main = ssa.main(); - - // Assert we have not incorrectly removed a constraint: - use Instruction::Constrain; - let constrain_count = count_instruction(main, |ins| matches!(ins, Constrain(..))); - assert_eq!(constrain_count, 1); + let src = " + acir(inline) fn main f1 { + b0(): + jmpif u1 0 then: b1, else: b2 + b1(): + jmp b2() + b2(): + constrain u1 0 == u1 1 // was incorrectly removed + return + } + "; + let ssa = Ssa::from_str(src).unwrap(); + + let expected = " + acir(inline) fn main f0 { + b0(): + enable_side_effects u1 1 + constrain u1 0 == u1 1 + return + } + "; + let ssa = ssa.flatten_cfg(); + assert_normalized_ssa_equals(ssa, expected); } #[test] 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 9e3dd3e5a30..a052abc5e16 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 @@ -212,37 +212,32 @@ impl<'f> PerFunctionContext<'f> { 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 reference_parameters = self.reference_parameters(); - 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; + return true; } let allocation_aliases_parameter = aliases.any(|alias| per_func_block_params.contains(&alias)); if allocation_aliases_parameter == Some(true) { - store_alias_used = true; + return true; } let allocation_aliases_parameter = aliases.any(|alias| self.calls_reference_input.contains(&alias)); if allocation_aliases_parameter == Some(true) { - store_alias_used = true; + return true; } let allocation_aliases_parameter = aliases.any(|alias| all_terminator_values.contains(&alias)); if allocation_aliases_parameter == Some(true) { - store_alias_used = true; + return true; } let allocation_aliases_parameter = aliases.any(|alias| { @@ -252,14 +247,25 @@ impl<'f> PerFunctionContext<'f> { false } }); - if allocation_aliases_parameter == Some(true) { - store_alias_used = true; + return true; } } } - store_alias_used + false + } + + /// Collect the input parameters of the function which are of reference type. + /// All references are mutable, so these inputs are shared with the function caller + /// and thus stores should not be eliminated, even if the blocks in this function + /// don't use them anywhere. + fn reference_parameters(&self) -> BTreeSet { + let parameters = self.inserter.function.parameters().iter(); + parameters + .filter(|param| self.inserter.function.dfg.value_is_reference(**param)) + .copied() + .collect() } fn recursively_add_values(&self, value: ValueId, set: &mut HashSet) { @@ -300,6 +306,12 @@ impl<'f> PerFunctionContext<'f> { fn analyze_block(&mut self, block: BasicBlockId, mut references: Block) { let instructions = self.inserter.function.dfg[block].take_instructions(); + // If this is the entry block, take all the block parameters and assume they may + // be aliased to each other + if block == self.inserter.function.entry_block() { + self.add_aliases_for_reference_parameters(block, &mut references); + } + for instruction in instructions { self.analyze_instruction(block, &mut references, instruction); } @@ -316,13 +328,51 @@ impl<'f> PerFunctionContext<'f> { self.blocks.insert(block, references); } + /// Go through each parameter and register that all reference parameters of the same type are + /// possibly aliased to each other. If there are parameters with nested references (arrays of + /// references or references containing other references) we give up and assume all parameter + /// references are `AliasSet::unknown()`. + fn add_aliases_for_reference_parameters(&self, block: BasicBlockId, references: &mut Block) { + let dfg = &self.inserter.function.dfg; + let params = dfg.block_parameters(block); + + let mut aliases: HashMap = HashMap::default(); + + for param in params { + match dfg.type_of_value(*param) { + // If the type indirectly contains a reference we have to assume all references + // are unknown since we don't have any ValueIds to use. + Type::Reference(element) if element.contains_reference() => return, + Type::Reference(element) => { + let empty_aliases = AliasSet::known_empty(); + let alias_set = + aliases.entry(element.as_ref().clone()).or_insert(empty_aliases); + alias_set.insert(*param); + } + typ if typ.contains_reference() => return, + _ => continue, + } + } + + for aliases in aliases.into_values() { + let first = aliases.first(); + let first = first.expect("All parameters alias at least themselves or we early return"); + + let expression = Expression::Other(first); + let previous = references.aliases.insert(expression.clone(), aliases.clone()); + assert!(previous.is_none()); + + aliases.for_each(|alias| { + let previous = references.expressions.insert(alias, expression.clone()); + assert!(previous.is_none()); + }); + } + } + /// Add all instructions in `last_stores` to `self.instructions_to_remove` which do not /// possibly alias any parameters of the given function. fn remove_stores_that_do_not_alias_parameters(&mut self, references: &Block) { - let parameters = self.inserter.function.parameters().iter(); - let reference_parameters = parameters - .filter(|param| self.inserter.function.dfg.value_is_reference(**param)) - .collect::>(); + let reference_parameters = self.reference_parameters(); for (allocation, instruction) in &references.last_stores { if let Some(expression) = references.expressions.get(allocation) { @@ -466,6 +516,8 @@ impl<'f> PerFunctionContext<'f> { } } + /// If `array` is an array constant that contains reference types, then insert each element + /// as a potential alias to the array itself. fn check_array_aliasing(&self, references: &mut Block, array: ValueId) { if let Some((elements, typ)) = self.inserter.function.dfg.get_array_constant(array) { if Self::contains_references(&typ) { @@ -904,7 +956,7 @@ mod tests { let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.insert_allocate(Type::field()); - let zero = builder.numeric_constant(0u128, Type::field()); + let zero = builder.field_constant(0u128); builder.insert_store(v0, zero); let v2 = builder.insert_allocate(Type::field()); @@ -928,9 +980,9 @@ mod tests { // Loop body builder.switch_to_block(b2); let v5 = builder.insert_load(v2, v2_type.clone()); - let two = builder.numeric_constant(2u128, Type::field()); + let two = builder.field_constant(2u128); builder.insert_store(v5, two); - let one = builder.numeric_constant(1u128, Type::field()); + let one = builder.field_constant(1u128); let v3_plus_one = builder.insert_binary(v3, BinaryOp::Add, one); builder.terminate_with_jmp(b1, vec![v3_plus_one]); @@ -961,4 +1013,44 @@ mod tests { assert_eq!(count_loads(b2, &main.dfg), 1); assert_eq!(count_loads(b3, &main.dfg), 3); } + + #[test] + fn parameter_alias() { + // Do not assume parameters are not aliased to each other. + // The load below shouldn't be removed since `v0` could + // be aliased to `v1`. + // + // fn main f0 { + // b0(v0: &mut Field, v1: &mut Field): + // store Field 0 at v0 + // store Field 1 at v1 + // v4 = load v0 + // constrain v4 == Field 1 + // return + // } + let main_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), main_id); + + let field_ref = Type::Reference(Arc::new(Type::field())); + let v0 = builder.add_parameter(field_ref.clone()); + let v1 = builder.add_parameter(field_ref.clone()); + + let zero = builder.field_constant(0u128); + let one = builder.field_constant(0u128); + builder.insert_store(v0, zero); + builder.insert_store(v1, one); + + let v4 = builder.insert_load(v0, Type::field()); + builder.insert_constrain(v4, one, None); + builder.terminate_with_return(Vec::new()); + + let ssa = builder.finish(); + let main = ssa.main(); + assert_eq!(count_loads(main.entry_block(), &main.dfg), 1); + + // No change expected + let ssa = ssa.mem2reg(); + let main = ssa.main(); + assert_eq!(count_loads(main.entry_block(), &main.dfg), 1); + } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg/alias_set.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg/alias_set.rs index 5477025e429..4d768caa36b 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg/alias_set.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg/alias_set.rs @@ -73,4 +73,11 @@ impl AliasSet { } } } + + /// Return the first ValueId in the alias set as long as there is at least one. + /// The ordering is arbitrary (by lowest ValueId) so this method should only be + /// used when you need an arbitrary ValueId from the alias set. + pub(super) fn first(&self) -> Option { + self.aliases.as_ref().and_then(|aliases| aliases.first().copied()) + } } 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 f3dbd58fa69..5576b494570 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 @@ -3,6 +3,7 @@ //! Each pass is generally expected to mutate the SSA IR into a gradually //! simpler form until the IR only has a single function remaining with 1 block within it. //! Generally, these passes are also expected to minimize the final amount of instructions. + mod array_set; mod as_slice_length; mod assert_constant; @@ -21,3 +22,29 @@ mod resolve_is_unconstrained; mod runtime_separation; mod simplify_cfg; mod unrolling; + +/// Asserts that the given SSA, after normalizing its IDs and printing it, +/// is equal to the expected strings. Normalization is done so the IDs don't +/// shift depending on whether temporary intermediate values were created. +#[cfg(test)] +pub(crate) fn assert_normalized_ssa_equals(mut ssa: super::Ssa, expected: &str) { + // First check if `expected` is valid SSA by parsing it, otherwise + // the comparison will always fail but it won't be clear that it's because + // expected is not valid. + if let Err(err) = Ssa::from_str(expected) { + panic!("`expected` argument of `assert_ssa_equals` is not valid SSA:\n{:?}", err); + } + + use crate::{ssa::Ssa, trim_leading_whitespace_from_lines}; + + ssa.normalize_ids(); + + let ssa = ssa.to_string(); + let ssa = trim_leading_whitespace_from_lines(&ssa); + let expected = trim_leading_whitespace_from_lines(expected); + + if ssa != expected { + println!("Got:\n~~~\n{}\n~~~\nExpected:\n~~~\n{}\n~~~", ssa, expected); + similar_asserts::assert_eq!(ssa, expected); + } +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs index 6f3f2fa14b7..cdbb1043232 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs @@ -145,6 +145,8 @@ impl Context<'_> { } /// Insert ssa instructions which computes lhs >> rhs by doing lhs/2^rhs + /// For negative signed integers, we do the division on the 1-complement representation of lhs, + /// before converting back the result to the 2-complement representation. pub(crate) fn insert_shift_right( &mut self, lhs: ValueId, @@ -153,16 +155,27 @@ impl Context<'_> { ) -> ValueId { let lhs_typ = self.function.dfg.type_of_value(lhs); let base = self.field_constant(FieldElement::from(2_u128)); - // we can safely cast to unsigned because overflow_checks prevent bit-shift with a negative value - let rhs_unsigned = self.insert_cast(rhs, Type::unsigned(bit_size)); - let pow = self.pow(base, rhs_unsigned); - // We need at least one more bit for the case where rhs == bit_size - let div_type = Type::unsigned(bit_size + 1); - let casted_lhs = self.insert_cast(lhs, div_type.clone()); - let casted_pow = self.insert_cast(pow, div_type); - let div_result = self.insert_binary(casted_lhs, BinaryOp::Div, casted_pow); - // We have to cast back to the original type - self.insert_cast(div_result, lhs_typ) + let pow = self.pow(base, rhs); + if lhs_typ.is_unsigned() { + // unsigned right bit shift is just a normal division + self.insert_binary(lhs, BinaryOp::Div, pow) + } else { + // Get the sign of the operand; positive signed operand will just do a division as well + let zero = self.numeric_constant(FieldElement::zero(), Type::signed(bit_size)); + let lhs_sign = self.insert_binary(lhs, BinaryOp::Lt, zero); + let lhs_sign_as_field = self.insert_cast(lhs_sign, Type::field()); + let lhs_as_field = self.insert_cast(lhs, Type::field()); + // For negative numbers, convert to 1-complement using wrapping addition of a + 1 + let one_complement = self.insert_binary(lhs_sign_as_field, BinaryOp::Add, lhs_as_field); + let one_complement = self.insert_truncate(one_complement, bit_size, bit_size + 1); + let one_complement = self.insert_cast(one_complement, Type::signed(bit_size)); + // Performs the division on the 1-complement (or the operand if positive) + let shifted_complement = self.insert_binary(one_complement, BinaryOp::Div, pow); + // Convert back to 2-complement representation if operand is negative + let lhs_sign_as_int = self.insert_cast(lhs_sign, lhs_typ); + let shifted = self.insert_binary(shifted_complement, BinaryOp::Sub, lhs_sign_as_int); + self.insert_truncate(shifted, bit_size, bit_size + 1) + } } /// Computes lhs^rhs via square&multiply, using the bits decomposition of rhs diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser.rs new file mode 100644 index 00000000000..717d2691b2f --- /dev/null +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser.rs @@ -0,0 +1,902 @@ +use std::{ + fmt::{self, Debug, Formatter}, + sync::Arc, +}; + +use super::{ + ir::{instruction::BinaryOp, types::Type}, + Ssa, +}; + +use acvm::{AcirField, FieldElement}; +use ast::{ + Identifier, ParsedBlock, ParsedFunction, ParsedInstruction, ParsedParameter, ParsedSsa, + ParsedValue, +}; +use lexer::{Lexer, LexerError}; +use noirc_errors::Span; +use noirc_frontend::{monomorphization::ast::InlineType, token::IntType}; +use thiserror::Error; +use token::{Keyword, SpannedToken, Token}; + +use crate::ssa::{ir::function::RuntimeType, parser::ast::ParsedTerminator}; + +mod ast; +mod into_ssa; +mod lexer; +mod tests; +mod token; + +impl Ssa { + pub(crate) fn from_str(src: &str) -> Result { + let mut parser = + Parser::new(src).map_err(|err| SsaErrorWithSource::parse_error(err, src))?; + let parsed_ssa = + parser.parse_ssa().map_err(|err| SsaErrorWithSource::parse_error(err, src))?; + parsed_ssa.into_ssa().map_err(|error| SsaErrorWithSource { src: src.to_string(), error }) + } +} + +pub(crate) struct SsaErrorWithSource { + src: String, + error: SsaError, +} + +impl SsaErrorWithSource { + fn parse_error(error: ParserError, src: &str) -> Self { + Self { src: src.to_string(), error: SsaError::ParserError(error) } + } +} + +impl Debug for SsaErrorWithSource { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + let span = self.error.span(); + + let mut byte: usize = 0; + for line in self.src.lines() { + let has_error = + byte <= span.start() as usize && span.end() as usize <= byte + line.len(); + if has_error { + writeln!(f)?; + } + + writeln!(f, "{}", line)?; + + if has_error { + let offset = span.start() as usize - byte; + write!(f, "{}", " ".repeat(offset))?; + writeln!(f, "{}", "^".repeat((span.end() - span.start()) as usize))?; + write!(f, "{}", " ".repeat(offset))?; + writeln!(f, "{}", self.error)?; + writeln!(f)?; + } + + byte += line.len() + 1; // "+ 1" for the newline + } + Ok(()) + } +} + +#[derive(Debug, Error)] +pub(crate) enum SsaError { + #[error("{0}")] + ParserError(ParserError), + #[error("Unknown variable '{0}'")] + UnknownVariable(Identifier), + #[error("Unknown block '{0}'")] + UnknownBlock(Identifier), + #[error("Unknown function '{0}'")] + UnknownFunction(Identifier), + #[error("Mismatched return values")] + MismatchedReturnValues { returns: Vec, expected: usize }, + #[error("Variable '{0}' already defined")] + VariableAlreadyDefined(Identifier), +} + +impl SsaError { + fn span(&self) -> Span { + match self { + SsaError::ParserError(parser_error) => parser_error.span(), + SsaError::UnknownVariable(identifier) + | SsaError::UnknownBlock(identifier) + | SsaError::VariableAlreadyDefined(identifier) + | SsaError::UnknownFunction(identifier) => identifier.span, + SsaError::MismatchedReturnValues { returns, expected: _ } => returns[0].span, + } + } +} + +type ParseResult = Result; + +pub(crate) struct Parser<'a> { + lexer: Lexer<'a>, + token: SpannedToken, +} + +impl<'a> Parser<'a> { + pub(crate) fn new(source: &'a str) -> ParseResult { + let lexer = Lexer::new(source); + let mut parser = Self { lexer, token: eof_spanned_token() }; + parser.token = parser.read_token_internal()?; + Ok(parser) + } + + pub(crate) fn parse_ssa(&mut self) -> ParseResult { + let mut functions = Vec::new(); + while !self.at(Token::Eof) { + let function = self.parse_function()?; + functions.push(function); + } + Ok(ParsedSsa { functions }) + } + + fn parse_function(&mut self) -> ParseResult { + let runtime_type = self.parse_runtime_type()?; + self.eat_or_error(Token::Keyword(Keyword::Fn))?; + + let external_name = self.eat_ident_or_error()?; + let internal_name = self.eat_ident_or_error()?; + + self.eat_or_error(Token::LeftBrace)?; + + let blocks = self.parse_blocks()?; + + self.eat_or_error(Token::RightBrace)?; + + Ok(ParsedFunction { runtime_type, external_name, internal_name, blocks }) + } + + fn parse_runtime_type(&mut self) -> ParseResult { + let acir = if self.eat_keyword(Keyword::Acir)? { + true + } else if self.eat_keyword(Keyword::Brillig)? { + false + } else { + return self.expected_one_of_tokens(&[ + Token::Keyword(Keyword::Acir), + Token::Keyword(Keyword::Brillig), + ]); + }; + + self.eat_or_error(Token::LeftParen)?; + let inline_type = self.parse_inline_type()?; + self.eat_or_error(Token::RightParen)?; + + if acir { + Ok(RuntimeType::Acir(inline_type)) + } else { + Ok(RuntimeType::Brillig(inline_type)) + } + } + + fn parse_inline_type(&mut self) -> ParseResult { + if self.eat_keyword(Keyword::Inline)? { + Ok(InlineType::Inline) + } else if self.eat_keyword(Keyword::InlineAlways)? { + Ok(InlineType::InlineAlways) + } else if self.eat_keyword(Keyword::Fold)? { + Ok(InlineType::Fold) + } else if self.eat_keyword(Keyword::NoPredicates)? { + Ok(InlineType::NoPredicates) + } else { + self.expected_one_of_tokens(&[ + Token::Keyword(Keyword::Inline), + Token::Keyword(Keyword::InlineAlways), + Token::Keyword(Keyword::Fold), + Token::Keyword(Keyword::NoPredicates), + ]) + } + } + + fn parse_blocks(&mut self) -> ParseResult> { + let mut blocks = Vec::new(); + while !self.at(Token::RightBrace) { + let block = self.parse_block()?; + blocks.push(block); + } + Ok(blocks) + } + + fn parse_block(&mut self) -> ParseResult { + let name = self.eat_ident_or_error()?; + self.eat_or_error(Token::LeftParen)?; + + let mut parameters = Vec::new(); + while !self.at(Token::RightParen) { + parameters.push(self.parse_parameter()?); + if !self.eat(Token::Comma)? { + break; + } + } + + self.eat_or_error(Token::RightParen)?; + self.eat_or_error(Token::Colon)?; + + let instructions = self.parse_instructions()?; + let terminator = self.parse_terminator()?; + Ok(ParsedBlock { name, parameters, instructions, terminator }) + } + + fn parse_parameter(&mut self) -> ParseResult { + let identifier = self.eat_identifier_or_error()?; + self.eat_or_error(Token::Colon)?; + let typ = self.parse_type()?; + Ok(ParsedParameter { identifier, typ }) + } + + fn parse_instructions(&mut self) -> ParseResult> { + let mut instructions = Vec::new(); + while let Some(instruction) = self.parse_instruction()? { + instructions.push(instruction); + } + Ok(instructions) + } + + fn parse_instruction(&mut self) -> ParseResult> { + if let Some(instruction) = self.parse_call()? { + return Ok(Some(instruction)); + } + + if let Some(instruction) = self.parse_constrain()? { + return Ok(Some(instruction)); + } + + if let Some(instruction) = self.parse_decrement_rc()? { + return Ok(Some(instruction)); + } + + if let Some(instruction) = self.parse_enable_side_effects()? { + return Ok(Some(instruction)); + } + + if let Some(instruction) = self.parse_increment_rc()? { + return Ok(Some(instruction)); + } + + if let Some(instruction) = self.parse_range_check()? { + return Ok(Some(instruction)); + } + + if let Some(instruction) = self.parse_store()? { + return Ok(Some(instruction)); + } + + if let Some(target) = self.eat_identifier()? { + return Ok(Some(self.parse_assignment(target)?)); + } + + Ok(None) + } + + fn eat_binary_op(&mut self) -> ParseResult> { + let op = match self.token.token() { + Token::Keyword(Keyword::Add) => BinaryOp::Add, + Token::Keyword(Keyword::Sub) => BinaryOp::Sub, + Token::Keyword(Keyword::Mul) => BinaryOp::Mul, + Token::Keyword(Keyword::Div) => BinaryOp::Div, + Token::Keyword(Keyword::Eq) => BinaryOp::Eq, + Token::Keyword(Keyword::Mod) => BinaryOp::Mod, + Token::Keyword(Keyword::Lt) => BinaryOp::Lt, + Token::Keyword(Keyword::And) => BinaryOp::And, + Token::Keyword(Keyword::Or) => BinaryOp::Or, + Token::Keyword(Keyword::Xor) => BinaryOp::Xor, + Token::Keyword(Keyword::Shl) => BinaryOp::Shl, + Token::Keyword(Keyword::Shr) => BinaryOp::Shr, + _ => return Ok(None), + }; + + self.bump()?; + + Ok(Some(op)) + } + + fn parse_call(&mut self) -> ParseResult> { + if !self.eat_keyword(Keyword::Call)? { + return Ok(None); + } + + let function = self.eat_identifier_or_error()?; + let arguments = self.parse_arguments()?; + Ok(Some(ParsedInstruction::Call { targets: vec![], function, arguments, types: vec![] })) + } + + fn parse_constrain(&mut self) -> ParseResult> { + if !self.eat_keyword(Keyword::Constrain)? { + return Ok(None); + } + + let lhs = self.parse_value_or_error()?; + self.eat_or_error(Token::Equal)?; + let rhs = self.parse_value_or_error()?; + Ok(Some(ParsedInstruction::Constrain { lhs, rhs })) + } + + fn parse_decrement_rc(&mut self) -> ParseResult> { + if !self.eat_keyword(Keyword::DecRc)? { + return Ok(None); + } + + let value = self.parse_value_or_error()?; + Ok(Some(ParsedInstruction::DecrementRc { value })) + } + + fn parse_enable_side_effects(&mut self) -> ParseResult> { + if !self.eat_keyword(Keyword::EnableSideEffects)? { + return Ok(None); + } + + let condition = self.parse_value_or_error()?; + Ok(Some(ParsedInstruction::EnableSideEffectsIf { condition })) + } + + fn parse_increment_rc(&mut self) -> ParseResult> { + if !self.eat_keyword(Keyword::IncRc)? { + return Ok(None); + } + + let value = self.parse_value_or_error()?; + Ok(Some(ParsedInstruction::IncrementRc { value })) + } + + fn parse_range_check(&mut self) -> ParseResult> { + if !self.eat_keyword(Keyword::RangeCheck)? { + return Ok(None); + } + + let value = self.parse_value_or_error()?; + self.eat_or_error(Token::Keyword(Keyword::To))?; + let max_bit_size = self.eat_int_or_error()?.to_u128() as u32; + self.eat_or_error(Token::Keyword(Keyword::Bits))?; + Ok(Some(ParsedInstruction::RangeCheck { value, max_bit_size })) + } + + fn parse_store(&mut self) -> ParseResult> { + if !self.eat_keyword(Keyword::Store)? { + return Ok(None); + } + + let value = self.parse_value_or_error()?; + self.eat_or_error(Token::Keyword(Keyword::At))?; + let address = self.parse_value_or_error()?; + Ok(Some(ParsedInstruction::Store { address, value })) + } + + fn parse_assignment(&mut self, target: Identifier) -> ParseResult { + let mut targets = vec![target]; + + while self.eat(Token::Comma)? { + let target = self.eat_identifier_or_error()?; + targets.push(target); + } + + self.eat_or_error(Token::Assign)?; + + if self.eat_keyword(Keyword::Call)? { + let function = self.eat_identifier_or_error()?; + let arguments = self.parse_arguments()?; + self.eat_or_error(Token::Arrow)?; + let types = self.parse_types()?; + return Ok(ParsedInstruction::Call { targets, function, arguments, types }); + } + + if targets.len() > 1 { + return Err(ParserError::MultipleReturnValuesOnlyAllowedForCall { + second_target: targets[1].clone(), + }); + } + + let target = targets.remove(0); + + if self.eat_keyword(Keyword::Allocate)? { + self.eat_or_error(Token::Arrow)?; + let typ = self.parse_mutable_reference_type_or_error()?; + return Ok(ParsedInstruction::Allocate { target, typ }); + } + + if self.eat_keyword(Keyword::ArrayGet)? { + let array = self.parse_value_or_error()?; + self.eat_or_error(Token::Comma)?; + self.eat_or_error(Token::Keyword(Keyword::Index))?; + let index = self.parse_value_or_error()?; + self.eat_or_error(Token::Arrow)?; + let element_type = self.parse_type()?; + return Ok(ParsedInstruction::ArrayGet { target, element_type, array, index }); + } + + if self.eat_keyword(Keyword::ArraySet)? { + let mutable = self.eat_keyword(Keyword::Mut)?; + let array = self.parse_value_or_error()?; + self.eat_or_error(Token::Comma)?; + self.eat_or_error(Token::Keyword(Keyword::Index))?; + let index = self.parse_value_or_error()?; + self.eat_or_error(Token::Comma)?; + self.eat_or_error(Token::Keyword(Keyword::Value))?; + let value = self.parse_value_or_error()?; + return Ok(ParsedInstruction::ArraySet { target, array, index, value, mutable }); + } + + if self.eat_keyword(Keyword::Cast)? { + let lhs = self.parse_value_or_error()?; + self.eat_or_error(Token::Keyword(Keyword::As))?; + let typ = self.parse_type()?; + return Ok(ParsedInstruction::Cast { target, lhs, typ }); + } + + if self.eat_keyword(Keyword::Load)? { + let value = self.parse_value_or_error()?; + self.eat_or_error(Token::Arrow)?; + let typ = self.parse_type()?; + return Ok(ParsedInstruction::Load { target, value, typ }); + } + + if self.eat_keyword(Keyword::Not)? { + let value = self.parse_value_or_error()?; + return Ok(ParsedInstruction::Not { target, value }); + } + + if self.eat_keyword(Keyword::Truncate)? { + let value = self.parse_value_or_error()?; + self.eat_or_error(Token::Keyword(Keyword::To))?; + let bit_size = self.eat_int_or_error()?.to_u128() as u32; + self.eat_or_error(Token::Keyword(Keyword::Bits))?; + self.eat_or_error(Token::Comma)?; + self.eat_or_error(Token::Keyword(Keyword::MaxBitSize))?; + self.eat_or_error(Token::Colon)?; + let max_bit_size = self.eat_int_or_error()?.to_u128() as u32; + return Ok(ParsedInstruction::Truncate { target, value, bit_size, max_bit_size }); + } + + if let Some(op) = self.eat_binary_op()? { + let lhs = self.parse_value_or_error()?; + self.eat_or_error(Token::Comma)?; + let rhs = self.parse_value_or_error()?; + return Ok(ParsedInstruction::BinaryOp { target, lhs, op, rhs }); + } + + self.expected_instruction_or_terminator() + } + + fn parse_terminator(&mut self) -> ParseResult { + if let Some(terminator) = self.parse_return()? { + return Ok(terminator); + } + + if let Some(terminator) = self.parse_jmp()? { + return Ok(terminator); + } + + if let Some(terminator) = self.parse_jmpif()? { + return Ok(terminator); + } + + self.expected_instruction_or_terminator() + } + + fn parse_return(&mut self) -> ParseResult> { + // Before advancing to the next token (after a potential return keyword), + // we check if a newline follows. This is because if we have this: + // + // return + // b1(): + // ... + // + // then unless we check for a newline we can't know if the return + // returns `b1` or not (we could check if a parentheses comes next, but + // that would require a look-ahead and, for the purpose of the SSA parser, + // it's just simpler to check if a newline follows) + let newline_follows = self.newline_follows(); + + if !self.eat_keyword(Keyword::Return)? { + return Ok(None); + } + + let values = + if newline_follows { Vec::new() } else { self.parse_comma_separated_values()? }; + Ok(Some(ParsedTerminator::Return(values))) + } + + fn parse_jmp(&mut self) -> ParseResult> { + if !self.eat_keyword(Keyword::Jmp)? { + return Ok(None); + } + + let destination = self.eat_identifier_or_error()?; + let arguments = self.parse_arguments()?; + Ok(Some(ParsedTerminator::Jmp { destination, arguments })) + } + + fn parse_jmpif(&mut self) -> ParseResult> { + if !self.eat_keyword(Keyword::Jmpif)? { + return Ok(None); + } + + let condition = self.parse_value_or_error()?; + self.eat_or_error(Token::Keyword(Keyword::Then))?; + self.eat_or_error(Token::Colon)?; + let then_block = self.eat_identifier_or_error()?; + self.eat_or_error(Token::Comma)?; + self.eat_or_error(Token::Keyword(Keyword::Else))?; + self.eat_or_error(Token::Colon)?; + let else_block = self.eat_identifier_or_error()?; + + Ok(Some(ParsedTerminator::Jmpif { condition, then_block, else_block })) + } + + fn parse_arguments(&mut self) -> ParseResult> { + self.eat_or_error(Token::LeftParen)?; + let arguments = self.parse_comma_separated_values()?; + self.eat_or_error(Token::RightParen)?; + Ok(arguments) + } + + fn parse_comma_separated_values(&mut self) -> ParseResult> { + let mut values = Vec::new(); + while let Some(value) = self.parse_value()? { + values.push(value); + if !self.eat(Token::Comma)? { + break; + } + } + Ok(values) + } + + fn parse_value_or_error(&mut self) -> ParseResult { + if let Some(value) = self.parse_value()? { + Ok(value) + } else { + self.expected_value() + } + } + + fn parse_value(&mut self) -> ParseResult> { + if let Some(value) = self.parse_field_value()? { + return Ok(Some(value)); + } + + if let Some(value) = self.parse_int_value()? { + return Ok(Some(value)); + } + + if let Some(value) = self.parse_array_value()? { + return Ok(Some(value)); + } + + if let Some(identifier) = self.eat_identifier()? { + return Ok(Some(ParsedValue::Variable(identifier))); + } + + Ok(None) + } + + fn parse_field_value(&mut self) -> ParseResult> { + if self.eat_keyword(Keyword::Field)? { + let constant = self.eat_int_or_error()?; + Ok(Some(ParsedValue::NumericConstant { constant, typ: Type::field() })) + } else { + Ok(None) + } + } + + fn parse_int_value(&mut self) -> ParseResult> { + if let Some(int_type) = self.eat_int_type()? { + let constant = self.eat_int_or_error()?; + let typ = match int_type { + IntType::Unsigned(bit_size) => Type::unsigned(bit_size), + IntType::Signed(bit_size) => Type::signed(bit_size), + }; + Ok(Some(ParsedValue::NumericConstant { constant, typ })) + } else { + Ok(None) + } + } + + fn parse_array_value(&mut self) -> ParseResult> { + if self.eat(Token::LeftBracket)? { + let values = self.parse_comma_separated_values()?; + self.eat_or_error(Token::RightBracket)?; + self.eat_or_error(Token::Keyword(Keyword::Of))?; + let types = self.parse_types()?; + let types_len = types.len(); + let values_len = values.len(); + Ok(Some(ParsedValue::Array { + typ: Type::Array(Arc::new(types), values_len / types_len), + values, + })) + } else { + Ok(None) + } + } + + fn parse_types(&mut self) -> ParseResult> { + if self.eat(Token::LeftParen)? { + let types = self.parse_comma_separated_types()?; + self.eat_or_error(Token::RightParen)?; + Ok(types) + } else { + Ok(vec![self.parse_type()?]) + } + } + + fn parse_comma_separated_types(&mut self) -> ParseResult> { + let mut types = Vec::new(); + loop { + let typ = self.parse_type()?; + types.push(typ); + if !self.eat(Token::Comma)? { + break; + } + } + Ok(types) + } + + fn parse_type(&mut self) -> ParseResult { + if self.eat_keyword(Keyword::Bool)? { + return Ok(Type::bool()); + } + + if self.eat_keyword(Keyword::Field)? { + return Ok(Type::field()); + } + + if let Some(int_type) = self.eat_int_type()? { + return Ok(match int_type { + IntType::Unsigned(bit_size) => Type::unsigned(bit_size), + IntType::Signed(bit_size) => Type::signed(bit_size), + }); + } + + if self.eat(Token::LeftBracket)? { + let element_types = self.parse_types()?; + if self.eat(Token::Semicolon)? { + let length = self.eat_int_or_error()?; + self.eat_or_error(Token::RightBracket)?; + return Ok(Type::Array(Arc::new(element_types), length.to_u128() as usize)); + } else { + self.eat_or_error(Token::RightBracket)?; + return Ok(Type::Slice(Arc::new(element_types))); + } + } + + if let Some(typ) = self.parse_mutable_reference_type()? { + return Ok(Type::Reference(Arc::new(typ))); + } + + self.expected_type() + } + + /// Parses `&mut Type`, returns `Type` if `&mut` was found, errors otherwise. + fn parse_mutable_reference_type_or_error(&mut self) -> ParseResult { + if let Some(typ) = self.parse_mutable_reference_type()? { + Ok(typ) + } else { + self.expected_token(Token::Ampersand) + } + } + + /// Parses `&mut Type`, returns `Some(Type)` if `&mut` was found, `None` otherwise. + fn parse_mutable_reference_type(&mut self) -> ParseResult> { + if !self.eat(Token::Ampersand)? { + return Ok(None); + } + + self.eat_or_error(Token::Keyword(Keyword::Mut))?; + let typ = self.parse_type()?; + Ok(Some(typ)) + } + + fn eat_identifier_or_error(&mut self) -> ParseResult { + if let Some(identifier) = self.eat_identifier()? { + Ok(identifier) + } else { + self.expected_identifier() + } + } + + fn eat_identifier(&mut self) -> ParseResult> { + let span = self.token.to_span(); + if let Some(name) = self.eat_ident()? { + Ok(Some(Identifier::new(name, span))) + } else { + Ok(None) + } + } + + fn eat_keyword(&mut self, keyword: Keyword) -> ParseResult { + if let Token::Keyword(kw) = self.token.token() { + if *kw == keyword { + self.bump()?; + Ok(true) + } else { + Ok(false) + } + } else { + Ok(false) + } + } + + fn eat_ident(&mut self) -> ParseResult> { + if !matches!(self.token.token(), Token::Ident(..)) { + return Ok(None); + } + + let token = self.bump()?; + match token.into_token() { + Token::Ident(ident) => Ok(Some(ident)), + _ => unreachable!(), + } + } + + fn eat_ident_or_error(&mut self) -> ParseResult { + if let Some(ident) = self.eat_ident()? { + Ok(ident) + } else { + self.expected_identifier() + } + } + + fn eat_int(&mut self) -> ParseResult> { + if matches!(self.token.token(), Token::Int(..)) { + let token = self.bump()?; + match token.into_token() { + Token::Int(int) => Ok(Some(int)), + _ => unreachable!(), + } + } else { + Ok(None) + } + } + + fn eat_int_or_error(&mut self) -> ParseResult { + if let Some(int) = self.eat_int()? { + Ok(int) + } else { + self.expected_int() + } + } + + fn eat_int_type(&mut self) -> ParseResult> { + let is_int_type = matches!(self.token.token(), Token::IntType(..)); + if is_int_type { + let token = self.bump()?; + match token.into_token() { + Token::IntType(int_type) => Ok(Some(int_type)), + _ => unreachable!(), + } + } else { + Ok(None) + } + } + + fn eat(&mut self, token: Token) -> ParseResult { + if self.token.token() == &token { + self.bump()?; + Ok(true) + } else { + Ok(false) + } + } + + fn eat_or_error(&mut self, token: Token) -> ParseResult<()> { + if self.eat(token.clone())? { + Ok(()) + } else { + self.expected_token(token) + } + } + + fn at(&self, token: Token) -> bool { + self.token.token() == &token + } + + fn at_keyword(&self, keyword: Keyword) -> bool { + self.at(Token::Keyword(keyword)) + } + + fn newline_follows(&self) -> bool { + self.lexer.newline_follows() + } + + fn bump(&mut self) -> ParseResult { + let token = self.read_token_internal()?; + Ok(std::mem::replace(&mut self.token, token)) + } + + fn read_token_internal(&mut self) -> ParseResult { + self.lexer.next_token().map_err(ParserError::LexerError) + } + + fn expected_instruction_or_terminator(&mut self) -> ParseResult { + Err(ParserError::ExpectedInstructionOrTerminator { + found: self.token.token().clone(), + span: self.token.to_span(), + }) + } + + fn expected_identifier(&mut self) -> ParseResult { + Err(ParserError::ExpectedIdentifier { + found: self.token.token().clone(), + span: self.token.to_span(), + }) + } + + fn expected_int(&mut self) -> ParseResult { + Err(ParserError::ExpectedInt { + found: self.token.token().clone(), + span: self.token.to_span(), + }) + } + + fn expected_type(&mut self) -> ParseResult { + Err(ParserError::ExpectedType { + found: self.token.token().clone(), + span: self.token.to_span(), + }) + } + + fn expected_value(&mut self) -> ParseResult { + Err(ParserError::ExpectedValue { + found: self.token.token().clone(), + span: self.token.to_span(), + }) + } + + fn expected_token(&mut self, token: Token) -> ParseResult { + Err(ParserError::ExpectedToken { + token, + found: self.token.token().clone(), + span: self.token.to_span(), + }) + } + + fn expected_one_of_tokens(&mut self, tokens: &[Token]) -> ParseResult { + Err(ParserError::ExpectedOneOfTokens { + tokens: tokens.to_vec(), + found: self.token.token().clone(), + span: self.token.to_span(), + }) + } +} + +#[derive(Debug, Error)] +pub(crate) enum ParserError { + #[error("{0}")] + LexerError(LexerError), + #[error("Expected '{token}', found '{found}'")] + ExpectedToken { token: Token, found: Token, span: Span }, + #[error("Expected one of {tokens:?}, found {found}")] + ExpectedOneOfTokens { tokens: Vec, found: Token, span: Span }, + #[error("Expected an identifier, found '{found}'")] + ExpectedIdentifier { found: Token, span: Span }, + #[error("Expected an int, found '{found}'")] + ExpectedInt { found: Token, span: Span }, + #[error("Expected a type, found '{found}'")] + ExpectedType { found: Token, span: Span }, + #[error("Expected an instruction or terminator, found '{found}'")] + ExpectedInstructionOrTerminator { found: Token, span: Span }, + #[error("Expected a value, found '{found}'")] + ExpectedValue { found: Token, span: Span }, + #[error("Multiple return values only allowed for call")] + MultipleReturnValuesOnlyAllowedForCall { second_target: Identifier }, +} + +impl ParserError { + fn span(&self) -> Span { + match self { + ParserError::LexerError(err) => err.span(), + ParserError::ExpectedToken { span, .. } + | ParserError::ExpectedOneOfTokens { span, .. } + | ParserError::ExpectedIdentifier { span, .. } + | ParserError::ExpectedInt { span, .. } + | ParserError::ExpectedType { span, .. } + | ParserError::ExpectedInstructionOrTerminator { span, .. } + | ParserError::ExpectedValue { span, .. } => *span, + ParserError::MultipleReturnValuesOnlyAllowedForCall { second_target, .. } => { + second_target.span + } + } + } +} + +fn eof_spanned_token() -> SpannedToken { + SpannedToken::new(Token::Eof, Default::default()) +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/ast.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/ast.rs new file mode 100644 index 00000000000..f8fe8c68a98 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/ast.rs @@ -0,0 +1,139 @@ +use std::fmt::{self, Display, Formatter}; + +use acvm::FieldElement; +use noirc_errors::Span; + +use crate::ssa::ir::{function::RuntimeType, instruction::BinaryOp, types::Type}; + +#[derive(Debug)] +pub(crate) struct ParsedSsa { + pub(crate) functions: Vec, +} + +#[derive(Debug)] +pub(crate) struct ParsedFunction { + pub(crate) runtime_type: RuntimeType, + pub(crate) external_name: String, + pub(crate) internal_name: String, + pub(crate) blocks: Vec, +} + +#[derive(Debug)] +pub(crate) struct ParsedBlock { + pub(crate) name: String, + pub(crate) parameters: Vec, + pub(crate) instructions: Vec, + pub(crate) terminator: ParsedTerminator, +} + +#[derive(Debug)] +pub(crate) struct ParsedParameter { + pub(crate) identifier: Identifier, + pub(crate) typ: Type, +} + +#[derive(Debug, Clone)] +pub(crate) struct Identifier { + pub(crate) name: String, + pub(crate) span: Span, +} + +impl Identifier { + pub(crate) fn new(name: String, span: Span) -> Self { + Self { name, span } + } +} + +impl Display for Identifier { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.name) + } +} + +#[derive(Debug)] +pub(crate) enum ParsedInstruction { + Allocate { + target: Identifier, + typ: Type, + }, + ArrayGet { + target: Identifier, + element_type: Type, + array: ParsedValue, + index: ParsedValue, + }, + ArraySet { + target: Identifier, + array: ParsedValue, + index: ParsedValue, + value: ParsedValue, + mutable: bool, + }, + BinaryOp { + target: Identifier, + lhs: ParsedValue, + op: BinaryOp, + rhs: ParsedValue, + }, + Call { + targets: Vec, + function: Identifier, + arguments: Vec, + types: Vec, + }, + Cast { + target: Identifier, + lhs: ParsedValue, + typ: Type, + }, + Constrain { + lhs: ParsedValue, + rhs: ParsedValue, + }, + DecrementRc { + value: ParsedValue, + }, + EnableSideEffectsIf { + condition: ParsedValue, + }, + IncrementRc { + value: ParsedValue, + }, + Load { + target: Identifier, + value: ParsedValue, + typ: Type, + }, + Not { + target: Identifier, + value: ParsedValue, + }, + RangeCheck { + value: ParsedValue, + max_bit_size: u32, + }, + Store { + value: ParsedValue, + address: ParsedValue, + }, + Truncate { + target: Identifier, + value: ParsedValue, + bit_size: u32, + max_bit_size: u32, + }, +} + +#[derive(Debug)] +pub(crate) enum ParsedTerminator { + Jmp { destination: Identifier, arguments: Vec }, + Jmpif { condition: ParsedValue, then_block: Identifier, else_block: Identifier }, + Return(Vec), +} + +#[derive(Debug)] +pub(crate) enum ParsedValue { + NumericConstant { constant: FieldElement, typ: Type }, + Array { values: Vec, typ: Type }, + Variable(Identifier), +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/into_ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/into_ssa.rs new file mode 100644 index 00000000000..2a94a4fd1eb --- /dev/null +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/into_ssa.rs @@ -0,0 +1,317 @@ +use std::collections::HashMap; + +use im::Vector; + +use crate::ssa::{ + function_builder::FunctionBuilder, + ir::{basic_block::BasicBlockId, function::FunctionId, value::ValueId}, +}; + +use super::{ + Identifier, ParsedBlock, ParsedFunction, ParsedInstruction, ParsedSsa, ParsedTerminator, + ParsedValue, RuntimeType, Ssa, SsaError, +}; + +impl ParsedSsa { + pub(crate) fn into_ssa(self) -> Result { + Translator::translate(self) + } +} + +struct Translator { + builder: FunctionBuilder, + + /// Maps function names to their IDs + functions: HashMap, + + /// Maps block names to their IDs + blocks: HashMap>, + + /// Maps variable names to their IDs + variables: HashMap>, +} + +impl Translator { + fn translate(mut parsed_ssa: ParsedSsa) -> Result { + let mut translator = Self::new(&mut parsed_ssa)?; + + // Note that the `new` call above removed the main function, + // so all we are left with are non-main functions. + for function in parsed_ssa.functions { + translator.translate_non_main_function(function)?; + } + + Ok(translator.finish()) + } + + fn new(parsed_ssa: &mut ParsedSsa) -> Result { + // A FunctionBuilder must be created with a main Function, so here wer remove it + // from the parsed SSA to avoid adding it twice later on. + let main_function = parsed_ssa.functions.remove(0); + let main_id = FunctionId::new(0); + let mut builder = FunctionBuilder::new(main_function.external_name.clone(), main_id); + builder.set_runtime(main_function.runtime_type); + + // Map function names to their IDs so calls can be resolved + let mut function_id_counter = 1; + let mut functions = HashMap::new(); + for function in &parsed_ssa.functions { + let function_id = FunctionId::new(function_id_counter); + function_id_counter += 1; + + functions.insert(function.internal_name.clone(), function_id); + } + + let mut translator = + Self { builder, functions, variables: HashMap::new(), blocks: HashMap::new() }; + translator.translate_function_body(main_function)?; + + Ok(translator) + } + + fn translate_non_main_function(&mut self, function: ParsedFunction) -> Result<(), SsaError> { + let function_id = self.functions[&function.internal_name]; + let external_name = function.external_name.clone(); + + match function.runtime_type { + RuntimeType::Acir(inline_type) => { + self.builder.new_function(external_name, function_id, inline_type); + } + RuntimeType::Brillig(inline_type) => { + self.builder.new_brillig_function(external_name, function_id, inline_type); + } + } + + self.translate_function_body(function) + } + + fn translate_function_body(&mut self, function: ParsedFunction) -> Result<(), SsaError> { + // First define all blocks so that they are known (a block might jump to a block that comes next) + for (index, block) in function.blocks.iter().enumerate() { + // The first block is the entry block and it was automatically created by the builder + let block_id = if index == 0 { + self.builder.current_function.entry_block() + } else { + self.builder.insert_block() + }; + let entry = self.blocks.entry(self.current_function_id()).or_default(); + entry.insert(block.name.clone(), block_id); + } + + for block in function.blocks { + self.translate_block(block)?; + } + + Ok(()) + } + + fn translate_block(&mut self, block: ParsedBlock) -> Result<(), SsaError> { + let block_id = self.blocks[&self.current_function_id()][&block.name]; + self.builder.switch_to_block(block_id); + + for parameter in block.parameters { + let parameter_value_id = self.builder.add_block_parameter(block_id, parameter.typ); + self.define_variable(parameter.identifier, parameter_value_id)?; + } + + for instruction in block.instructions { + self.translate_instruction(instruction)?; + } + + match block.terminator { + ParsedTerminator::Jmp { destination, arguments } => { + let block_id = self.lookup_block(destination)?; + let arguments = self.translate_values(arguments)?; + self.builder.terminate_with_jmp(block_id, arguments); + } + ParsedTerminator::Jmpif { condition, then_block, else_block } => { + let condition = self.translate_value(condition)?; + let then_destination = self.lookup_block(then_block)?; + let else_destination = self.lookup_block(else_block)?; + self.builder.terminate_with_jmpif(condition, then_destination, else_destination); + } + ParsedTerminator::Return(values) => { + let return_values = self.translate_values(values)?; + self.builder.terminate_with_return(return_values); + } + } + + Ok(()) + } + + fn translate_instruction(&mut self, instruction: ParsedInstruction) -> Result<(), SsaError> { + match instruction { + ParsedInstruction::Allocate { target, typ } => { + let value_id = self.builder.insert_allocate(typ); + self.define_variable(target, value_id)?; + } + ParsedInstruction::ArrayGet { target, element_type, array, index } => { + let array = self.translate_value(array)?; + let index = self.translate_value(index)?; + let value_id = self.builder.insert_array_get(array, index, element_type); + self.define_variable(target, value_id)?; + } + ParsedInstruction::ArraySet { target, array, index, value, mutable } => { + let array = self.translate_value(array)?; + let index = self.translate_value(index)?; + let value = self.translate_value(value)?; + let value_id = if mutable { + self.builder.insert_mutable_array_set(array, index, value) + } else { + self.builder.insert_array_set(array, index, value) + }; + self.define_variable(target, value_id)?; + } + ParsedInstruction::BinaryOp { target, lhs, op, rhs } => { + let lhs = self.translate_value(lhs)?; + let rhs = self.translate_value(rhs)?; + let value_id = self.builder.insert_binary(lhs, op, rhs); + self.define_variable(target, value_id)?; + } + ParsedInstruction::Call { targets, function, arguments, types } => { + let function_id = if let Some(id) = self.builder.import_intrinsic(&function.name) { + id + } else { + let function_id = self.lookup_function(function)?; + self.builder.import_function(function_id) + }; + + let arguments = self.translate_values(arguments)?; + + let value_ids = self.builder.insert_call(function_id, arguments, types).to_vec(); + + if value_ids.len() != targets.len() { + return Err(SsaError::MismatchedReturnValues { + returns: targets, + expected: value_ids.len(), + }); + } + + for (target, value_id) in targets.into_iter().zip(value_ids.into_iter()) { + self.define_variable(target, value_id)?; + } + } + ParsedInstruction::Cast { target, lhs, typ } => { + let lhs = self.translate_value(lhs)?; + let value_id = self.builder.insert_cast(lhs, typ); + self.define_variable(target, value_id)?; + } + ParsedInstruction::Constrain { lhs, rhs } => { + let lhs = self.translate_value(lhs)?; + let rhs = self.translate_value(rhs)?; + self.builder.insert_constrain(lhs, rhs, None); + } + ParsedInstruction::DecrementRc { value } => { + let value = self.translate_value(value)?; + self.builder.decrement_array_reference_count(value); + } + ParsedInstruction::EnableSideEffectsIf { condition } => { + let condition = self.translate_value(condition)?; + self.builder.insert_enable_side_effects_if(condition); + } + ParsedInstruction::IncrementRc { value } => { + let value = self.translate_value(value)?; + self.builder.increment_array_reference_count(value); + } + ParsedInstruction::Load { target, value, typ } => { + let value = self.translate_value(value)?; + let value_id = self.builder.insert_load(value, typ); + self.define_variable(target, value_id)?; + } + ParsedInstruction::Not { target, value } => { + let value = self.translate_value(value)?; + let value_id = self.builder.insert_not(value); + self.define_variable(target, value_id)?; + } + ParsedInstruction::RangeCheck { value, max_bit_size } => { + let value = self.translate_value(value)?; + self.builder.insert_range_check(value, max_bit_size, None); + } + ParsedInstruction::Store { value, address } => { + let value = self.translate_value(value)?; + let address = self.translate_value(address)?; + self.builder.insert_store(address, value); + } + ParsedInstruction::Truncate { target, value, bit_size, max_bit_size } => { + let value = self.translate_value(value)?; + let value_id = self.builder.insert_truncate(value, bit_size, max_bit_size); + self.define_variable(target, value_id)?; + } + } + + Ok(()) + } + + fn translate_values(&mut self, values: Vec) -> Result, SsaError> { + let mut translated_values = Vec::with_capacity(values.len()); + for value in values { + translated_values.push(self.translate_value(value)?); + } + Ok(translated_values) + } + + fn translate_value(&mut self, value: ParsedValue) -> Result { + match value { + ParsedValue::NumericConstant { constant, typ } => { + Ok(self.builder.numeric_constant(constant, typ)) + } + ParsedValue::Array { values, typ } => { + let mut translated_values = Vector::new(); + for value in values { + translated_values.push_back(self.translate_value(value)?); + } + Ok(self.builder.array_constant(translated_values, typ)) + } + ParsedValue::Variable(identifier) => self.lookup_variable(identifier), + } + } + + fn define_variable( + &mut self, + identifier: Identifier, + value_id: ValueId, + ) -> Result<(), SsaError> { + if let Some(vars) = self.variables.get(&self.current_function_id()) { + if vars.contains_key(&identifier.name) { + return Err(SsaError::VariableAlreadyDefined(identifier)); + } + } + + let entry = self.variables.entry(self.current_function_id()).or_default(); + entry.insert(identifier.name, value_id); + + Ok(()) + } + + fn lookup_variable(&mut self, identifier: Identifier) -> Result { + if let Some(value_id) = self.variables[&self.current_function_id()].get(&identifier.name) { + Ok(*value_id) + } else { + Err(SsaError::UnknownVariable(identifier)) + } + } + + fn lookup_block(&mut self, identifier: Identifier) -> Result { + if let Some(block_id) = self.blocks[&self.current_function_id()].get(&identifier.name) { + Ok(*block_id) + } else { + Err(SsaError::UnknownBlock(identifier)) + } + } + + fn lookup_function(&mut self, identifier: Identifier) -> Result { + if let Some(function_id) = self.functions.get(&identifier.name) { + Ok(*function_id) + } else { + Err(SsaError::UnknownFunction(identifier)) + } + } + + fn finish(self) -> Ssa { + self.builder.finish() + } + + fn current_function_id(&self) -> FunctionId { + self.builder.current_function.id() + } +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/lexer.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/lexer.rs new file mode 100644 index 00000000000..ac4c3b77205 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/lexer.rs @@ -0,0 +1,259 @@ +use std::str::{CharIndices, FromStr}; + +use acvm::{AcirField, FieldElement}; +use noirc_errors::{Position, Span}; +use noirc_frontend::token::IntType; +use num_bigint::BigInt; +use num_traits::{Num, One}; +use thiserror::Error; + +use super::token::{Keyword, SpannedToken, Token}; + +pub(crate) struct Lexer<'a> { + chars: CharIndices<'a>, + position: Position, + done: bool, + max_integer: BigInt, +} + +impl<'a> Lexer<'a> { + pub(crate) fn new(source: &'a str) -> Self { + Lexer { + chars: source.char_indices(), + position: 0, + done: false, + max_integer: BigInt::from_biguint(num_bigint::Sign::Plus, FieldElement::modulus()) + - BigInt::one(), + } + } + + pub(crate) fn next_token(&mut self) -> SpannedTokenResult { + match self.next_char() { + Some(char) if char.is_ascii_whitespace() => { + while let Some(char) = self.peek_char() { + if char.is_ascii_whitespace() { + self.next_char(); + } else { + break; + } + } + self.next_token() + } + Some('/') if self.peek_char() == Some('/') => { + while let Some(char) = self.next_char() { + if char == '\n' { + break; + } + } + self.next_token() + } + Some('=') if self.peek_char() == Some('=') => self.double_char_token(Token::Equal), + Some('=') => self.single_char_token(Token::Assign), + Some(',') => self.single_char_token(Token::Comma), + Some(':') => self.single_char_token(Token::Colon), + Some(';') => self.single_char_token(Token::Semicolon), + Some('(') => self.single_char_token(Token::LeftParen), + Some(')') => self.single_char_token(Token::RightParen), + Some('{') => self.single_char_token(Token::LeftBrace), + Some('}') => self.single_char_token(Token::RightBrace), + Some('[') => self.single_char_token(Token::LeftBracket), + Some(']') => self.single_char_token(Token::RightBracket), + Some('&') => self.single_char_token(Token::Ampersand), + Some('-') if self.peek_char() == Some('>') => self.double_char_token(Token::Arrow), + Some(ch) if ch.is_ascii_alphanumeric() || ch == '_' => self.eat_alpha_numeric(ch), + Some(char) => Err(LexerError::UnexpectedCharacter { + char, + span: Span::single_char(self.position), + }), + None => { + self.done = true; + Ok(Token::Eof.into_single_span(self.position)) + } + } + } + + fn eat_alpha_numeric(&mut self, initial_char: char) -> SpannedTokenResult { + match initial_char { + 'A'..='Z' | 'a'..='z' | '_' => Ok(self.eat_word(initial_char)?), + '0'..='9' => self.eat_digit(initial_char), + _ => Err(LexerError::UnexpectedCharacter { + char: initial_char, + span: Span::single_char(self.position), + }), + } + } + + fn eat_word(&mut self, initial_char: char) -> SpannedTokenResult { + let (start, word, end) = self.lex_word(initial_char); + self.lookup_word_token(word, start, end) + } + + fn lex_word(&mut self, initial_char: char) -> (Position, String, Position) { + let start = self.position; + let word = self.eat_while(Some(initial_char), |ch| { + ch.is_ascii_alphabetic() || ch.is_numeric() || ch == '_' + }); + (start, word, self.position) + } + + fn lookup_word_token( + &self, + word: String, + start: Position, + end: Position, + ) -> SpannedTokenResult { + // Check if word either an identifier or a keyword + if let Some(keyword_token) = Keyword::lookup_keyword(&word) { + return Ok(keyword_token.into_span(start, end)); + } + + // Check if word an int type + // if no error occurred, then it is either a valid integer type or it is not an int type + let parsed_token = IntType::lookup_int_type(&word); + + // Check if it is an int type + if let Some(int_type) = parsed_token { + return Ok(Token::IntType(int_type).into_span(start, end)); + } + + // Else it is just an identifier + let ident_token = Token::Ident(word); + Ok(ident_token.into_span(start, end)) + } + + fn eat_digit(&mut self, initial_char: char) -> SpannedTokenResult { + let start = self.position; + + let integer_str = self.eat_while(Some(initial_char), |ch| { + ch.is_ascii_digit() | ch.is_ascii_hexdigit() | (ch == 'x') | (ch == '_') + }); + + let end = self.position; + + // We want to enforce some simple rules about usage of underscores: + // 1. Underscores cannot appear at the end of a integer literal. e.g. 0x123_. + // 2. There cannot be more than one underscore consecutively, e.g. 0x5__5, 5__5. + // + // We're not concerned with an underscore at the beginning of a decimal literal + // such as `_5` as this would be lexed into an ident rather than an integer literal. + let invalid_underscore_location = integer_str.ends_with('_'); + let consecutive_underscores = integer_str.contains("__"); + if invalid_underscore_location || consecutive_underscores { + return Err(LexerError::InvalidIntegerLiteral { + span: Span::inclusive(start, end), + found: integer_str, + }); + } + + // Underscores needs to be stripped out before the literal can be converted to a `FieldElement. + let integer_str = integer_str.replace('_', ""); + + let bigint_result = match integer_str.strip_prefix("0x") { + Some(integer_str) => BigInt::from_str_radix(integer_str, 16), + None => BigInt::from_str(&integer_str), + }; + + let integer = match bigint_result { + Ok(bigint) => { + if bigint > self.max_integer { + return Err(LexerError::IntegerLiteralTooLarge { + span: Span::inclusive(start, end), + limit: self.max_integer.to_string(), + }); + } + let big_uint = bigint.magnitude(); + FieldElement::from_be_bytes_reduce(&big_uint.to_bytes_be()) + } + Err(_) => { + return Err(LexerError::InvalidIntegerLiteral { + span: Span::inclusive(start, end), + found: integer_str, + }) + } + }; + + let integer_token = Token::Int(integer); + Ok(integer_token.into_span(start, end)) + } + + fn eat_while bool>( + &mut self, + initial_char: Option, + predicate: F, + ) -> String { + // This function is only called when we want to continue consuming a character of the same type. + // For example, we see a digit and we want to consume the whole integer + // Therefore, the current character which triggered this function will need to be appended + let mut word = String::new(); + if let Some(init_char) = initial_char { + word.push(init_char); + } + + // Keep checking that we are not at the EOF + while let Some(peek_char) = self.peek_char() { + // Then check for the predicate, if predicate matches append char and increment the cursor + // If not, return word. The next character will be analyzed on the next iteration of next_token, + // Which will increment the cursor + if !predicate(peek_char) { + return word; + } + word.push(peek_char); + + // If we arrive at this point, then the char has been added to the word and we should increment the cursor + self.next_char(); + } + + word + } + + fn single_char_token(&self, token: Token) -> SpannedTokenResult { + Ok(token.into_single_span(self.position)) + } + + fn double_char_token(&mut self, token: Token) -> SpannedTokenResult { + let start_position = self.position; + self.next_char(); + Ok(token.into_span(start_position, self.position)) + } + + fn next_char(&mut self) -> Option { + let (position, ch) = self.chars.next()?; + self.position = position as u32; + Some(ch) + } + + fn peek_char(&self) -> Option { + self.chars.clone().next().map(|(_, ch)| ch) + } + + fn is_code_whitespace(c: char) -> bool { + c.is_ascii_whitespace() + } + + pub(crate) fn newline_follows(&self) -> bool { + let chars = self.chars.clone(); + chars.take_while(|(_, char)| char.is_ascii_whitespace()).any(|(_, char)| char == '\n') + } +} + +type SpannedTokenResult = Result; + +#[derive(Debug, Error)] +pub(crate) enum LexerError { + #[error("Unexpected character: {char:?}")] + UnexpectedCharacter { char: char, span: Span }, + #[error("Invalid integer literal")] + InvalidIntegerLiteral { span: Span, found: String }, + #[error("Integer literal too large")] + IntegerLiteralTooLarge { span: Span, limit: String }, +} + +impl LexerError { + pub(crate) fn span(&self) -> Span { + match self { + LexerError::UnexpectedCharacter { span, .. } + | LexerError::InvalidIntegerLiteral { span, .. } + | LexerError::IntegerLiteralTooLarge { span, .. } => *span, + } + } +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/tests.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/tests.rs new file mode 100644 index 00000000000..3ed6be57b5e --- /dev/null +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/tests.rs @@ -0,0 +1,427 @@ +#![cfg(test)] + +use crate::{ + ssa::{opt::assert_normalized_ssa_equals, Ssa}, + trim_leading_whitespace_from_lines, +}; + +fn assert_ssa_roundtrip(src: &str) { + let ssa = Ssa::from_str(src).unwrap(); + let ssa = ssa.to_string(); + let ssa = trim_leading_whitespace_from_lines(&ssa); + let src = trim_leading_whitespace_from_lines(src); + if ssa != src { + println!("Expected:\n~~~\n{}\n~~~\nGot:\n~~~\n{}\n~~~", src, ssa); + similar_asserts::assert_eq!(ssa, src); + } +} + +#[test] +fn test_empty_acir_function() { + let src = " + acir(inline) fn main f0 { + b0(): + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_empty_brillig_function() { + let src = " + brillig(inline) fn main f0 { + b0(): + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_return_integer() { + for typ in ["u1", "u8", "u16", "u32", "u64", "i1", "i8", "i16", "i32", "i64", "Field"] { + let src = format!( + " + acir(inline) fn main f0 {{ + b0(): + return {typ} 1 + }} + " + ); + assert_ssa_roundtrip(&src); + } +} + +#[test] +fn test_return_array() { + let src = " + acir(inline) fn main f0 { + b0(): + return [Field 1] of Field + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_return_empty_array() { + let src = " + acir(inline) fn main f0 { + b0(): + return [] of Field + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_return_composite_array() { + let src = " + acir(inline) fn main f0 { + b0(): + return [Field 1, Field 2] of (Field, Field) + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_block_parameters() { + let src = " + acir(inline) fn main f0 { + b0(v0: Field, v1: Field): + return v0, v1 + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_multiple_blocks_and_jmp() { + let src = " + acir(inline) fn main f0 { + b0(): + jmp b1(Field 1) + b1(v1: Field): + return v1 + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_jmpif() { + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + jmpif v0 then: b1, else: b2 + b1(): + return + b2(): + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_call() { + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + v2 = call f1(v0) -> Field + return v2 + } + acir(inline) fn foo f1 { + b0(v0: Field): + return v0 + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_call_multiple_return_values() { + let src = " + acir(inline) fn main f0 { + b0(): + v1, v2 = call f1() -> ([Field; 3], [Field; 1]) + return v1 + } + acir(inline) fn foo f1 { + b0(): + return [Field 1, Field 2, Field 3] of Field, [Field 4] of Field + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_call_no_return_value() { + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + call f1(v0) + return + } + acir(inline) fn foo f1 { + b0(v0: Field): + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_call_intrinsic() { + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + call assert_constant(v0) + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_cast() { + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + v1 = cast v0 as i32 + return v1 + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_constrain() { + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + constrain v0 == Field 1 + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_enable_side_effects() { + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + enable_side_effects v0 + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_array_get() { + let src = " + acir(inline) fn main f0 { + b0(v0: [Field; 3]): + v2 = array_get v0, index Field 0 -> Field + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_array_set() { + let src = " + acir(inline) fn main f0 { + b0(v0: [Field; 3]): + v3 = array_set v0, index Field 0, value Field 1 + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_mutable_array_set() { + let src = " + acir(inline) fn main f0 { + b0(v0: [Field; 3]): + v3 = array_set mut v0, index Field 0, value Field 1 + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_array_get_set_bug() { + let src = " + acir(inline) fn main f0 { + b0(v0: [u32; 3]): + v3 = array_set v0, index u32 1, value u32 2 + v5 = array_get v3, index u32 0 -> u32 + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_binary() { + for op in ["add", "sub", "mul", "div", "eq", "mod", "lt", "and", "or", "xor", "shl", "shr"] { + let src = format!( + " + acir(inline) fn main f0 {{ + b0(v0: Field, v1: Field): + v2 = {op} v0, v1 + return + }} + " + ); + assert_ssa_roundtrip(&src); + } +} + +#[test] +fn test_truncate() { + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + v1 = truncate v0 to 8 bits, max_bit_size: 16 + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_not() { + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + v1 = not v0 + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_range_check() { + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + range_check v0 to 8 bits + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_allocate() { + let src = " + acir(inline) fn main f0 { + b0(): + v0 = allocate -> &mut [Field; 3] + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_load() { + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + v1 = load v0 -> Field + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_store() { + let src = " + acir(inline) fn main f0 { + b0(v0: Field): + store Field 1 at v0 + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_inc_rc() { + let src = " + acir(inline) fn main f0 { + b0(v0: [Field; 3]): + inc_rc v0 + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_dec_rc() { + let src = " + acir(inline) fn main f0 { + b0(v0: [Field; 3]): + dec_rc v0 + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_mutable_reference_type() { + let src = " + acir(inline) fn main f0 { + b0(v0: &mut Field): + return + } + "; + assert_ssa_roundtrip(src); +} + +#[test] +fn test_parses_with_comments() { + let src = " + // This is a comment + acir(inline) fn main f0 { + b0(v0: &mut Field): // This is a block + return // Returns nothing + } + "; + + let expected = " + acir(inline) fn main f0 { + b0(v0: &mut Field): + return + } + "; + + let ssa = Ssa::from_str(src).unwrap(); + assert_normalized_ssa_equals(ssa, expected); +} + +#[test] +fn test_slice() { + let src = " + acir(inline) fn main f0 { + b0(v0: [Field; 3]): + v2, v3 = call as_slice(v0) -> (u32, [Field]) + return + } + "; + assert_ssa_roundtrip(src); +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/token.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/token.rs new file mode 100644 index 00000000000..41c4f9ca164 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/parser/token.rs @@ -0,0 +1,269 @@ +use std::fmt::Display; + +use acvm::FieldElement; +use noirc_errors::{Position, Span, Spanned}; +use noirc_frontend::token::IntType; + +#[derive(Debug)] +pub(crate) struct SpannedToken(Spanned); + +impl SpannedToken { + pub(crate) fn new(token: Token, span: Span) -> SpannedToken { + SpannedToken(Spanned::from(span, token)) + } + + pub(crate) fn to_span(&self) -> Span { + self.0.span() + } + + pub(crate) fn token(&self) -> &Token { + &self.0.contents + } + + pub(crate) fn into_token(self) -> Token { + self.0.contents + } +} + +#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub(crate) enum Token { + Ident(String), + Int(FieldElement), + Keyword(Keyword), + IntType(IntType), + /// = + Assign, + /// ( + LeftParen, + /// ) + RightParen, + /// { + LeftBrace, + /// } + RightBrace, + /// [ + LeftBracket, + /// ] + RightBracket, + /// , + Comma, + /// : + Colon, + /// ; + Semicolon, + /// -> + Arrow, + /// == + Equal, + /// & + Ampersand, + Eof, +} + +impl Token { + pub(super) fn into_single_span(self, position: Position) -> SpannedToken { + self.into_span(position, position) + } + + pub(super) fn into_span(self, start: Position, end: Position) -> SpannedToken { + SpannedToken(Spanned::from_position(start, end, self)) + } +} + +impl Display for Token { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Token::Ident(ident) => write!(f, "{}", ident), + Token::Int(int) => write!(f, "{}", int), + Token::Keyword(keyword) => write!(f, "{}", keyword), + Token::IntType(int_type) => write!(f, "{}", int_type), + Token::Assign => write!(f, "="), + Token::LeftParen => write!(f, "("), + Token::RightParen => write!(f, ")"), + Token::LeftBrace => write!(f, "{{"), + Token::RightBrace => write!(f, "}}"), + Token::LeftBracket => write!(f, "["), + Token::RightBracket => write!(f, "]"), + Token::Comma => write!(f, ","), + Token::Colon => write!(f, ":"), + Token::Semicolon => write!(f, ";"), + Token::Arrow => write!(f, "->"), + Token::Equal => write!(f, "=="), + Token::Ampersand => write!(f, "&"), + Token::Eof => write!(f, "(end of stream)"), + } + } +} + +impl std::fmt::Debug for Token { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self) + } +} + +#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub(crate) enum Keyword { + Acir, + Add, + Allocate, + And, + ArrayGet, + ArraySet, + As, + At, + Bits, + Bool, + Brillig, + Call, + Cast, + Constrain, + DecRc, + Div, + Inline, + InlineAlways, + Else, + EnableSideEffects, + Eq, + Field, + Fold, + Fn, + IncRc, + Index, + Jmp, + Jmpif, + Load, + Lt, + MaxBitSize, + Mod, + Mul, + Mut, + NoPredicates, + Not, + Of, + Or, + RangeCheck, + Return, + Shl, + Shr, + Store, + Sub, + Then, + To, + Truncate, + Value, + Xor, +} + +impl Keyword { + pub(crate) fn lookup_keyword(word: &str) -> Option { + let keyword = match word { + "acir" => Keyword::Acir, + "add" => Keyword::Add, + "allocate" => Keyword::Allocate, + "and" => Keyword::And, + "array_get" => Keyword::ArrayGet, + "array_set" => Keyword::ArraySet, + "as" => Keyword::As, + "at" => Keyword::At, + "bits" => Keyword::Bits, + "bool" => Keyword::Bool, + "brillig" => Keyword::Brillig, + "call" => Keyword::Call, + "cast" => Keyword::Cast, + "constrain" => Keyword::Constrain, + "dec_rc" => Keyword::DecRc, + "div" => Keyword::Div, + "else" => Keyword::Else, + "enable_side_effects" => Keyword::EnableSideEffects, + "eq" => Keyword::Eq, + "inline" => Keyword::Inline, + "inline_always" => Keyword::InlineAlways, + "Field" => Keyword::Field, + "fold" => Keyword::Fold, + "fn" => Keyword::Fn, + "inc_rc" => Keyword::IncRc, + "index" => Keyword::Index, + "jmp" => Keyword::Jmp, + "jmpif" => Keyword::Jmpif, + "load" => Keyword::Load, + "lt" => Keyword::Lt, + "max_bit_size" => Keyword::MaxBitSize, + "mod" => Keyword::Mod, + "mul" => Keyword::Mul, + "mut" => Keyword::Mut, + "no_predicates" => Keyword::NoPredicates, + "not" => Keyword::Not, + "of" => Keyword::Of, + "or" => Keyword::Or, + "range_check" => Keyword::RangeCheck, + "return" => Keyword::Return, + "shl" => Keyword::Shl, + "shr" => Keyword::Shr, + "store" => Keyword::Store, + "sub" => Keyword::Sub, + "then" => Keyword::Then, + "to" => Keyword::To, + "truncate" => Keyword::Truncate, + "value" => Keyword::Value, + "xor" => Keyword::Xor, + _ => return None, + }; + Some(Token::Keyword(keyword)) + } +} + +impl Display for Keyword { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Keyword::Acir => write!(f, "acir"), + Keyword::Add => write!(f, "add"), + Keyword::Allocate => write!(f, "allocate"), + Keyword::And => write!(f, "and"), + Keyword::ArrayGet => write!(f, "array_get"), + Keyword::ArraySet => write!(f, "array_set"), + Keyword::As => write!(f, "as"), + Keyword::At => write!(f, "at"), + Keyword::Bits => write!(f, "bits"), + Keyword::Bool => write!(f, "bool"), + Keyword::Brillig => write!(f, "brillig"), + Keyword::Call => write!(f, "call"), + Keyword::Cast => write!(f, "cast"), + Keyword::Constrain => write!(f, "constrain"), + Keyword::DecRc => write!(f, "dec_rc"), + Keyword::Div => write!(f, "div"), + Keyword::Else => write!(f, "else"), + Keyword::EnableSideEffects => write!(f, "enable_side_effects"), + Keyword::Eq => write!(f, "eq"), + Keyword::Field => write!(f, "Field"), + Keyword::Fold => write!(f, "fold"), + Keyword::Fn => write!(f, "fn"), + Keyword::IncRc => write!(f, "inc_rc"), + Keyword::Index => write!(f, "index"), + Keyword::Inline => write!(f, "inline"), + Keyword::InlineAlways => write!(f, "inline_always"), + Keyword::Jmp => write!(f, "jmp"), + Keyword::Jmpif => write!(f, "jmpif"), + Keyword::Load => write!(f, "load"), + Keyword::Lt => write!(f, "lt"), + Keyword::MaxBitSize => write!(f, "max_bit_size"), + Keyword::Mod => write!(f, "mod"), + Keyword::Mul => write!(f, "mul"), + Keyword::Mut => write!(f, "mut"), + Keyword::NoPredicates => write!(f, "no_predicates"), + Keyword::Not => write!(f, "not"), + Keyword::Of => write!(f, "of"), + Keyword::Or => write!(f, "or"), + Keyword::RangeCheck => write!(f, "range_check"), + Keyword::Return => write!(f, "return"), + Keyword::Shl => write!(f, "shl"), + Keyword::Shr => write!(f, "shr"), + Keyword::Store => write!(f, "store"), + Keyword::Sub => write!(f, "sub"), + Keyword::Then => write!(f, "then"), + Keyword::To => write!(f, "to"), + Keyword::Truncate => write!(f, "truncate"), + Keyword::Value => write!(f, "value"), + Keyword::Xor => write!(f, "xor"), + } + } +} diff --git a/noir/noir-repo/compiler/noirc_frontend/Cargo.toml b/noir/noir-repo/compiler/noirc_frontend/Cargo.toml index d729dabcb04..581d7f1b61d 100644 --- a/noir/noir-repo/compiler/noirc_frontend/Cargo.toml +++ b/noir/noir-repo/compiler/noirc_frontend/Cargo.toml @@ -36,6 +36,8 @@ strum_macros = "0.24" [dev-dependencies] base64.workspace = true +proptest.workspace = true +proptest-derive = "0.5.0" [features] experimental_parser = [] diff --git a/noir/noir-repo/compiler/noirc_frontend/proptest-regressions/hir_def/types/arithmetic.txt b/noir/noir-repo/compiler/noirc_frontend/proptest-regressions/hir_def/types/arithmetic.txt new file mode 100644 index 00000000000..80f5c7f1ead --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/proptest-regressions/hir_def/types/arithmetic.txt @@ -0,0 +1,7 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc fc27f4091dfa5f938973048209b5fcf22aefa1cfaffaaa3e349f30e9b1f93f49 # shrinks to infix_and_bindings = (((0: numeric bool) % (Numeric(Shared(RefCell { value: Unbound('2, Numeric(bool)) }): bool) + Numeric(Shared(RefCell { value: Unbound('0, Numeric(bool)) }): bool))), [('0, (0: numeric bool)), ('1, (0: numeric bool)), ('2, (0: numeric bool))]) diff --git a/noir/noir-repo/compiler/noirc_frontend/proptest-regressions/tests/arithmetic_generics.txt b/noir/noir-repo/compiler/noirc_frontend/proptest-regressions/tests/arithmetic_generics.txt new file mode 100644 index 00000000000..80f5c7f1ead --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/proptest-regressions/tests/arithmetic_generics.txt @@ -0,0 +1,7 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc fc27f4091dfa5f938973048209b5fcf22aefa1cfaffaaa3e349f30e9b1f93f49 # shrinks to infix_and_bindings = (((0: numeric bool) % (Numeric(Shared(RefCell { value: Unbound('2, Numeric(bool)) }): bool) + Numeric(Shared(RefCell { value: Unbound('0, Numeric(bool)) }): bool))), [('0, (0: numeric bool)), ('1, (0: numeric bool)), ('2, (0: numeric bool))]) 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 67ddffe3277..2c8a9b6508d 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs @@ -98,7 +98,7 @@ impl UnresolvedGeneric { UnresolvedGeneric::Variable(_) => Ok(Kind::Normal), UnresolvedGeneric::Numeric { typ, .. } => { let typ = self.resolve_numeric_kind_type(typ)?; - Ok(Kind::Numeric(Box::new(typ))) + Ok(Kind::numeric(typ)) } UnresolvedGeneric::Resolved(..) => { panic!("Don't know the kind of a resolved generic here") @@ -504,7 +504,7 @@ impl FunctionDefinition { } pub fn is_test(&self) -> bool { - if let Some(attribute) = &self.attributes.function { + if let Some(attribute) = self.attributes.function() { matches!(attribute, FunctionAttribute::Test(..)) } else { false diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/function.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/function.rs index beeea3ffac5..99ae78c93ea 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/function.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/function.rs @@ -77,7 +77,7 @@ impl NoirFunction { &self.def.attributes } pub fn function_attribute(&self) -> Option<&FunctionAttribute> { - self.def.attributes.function.as_ref() + self.def.attributes.function() } pub fn secondary_attributes(&self) -> &[SecondaryAttribute] { self.def.attributes.secondary.as_ref() @@ -108,7 +108,7 @@ impl NoirFunction { impl From for NoirFunction { fn from(fd: FunctionDefinition) -> Self { // The function type is determined by the existence of a function attribute - let kind = match fd.attributes.function { + let kind = match fd.attributes.function() { Some(FunctionAttribute::Builtin(_)) => FunctionKind::Builtin, Some(FunctionAttribute::Foreign(_)) => FunctionKind::LowLevel, Some(FunctionAttribute::Test { .. }) => FunctionKind::Normal, 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 e85563691ba..3c6664dd569 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs @@ -19,6 +19,9 @@ pub use visitor::Visitor; pub use expression::*; pub use function::*; +#[cfg(test)] +use proptest_derive::Arbitrary; + use acvm::FieldElement; pub use docs::*; use noirc_errors::Span; @@ -37,6 +40,7 @@ use crate::{ use acvm::acir::AcirField; use iter_extended::vecmap; +#[cfg_attr(test, derive(Arbitrary))] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Ord, PartialOrd)] pub enum IntegerBitSize { One, 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 49f585894d9..7244be371af 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs @@ -445,11 +445,6 @@ impl Path { self.span } - pub fn first_segment(&self) -> PathSegment { - assert!(!self.segments.is_empty()); - self.segments.first().unwrap().clone() - } - pub fn last_segment(&self) -> PathSegment { assert!(!self.segments.is_empty()); self.segments.last().unwrap().clone() @@ -459,9 +454,8 @@ impl Path { self.last_segment().ident } - pub fn first_name(&self) -> &str { - assert!(!self.segments.is_empty()); - &self.segments.first().unwrap().ident.0.contents + pub fn first_name(&self) -> Option<&str> { + self.segments.first().map(|segment| segment.ident.0.contents.as_str()) } pub fn last_name(&self) -> &str { 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 9e12b29677c..f149c998eca 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/visitor.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/visitor.rs @@ -16,7 +16,7 @@ use crate::{ InternedUnresolvedTypeData, QuotedTypeId, }, parser::{Item, ItemKind, ParsedSubModule}, - token::{CustomAttribute, SecondaryAttribute, Tokens}, + token::{MetaAttribute, SecondaryAttribute, Tokens}, ParsedModule, QuotedType, }; @@ -474,7 +474,9 @@ pub trait Visitor { true } - fn visit_custom_attribute(&mut self, _: &CustomAttribute, _target: AttributeTarget) {} + fn visit_meta_attribute(&mut self, _: &MetaAttribute, _target: AttributeTarget) -> bool { + true + } } impl ParsedModule { @@ -1441,15 +1443,22 @@ impl SecondaryAttribute { } pub fn accept_children(&self, target: AttributeTarget, visitor: &mut impl Visitor) { - if let SecondaryAttribute::Meta(custom) = self { - custom.accept(target, visitor); + if let SecondaryAttribute::Meta(meta_attribute) = self { + meta_attribute.accept(target, visitor); } } } -impl CustomAttribute { +impl MetaAttribute { pub fn accept(&self, target: AttributeTarget, visitor: &mut impl Visitor) { - visitor.visit_custom_attribute(self, target); + if visitor.visit_meta_attribute(self, target) { + self.accept_children(visitor); + } + } + + pub fn accept_children(&self, visitor: &mut impl Visitor) { + self.name.accept(visitor); + visit_expressions(&self.arguments, visitor); } } 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 13f51abe6ba..279adc331ea 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/comptime.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/comptime.rs @@ -19,10 +19,9 @@ use crate::{ resolution::errors::ResolverError, }, hir_def::expr::{HirExpression, HirIdent}, - lexer::Lexer, node_interner::{DefinitionKind, DependencyId, FuncId, NodeInterner, StructId, TraitId}, - parser::{Item, ItemKind, Parser}, - token::SecondaryAttribute, + parser::{Item, ItemKind}, + token::{MetaAttribute, SecondaryAttribute}, Type, TypeBindings, UnificationError, }; @@ -162,10 +161,9 @@ impl<'context> Elaborator<'context> { if let SecondaryAttribute::Meta(attribute) = attribute { self.elaborate_in_comptime_context(|this| { if let Err(error) = this.run_comptime_attribute_name_on_item( - &attribute.contents, + attribute, item.clone(), span, - attribute.contents_span, attribute_context, generated_items, ) { @@ -177,27 +175,21 @@ impl<'context> Elaborator<'context> { fn run_comptime_attribute_name_on_item( &mut self, - attribute: &str, + attribute: &MetaAttribute, item: Value, span: Span, - attribute_span: Span, attribute_context: AttributeContext, generated_items: &mut CollectedItems, ) -> Result<(), (CompilationError, FileId)> { self.file = attribute_context.attribute_file; self.local_module = attribute_context.attribute_module; - let location = Location::new(attribute_span, self.file); - let Some((function, arguments)) = Self::parse_attribute(attribute, location)? else { - return Err(( - ResolverError::UnableToParseAttribute { - attribute: attribute.to_string(), - span: attribute_span, - } - .into(), - self.file, - )); + let location = Location::new(attribute.span, self.file); + let function = Expression { + kind: ExpressionKind::Variable(attribute.name.clone()), + span: attribute.span, }; + let arguments = attribute.arguments.clone(); // Elaborate the function, rolling back any errors generated in case it is unknown let error_count = self.errors.len(); @@ -211,7 +203,7 @@ impl<'context> Elaborator<'context> { return Err(( ResolverError::AttributeFunctionIsNotAPath { function: function_string, - span: attribute_span, + span: attribute.span, } .into(), self.file, @@ -223,7 +215,7 @@ impl<'context> Elaborator<'context> { return Err(( ResolverError::AttributeFunctionNotInScope { name: function_string, - span: attribute_span, + span: attribute.span, } .into(), self.file, @@ -269,38 +261,6 @@ impl<'context> Elaborator<'context> { Ok(()) } - /// Parses an attribute in the form of a function call (e.g. `#[foo(a b, c d)]`) into - /// the function and quoted arguments called (e.g. `("foo", vec![(a b, location), (c d, location)])`) - #[allow(clippy::type_complexity)] - pub(crate) fn parse_attribute( - annotation: &str, - location: Location, - ) -> Result)>, (CompilationError, FileId)> { - let (tokens, mut lexing_errors) = Lexer::lex(annotation); - if !lexing_errors.is_empty() { - return Err((lexing_errors.swap_remove(0).into(), location.file)); - } - - let Some(expression) = Parser::for_tokens(tokens).parse_option(Parser::parse_expression) - else { - return Ok(None); - }; - - let (mut func, mut arguments) = match expression.kind { - ExpressionKind::Call(call) => (*call.func, call.arguments), - ExpressionKind::Variable(_) => (expression, Vec::new()), - _ => return Ok(None), - }; - - func.span = func.span.shift_by(location.span.start()); - - for argument in &mut arguments { - argument.span = argument.span.shift_by(location.span.start()); - } - - Ok(Some((func, arguments))) - } - fn handle_attribute_arguments( interpreter: &mut Interpreter, item: &Value, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/lints.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/lints.rs index 249fed90a60..d3b776bea24 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/lints.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/lints.rs @@ -67,7 +67,7 @@ pub(super) fn low_level_function_outside_stdlib( crate_id: CrateId, ) -> Option { let is_low_level_function = - modifiers.attributes.function.as_ref().map_or(false, |func| func.is_low_level()); + modifiers.attributes.function().map_or(false, |func| func.is_low_level()); if !crate_id.is_stdlib() && is_low_level_function { let ident = func_meta_name_ident(func, modifiers); Some(ResolverError::LowLevelFunctionOutsideOfStdlib { ident }) @@ -81,8 +81,7 @@ pub(super) fn oracle_not_marked_unconstrained( func: &FuncMeta, modifiers: &FunctionModifiers, ) -> Option { - let is_oracle_function = - modifiers.attributes.function.as_ref().map_or(false, |func| func.is_oracle()); + let is_oracle_function = modifiers.attributes.function().map_or(false, |func| func.is_oracle()); if is_oracle_function && !modifiers.is_unconstrained { let ident = func_meta_name_ident(func, modifiers); Some(ResolverError::OracleMarkedAsConstrained { ident }) @@ -105,8 +104,7 @@ pub(super) fn oracle_called_from_constrained_function( } let function_attributes = interner.function_attributes(called_func); - let is_oracle_call = - function_attributes.function.as_ref().map_or(false, |func| func.is_oracle()); + let is_oracle_call = function_attributes.function().map_or(false, |func| func.is_oracle()); if is_oracle_call { Some(ResolverError::UnconstrainedOracleReturnToConstrained { span }) } else { 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 14901303b92..084bcbe3f8d 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs @@ -4,9 +4,8 @@ use std::{ }; use crate::{ - ast::ItemVisibility, hir::resolution::import::PathResolutionItem, - hir_def::traits::ResolvedTraitBound, usage_tracker::UsageTracker, StructField, StructType, - TypeBindings, + ast::ItemVisibility, hir_def::traits::ResolvedTraitBound, usage_tracker::UsageTracker, + StructField, StructType, TypeBindings, }; use crate::{ ast::{ @@ -24,7 +23,6 @@ use crate::{ def_map::{DefMaps, ModuleData}, def_map::{LocalModuleId, ModuleId, MAIN_FUNCTION}, resolution::errors::ResolverError, - resolution::import::PathResolution, scope::ScopeForest as GenericScopeForest, type_check::{generics::TraitGenerics, TypeCheckError}, Context, @@ -40,13 +38,14 @@ use crate::{ DefinitionKind, DependencyId, ExprId, FuncId, FunctionModifiers, GlobalId, NodeInterner, ReferenceId, StructId, TraitId, TraitImplId, TypeAliasId, }, - token::{CustomAttribute, SecondaryAttribute}, + token::SecondaryAttribute, Shared, Type, TypeVariable, }; mod comptime; mod expressions; mod lints; +mod path_resolution; mod patterns; mod scope; mod statements; @@ -58,6 +57,7 @@ mod unquote; use fm::FileId; use iter_extended::vecmap; use noirc_errors::{Location, Span, Spanned}; +use path_resolution::{PathResolution, PathResolutionItem}; use types::bind_ordered_generics; use self::traits::check_trait_impl_method_matches_declaration; @@ -641,7 +641,7 @@ impl<'context> Elaborator<'context> { let typ = if unresolved_typ.is_type_expression() { self.resolve_type_inner( unresolved_typ.clone(), - &Kind::Numeric(Box::new(Type::default_int_type())), + &Kind::numeric(Type::default_int_type()), ) } else { self.resolve_type(unresolved_typ.clone()) @@ -654,7 +654,7 @@ impl<'context> Elaborator<'context> { }); self.push_err(unsupported_typ_err); } - Kind::Numeric(Box::new(typ)) + Kind::numeric(typ) } else { Kind::Normal } @@ -839,11 +839,6 @@ impl<'context> Elaborator<'context> { None }; - let attributes = func.secondary_attributes().iter(); - let attributes = - attributes.filter_map(|secondary_attribute| secondary_attribute.as_custom()); - let attributes: Vec = attributes.cloned().collect(); - let meta = FuncMeta { name: name_ident, kind: func.kind, @@ -867,7 +862,6 @@ impl<'context> Elaborator<'context> { function_body: FunctionBody::Unresolved(func.kind, body, func.def.span), self_type: self.self_type.clone(), source_file: self.file, - custom_attributes: attributes, }; self.interner.push_fn_meta(meta, func_id); @@ -896,6 +890,10 @@ impl<'context> Elaborator<'context> { Type::Alias(alias_type, generics) => { self.mark_type_as_used(&alias_type.borrow().get_type(generics)); } + Type::CheckedCast { from, to } => { + self.mark_type_as_used(from); + self.mark_type_as_used(to); + } Type::MutableReference(typ) => { self.mark_type_as_used(typ); } @@ -1498,6 +1496,10 @@ impl<'context> Elaborator<'context> { span, ); } + Type::CheckedCast { from, to } => { + self.check_type_is_not_more_private_then_item(name, visibility, from, span); + self.check_type_is_not_more_private_then_item(name, visibility, to, span); + } Type::Function(args, return_type, env, _) => { for arg in args { self.check_type_is_not_more_private_then_item(name, visibility, arg, span); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/path_resolution.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/path_resolution.rs new file mode 100644 index 00000000000..a68991becb7 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/path_resolution.rs @@ -0,0 +1,347 @@ +use noirc_errors::{Location, Span}; + +use crate::ast::{Path, PathKind, UnresolvedType}; +use crate::hir::def_map::{ModuleDefId, ModuleId}; +use crate::hir::resolution::import::{resolve_path_kind, PathResolutionError}; + +use crate::hir::resolution::errors::ResolverError; +use crate::hir::resolution::visibility::item_in_module_is_visible; + +use crate::locations::ReferencesTracker; +use crate::node_interner::{FuncId, GlobalId, StructId, TraitId, TypeAliasId}; +use crate::Type; + +use super::types::SELF_TYPE_NAME; +use super::Elaborator; + +#[derive(Debug)] +pub(crate) struct PathResolution { + pub(crate) item: PathResolutionItem, + pub(crate) errors: Vec, +} + +/// All possible items that result from resolving a Path. +/// Note that this item doesn't include the last turbofish in a Path, +/// only intermediate ones, if any. +#[derive(Debug, Clone)] +pub enum PathResolutionItem { + Module(ModuleId), + Struct(StructId), + TypeAlias(TypeAliasId), + Trait(TraitId), + Global(GlobalId), + ModuleFunction(FuncId), + StructFunction(StructId, Option, FuncId), + TypeAliasFunction(TypeAliasId, Option, FuncId), + TraitFunction(TraitId, Option, FuncId), +} + +impl PathResolutionItem { + pub fn function_id(&self) -> Option { + match self { + PathResolutionItem::ModuleFunction(func_id) + | PathResolutionItem::StructFunction(_, _, func_id) + | PathResolutionItem::TypeAliasFunction(_, _, func_id) + | PathResolutionItem::TraitFunction(_, _, func_id) => Some(*func_id), + _ => None, + } + } + + pub fn module_id(&self) -> Option { + match self { + Self::Module(module_id) => Some(*module_id), + _ => None, + } + } + + pub fn description(&self) -> &'static str { + match self { + PathResolutionItem::Module(..) => "module", + PathResolutionItem::Struct(..) => "type", + PathResolutionItem::TypeAlias(..) => "type alias", + PathResolutionItem::Trait(..) => "trait", + PathResolutionItem::Global(..) => "global", + PathResolutionItem::ModuleFunction(..) + | PathResolutionItem::StructFunction(..) + | PathResolutionItem::TypeAliasFunction(..) + | PathResolutionItem::TraitFunction(..) => "function", + } + } +} + +#[derive(Debug, Clone)] +pub struct Turbofish { + pub generics: Vec, + pub span: Span, +} + +/// Any item that can appear before the last segment in a path. +#[derive(Debug)] +enum IntermediatePathResolutionItem { + Module(ModuleId), + Struct(StructId, Option), + TypeAlias(TypeAliasId, Option), + Trait(TraitId, Option), +} + +pub(crate) type PathResolutionResult = Result; + +impl<'context> Elaborator<'context> { + pub(super) fn resolve_path_or_error( + &mut self, + path: Path, + ) -> Result { + let path_resolution = self.resolve_path(path)?; + + for error in path_resolution.errors { + self.push_err(error); + } + + Ok(path_resolution.item) + } + + /// Resolves a path in the current module. + /// If the referenced name can't be found, `Err` will be returned. If it can be found, `Ok` + /// will be returned with a potential list of errors if, for example, one of the segments + /// is not accessible from the current module (e.g. because it's private). + pub(super) fn resolve_path(&mut self, mut path: Path) -> PathResolutionResult { + let mut module_id = self.module_id(); + + if path.kind == PathKind::Plain && path.first_name() == Some(SELF_TYPE_NAME) { + if let Some(Type::Struct(struct_type, _)) = &self.self_type { + let struct_type = struct_type.borrow(); + if path.segments.len() == 1 { + return Ok(PathResolution { + item: PathResolutionItem::Struct(struct_type.id), + errors: Vec::new(), + }); + } + + module_id = struct_type.id.module_id(); + path.segments.remove(0); + } + } + + self.resolve_path_in_module(path, module_id) + } + + /// Resolves a path in `current_module`. + /// `importing_module` is the module where the lookup originally started. + fn resolve_path_in_module( + &mut self, + path: Path, + importing_module: ModuleId, + ) -> PathResolutionResult { + let references_tracker = if self.interner.is_in_lsp_mode() { + Some(ReferencesTracker::new(self.interner, self.file)) + } else { + None + }; + let (path, module_id, _) = + resolve_path_kind(path, importing_module, self.def_maps, references_tracker)?; + self.resolve_name_in_module(path, module_id, importing_module) + } + + /// Resolves a Path assuming we are inside `starting_module`. + /// `importing_module` is the module where the lookup originally started. + fn resolve_name_in_module( + &mut self, + path: Path, + starting_module: ModuleId, + importing_module: ModuleId, + ) -> PathResolutionResult { + // There is a possibility that the import path is empty. In that case, early return. + if path.segments.is_empty() { + return Ok(PathResolution { + item: PathResolutionItem::Module(starting_module), + errors: Vec::new(), + }); + } + + let plain_or_crate = matches!(path.kind, PathKind::Plain | PathKind::Crate); + + // The current module and module ID as we resolve path segments + let mut current_module_id = starting_module; + let mut current_module = self.get_module(starting_module); + + let mut intermediate_item = IntermediatePathResolutionItem::Module(current_module_id); + + let first_segment = + &path.segments.first().expect("ice: could not fetch first segment").ident; + let mut current_ns = current_module.find_name(first_segment); + if current_ns.is_none() { + return Err(PathResolutionError::Unresolved(first_segment.clone())); + } + + self.usage_tracker.mark_as_referenced(current_module_id, first_segment); + + let mut errors = Vec::new(); + for (index, (last_segment, current_segment)) in + path.segments.iter().zip(path.segments.iter().skip(1)).enumerate() + { + let last_ident = &last_segment.ident; + let current_ident = ¤t_segment.ident; + let last_segment_generics = &last_segment.generics; + + let (typ, visibility) = match current_ns.types { + None => return Err(PathResolutionError::Unresolved(last_ident.clone())), + Some((typ, visibility, _)) => (typ, visibility), + }; + + let location = Location::new(last_segment.span, self.file); + self.interner.add_module_def_id_reference( + typ, + location, + last_segment.ident.is_self_type_name(), + ); + + (current_module_id, intermediate_item) = match typ { + ModuleDefId::ModuleId(id) => { + if last_segment_generics.is_some() { + errors.push(PathResolutionError::TurbofishNotAllowedOnItem { + item: format!("module `{last_ident}`"), + span: last_segment.turbofish_span(), + }); + } + + (id, IntermediatePathResolutionItem::Module(id)) + } + ModuleDefId::TypeId(id) => ( + id.module_id(), + IntermediatePathResolutionItem::Struct( + id, + last_segment_generics.as_ref().map(|generics| Turbofish { + generics: generics.clone(), + span: last_segment.turbofish_span(), + }), + ), + ), + ModuleDefId::TypeAliasId(id) => { + let type_alias = self.interner.get_type_alias(id); + let type_alias = type_alias.borrow(); + + let module_id = match &type_alias.typ { + Type::Struct(struct_id, _generics) => struct_id.borrow().id.module_id(), + Type::Error => { + return Err(PathResolutionError::Unresolved(last_ident.clone())); + } + _ => { + // For now we only allow type aliases that point to structs. + // The more general case is captured here: https://github.com/noir-lang/noir/issues/6398 + panic!("Type alias in path not pointing to struct not yet supported") + } + }; + + ( + module_id, + IntermediatePathResolutionItem::TypeAlias( + id, + last_segment_generics.as_ref().map(|generics| Turbofish { + generics: generics.clone(), + span: last_segment.turbofish_span(), + }), + ), + ) + } + ModuleDefId::TraitId(id) => ( + id.0, + IntermediatePathResolutionItem::Trait( + id, + last_segment_generics.as_ref().map(|generics| Turbofish { + generics: generics.clone(), + span: last_segment.turbofish_span(), + }), + ), + ), + ModuleDefId::FunctionId(_) => panic!("functions cannot be in the type namespace"), + ModuleDefId::GlobalId(_) => panic!("globals cannot be in the type namespace"), + }; + + // If the path is plain or crate, the first segment will always refer to + // something that's visible from the current module. + if !((plain_or_crate && index == 0) + || item_in_module_is_visible( + self.def_maps, + importing_module, + current_module_id, + visibility, + )) + { + errors.push(PathResolutionError::Private(last_ident.clone())); + } + + current_module = self.get_module(current_module_id); + + // Check if namespace + let found_ns = current_module.find_name(current_ident); + if found_ns.is_none() { + return Err(PathResolutionError::Unresolved(current_ident.clone())); + } + + self.usage_tracker.mark_as_referenced(current_module_id, current_ident); + + current_ns = found_ns; + } + + let (module_def_id, visibility, _) = + current_ns.values.or(current_ns.types).expect("Found empty namespace"); + + let name = path.last_ident(); + let is_self_type = name.is_self_type_name(); + let location = Location::new(name.span(), self.file); + self.interner.add_module_def_id_reference(module_def_id, location, is_self_type); + + let item = merge_intermediate_path_resolution_item_with_module_def_id( + intermediate_item, + module_def_id, + ); + + if !(self.self_type_module_id() == Some(current_module_id) + || item_in_module_is_visible( + self.def_maps, + importing_module, + current_module_id, + visibility, + )) + { + errors.push(PathResolutionError::Private(name.clone())); + } + + Ok(PathResolution { item, errors }) + } + + fn self_type_module_id(&self) -> Option { + if let Some(Type::Struct(struct_type, _)) = &self.self_type { + Some(struct_type.borrow().id.module_id()) + } else { + None + } + } +} + +fn merge_intermediate_path_resolution_item_with_module_def_id( + intermediate_item: IntermediatePathResolutionItem, + module_def_id: ModuleDefId, +) -> PathResolutionItem { + match module_def_id { + ModuleDefId::ModuleId(module_id) => PathResolutionItem::Module(module_id), + ModuleDefId::TypeId(struct_id) => PathResolutionItem::Struct(struct_id), + ModuleDefId::TypeAliasId(type_alias_id) => PathResolutionItem::TypeAlias(type_alias_id), + ModuleDefId::TraitId(trait_id) => PathResolutionItem::Trait(trait_id), + ModuleDefId::GlobalId(global_id) => PathResolutionItem::Global(global_id), + ModuleDefId::FunctionId(func_id) => match intermediate_item { + IntermediatePathResolutionItem::Module(_) => { + PathResolutionItem::ModuleFunction(func_id) + } + IntermediatePathResolutionItem::Struct(struct_id, generics) => { + PathResolutionItem::StructFunction(struct_id, generics, func_id) + } + IntermediatePathResolutionItem::TypeAlias(alias_id, generics) => { + PathResolutionItem::TypeAliasFunction(alias_id, generics, func_id) + } + IntermediatePathResolutionItem::Trait(trait_id, generics) => { + PathResolutionItem::TraitFunction(trait_id, generics, func_id) + } + }, + } +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs index 9e60adcbc6f..3928362db11 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs @@ -9,7 +9,7 @@ use crate::{ }, hir::{ def_collector::dc_crate::CompilationError, - resolution::{errors::ResolverError, import::PathResolutionItem}, + resolution::errors::ResolverError, type_check::{Source, TypeCheckError}, }, hir_def::{ @@ -20,7 +20,7 @@ use crate::{ Kind, Shared, StructType, Type, TypeAlias, TypeBindings, }; -use super::{Elaborator, ResolverMeta}; +use super::{path_resolution::PathResolutionItem, Elaborator, ResolverMeta}; impl<'context> Elaborator<'context> { pub(super) fn elaborate_pattern( 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 33e97c1df22..fe01e3cb7f3 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/scope.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/scope.rs @@ -1,9 +1,8 @@ -use noirc_errors::{Location, Spanned}; +use noirc_errors::Spanned; -use crate::ast::{Ident, Path, PathKind, ERROR_IDENT}; +use crate::ast::{Ident, Path, ERROR_IDENT}; use crate::hir::def_map::{LocalModuleId, ModuleId}; -use crate::hir::resolution::import::{PathResolution, PathResolutionItem, PathResolutionResult}; -use crate::hir::resolution::path_resolver::{PathResolver, StandardPathResolver}; + use crate::hir::scope::{Scope as GenericScope, ScopeTree as GenericScopeTree}; use crate::{ hir::resolution::errors::ResolverError, @@ -16,6 +15,7 @@ use crate::{ }; use crate::{Type, TypeAlias}; +use super::path_resolution::PathResolutionItem; use super::types::SELF_TYPE_NAME; use super::{Elaborator, ResolverMeta}; @@ -37,99 +37,6 @@ impl<'context> Elaborator<'context> { current_module } - pub(super) fn resolve_path_or_error( - &mut self, - path: Path, - ) -> Result { - let path_resolution = self.resolve_path(path)?; - - for error in path_resolution.errors { - self.push_err(error); - } - - Ok(path_resolution.item) - } - - pub(super) fn resolve_path(&mut self, path: Path) -> PathResolutionResult { - let mut module_id = self.module_id(); - let mut path = path; - - if path.kind == PathKind::Plain && path.first_name() == SELF_TYPE_NAME { - if let Some(Type::Struct(struct_type, _)) = &self.self_type { - let struct_type = struct_type.borrow(); - if path.segments.len() == 1 { - return Ok(PathResolution { - item: PathResolutionItem::Struct(struct_type.id), - errors: Vec::new(), - }); - } - - module_id = struct_type.id.module_id(); - path = Path { - segments: path.segments[1..].to_vec(), - kind: PathKind::Plain, - span: path.span(), - }; - } - } - - self.resolve_path_in_module(path, module_id) - } - - fn resolve_path_in_module(&mut self, path: Path, module_id: ModuleId) -> PathResolutionResult { - let self_type_module_id = if let Some(Type::Struct(struct_type, _)) = &self.self_type { - Some(struct_type.borrow().id.module_id()) - } else { - None - }; - - let resolver = StandardPathResolver::new(module_id, self_type_module_id); - - if !self.interner.lsp_mode { - return resolver.resolve( - self.interner, - self.def_maps, - path, - self.usage_tracker, - &mut None, - ); - } - - let last_segment = path.last_ident(); - let location = Location::new(last_segment.span(), self.file); - let is_self_type_name = last_segment.is_self_type_name(); - - let mut references: Vec<_> = Vec::new(); - let path_resolution = resolver.resolve( - self.interner, - self.def_maps, - path.clone(), - self.usage_tracker, - &mut Some(&mut references), - ); - - for (referenced, segment) in references.iter().zip(path.segments) { - self.interner.add_reference( - *referenced, - Location::new(segment.ident.span(), self.file), - segment.ident.is_self_type_name(), - ); - } - - let path_resolution = match path_resolution { - Ok(path_resolution) => path_resolution, - Err(err) => return Err(err), - }; - - self.interner.add_path_resolution_kind_reference( - path_resolution.item.clone(), - location, - is_self_type_name, - ); - - Ok(path_resolution) - } - pub(super) fn get_struct(&self, type_id: StructId) -> Shared { self.interner.get_struct(type_id) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs index ae278616e03..e1be45927ca 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs @@ -23,6 +23,8 @@ use super::Elaborator; impl<'context> Elaborator<'context> { pub fn collect_traits(&mut self, traits: &BTreeMap) { for (trait_id, unresolved_trait) in traits { + self.local_module = unresolved_trait.module_id; + self.recover_generics(|this| { this.current_trait = Some(*trait_id); 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 c8a16a6cd9b..b296c4f1805 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs @@ -14,10 +14,7 @@ use crate::{ hir::{ comptime::{Interpreter, Value}, def_collector::dc_crate::CompilationError, - resolution::{ - errors::ResolverError, - import::{PathResolutionError, PathResolutionItem}, - }, + resolution::{errors::ResolverError, import::PathResolutionError}, type_check::{ generics::{Generic, TraitGenerics}, NoMatchingImplFoundError, Source, TypeCheckError, @@ -41,7 +38,7 @@ use crate::{ UnificationError, }; -use super::{lints, Elaborator}; +use super::{lints, path_resolution::PathResolutionItem, Elaborator}; pub const SELF_TYPE_NAME: &str = "Self"; pub const WILDCARD_TYPE: &str = "_"; @@ -195,7 +192,7 @@ impl<'context> Elaborator<'context> { // Resolve Self::Foo to an associated type on the current trait or trait impl fn lookup_associated_type_on_self(&self, path: &Path) -> Option { - if path.segments.len() == 2 && path.first_name() == SELF_TYPE_NAME { + if path.segments.len() == 2 && path.first_name() == Some(SELF_TYPE_NAME) { if let Some(trait_id) = self.current_trait { let the_trait = self.interner.get_trait(trait_id); if let Some(typ) = the_trait.get_associated_type(path.last_name()) { @@ -417,7 +414,7 @@ impl<'context> Elaborator<'context> { let kind = self .interner .get_global_let_statement(id) - .map(|let_statement| Kind::Numeric(Box::new(let_statement.r#type))) + .map(|let_statement| Kind::numeric(let_statement.r#type)) .unwrap_or(Kind::u32()); // TODO(https://github.com/noir-lang/noir/issues/6238): @@ -465,14 +462,26 @@ impl<'context> Elaborator<'context> { }); return Type::Error; } - if let Some(result) = op.function(lhs, rhs, &lhs_kind) { - Type::Constant(result, lhs_kind) - } else { - self.push_err(ResolverError::OverflowInType { lhs, op, rhs, span }); - Type::Error + match op.function(lhs, rhs, &lhs_kind, span) { + Ok(result) => Type::Constant(result, lhs_kind), + Err(err) => { + let err = Box::new(err); + self.push_err(ResolverError::BinaryOpError { + lhs, + op, + rhs, + err, + span, + }); + Type::Error + } } } - (lhs, rhs) => Type::InfixExpr(Box::new(lhs), op, Box::new(rhs)).canonicalize(), + (lhs, rhs) => { + let infix = Type::InfixExpr(Box::new(lhs), op, Box::new(rhs)); + Type::CheckedCast { from: Box::new(infix.clone()), to: Box::new(infix) } + .canonicalize() + } } } UnresolvedTypeExpression::AsTraitPath(path) => { @@ -1741,6 +1750,11 @@ impl<'context> Elaborator<'context> { | Type::Quoted(_) | Type::Forall(_, _) => (), + Type::CheckedCast { from, to } => { + Self::find_numeric_generics_in_type(from, found); + Self::find_numeric_generics_in_type(to, found); + } + Type::TraitAsType(_, _, args) => { for arg in &args.ordered { Self::find_numeric_generics_in_type(arg, found); 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 index bfbe39df241..560d11cfa2e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/display.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/display.rs @@ -281,8 +281,7 @@ impl<'interner> TokenPrettyPrinter<'interner> { | Token::Whitespace(_) | Token::LineComment(..) | Token::BlockComment(..) - | Token::Attribute(..) - | Token::InnerAttribute(..) + | Token::AttributeStart { .. } | Token::Invalid(_) => { if last_was_alphanumeric { write!(f, " ")?; 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 dfd328f85f0..198ba91156e 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 @@ -3,7 +3,10 @@ use std::rc::Rc; use crate::{ ast::TraitBound, - hir::{def_collector::dc_crate::CompilationError, type_check::NoMatchingImplFoundError}, + hir::{ + def_collector::dc_crate::CompilationError, + type_check::{NoMatchingImplFoundError, TypeCheckError}, + }, parser::ParserError, Type, }; @@ -87,6 +90,7 @@ pub enum InterpreterError { }, NonIntegerArrayLength { typ: Type, + err: Option>, location: Location, }, NonNumericCasted { @@ -228,6 +232,7 @@ pub enum InterpreterError { }, UnknownArrayLength { length: Type, + err: Box, location: Location, }, @@ -435,9 +440,13 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic { let secondary = "This is likely a bug".into(); CustomDiagnostic::simple_error(msg, secondary, location.span) } - InterpreterError::NonIntegerArrayLength { typ, location } => { + InterpreterError::NonIntegerArrayLength { typ, err, location } => { let msg = format!("Non-integer array length: `{typ}`"); - let secondary = "Array lengths must be integers".into(); + let secondary = if let Some(err) = err { + format!("Array lengths must be integers, but evaluating `{typ}` resulted in `{err}`") + } else { + "Array lengths must be integers".to_string() + }; CustomDiagnostic::simple_error(msg, secondary, location.span) } InterpreterError::NonNumericCasted { typ, location } => { @@ -640,9 +649,10 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic { let msg = format!("`{expression}` is not a valid function body"); CustomDiagnostic::simple_error(msg, String::new(), location.span) } - InterpreterError::UnknownArrayLength { length, location } => { + InterpreterError::UnknownArrayLength { length, err, location } => { let msg = format!("Could not determine array length `{length}`"); - CustomDiagnostic::simple_error(msg, String::new(), location.span) + let secondary = format!("Evaluating the length failed with: `{err}`"); + CustomDiagnostic::simple_error(msg, secondary, location.span) } } } 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 260c4e3848a..5540a199cec 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 @@ -340,6 +340,7 @@ impl Type { let name = Path::from_single(name.as_ref().clone(), Span::default()); UnresolvedTypeData::Named(name, GenericTypeArgs::default(), true) } + Type::CheckedCast { to, .. } => to.to_display_ast().typ, Type::Function(args, ret, env, unconstrained) => { let args = vecmap(args, |arg| arg.to_display_ast()); let ret = Box::new(ret.to_display_ast()); 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 7205242ead9..994318a371a 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 @@ -223,7 +223,7 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { location: Location, ) -> IResult { let attributes = self.elaborator.interner.function_attributes(&function); - let func_attrs = attributes.function.as_ref() + let func_attrs = attributes.function() .expect("all builtin functions must contain a function attribute which contains the opcode which it links to"); if let Some(builtin) = func_attrs.builtin() { @@ -585,20 +585,25 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { } DefinitionKind::NumericGeneric(type_variable, numeric_typ) => { let value = match &*type_variable.borrow() { - TypeBinding::Unbound(_, _) => None, + TypeBinding::Unbound(_, _) => { + let typ = self.elaborator.interner.id_type(id); + let location = self.elaborator.interner.expr_location(&id); + Err(InterpreterError::NonIntegerArrayLength { typ, err: None, location }) + } TypeBinding::Bound(binding) => { - binding.evaluate_to_field_element(&Kind::Numeric(numeric_typ.clone())) + let span = self.elaborator.interner.id_location(id).span; + binding + .evaluate_to_field_element(&Kind::Numeric(numeric_typ.clone()), span) + .map_err(|err| { + let typ = Type::TypeVariable(type_variable.clone()); + let err = Some(Box::new(err)); + let location = self.elaborator.interner.expr_location(&id); + InterpreterError::NonIntegerArrayLength { typ, err, location } + }) } - }; + }?; - if let Some(value) = value { - let typ = self.elaborator.interner.id_type(id); - self.evaluate_integer(value, false, id) - } else { - let location = self.elaborator.interner.expr_location(&id); - let typ = Type::TypeVariable(type_variable.clone()); - Err(InterpreterError::NonIntegerArrayLength { typ, location }) - } + self.evaluate_integer(value, false, id) } } } @@ -805,12 +810,17 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { HirArrayLiteral::Repeated { repeated_element, length } => { let element = self.evaluate(repeated_element)?; - if let Some(length) = length.evaluate_to_u32() { - let elements = (0..length).map(|_| element.clone()).collect(); - Ok(Value::Array(elements, typ)) - } else { - let location = self.elaborator.interner.expr_location(&id); - Err(InterpreterError::NonIntegerArrayLength { typ: length, location }) + let span = self.elaborator.interner.id_location(id).span; + match length.evaluate_to_u32(span) { + Ok(length) => { + let elements = (0..length).map(|_| element.clone()).collect(); + Ok(Value::Array(elements, typ)) + } + Err(err) => { + let err = Some(Box::new(err)); + let location = self.elaborator.interner.expr_location(&id); + Err(InterpreterError::NonIntegerArrayLength { typ: length, err, location }) + } } } } 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 d8842215a29..8a6c46ca50c 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 @@ -12,7 +12,7 @@ use builtin_helpers::{ }; use im::Vector; use iter_extended::{try_vecmap, vecmap}; -use noirc_errors::Location; +use noirc_errors::{Location, Span}; use num_bigint::BigUint; use rustc_hash::FxHashMap as HashMap; @@ -37,7 +37,7 @@ use crate::{ hir_def::{self}, node_interner::{DefinitionKind, NodeInterner, TraitImplKind}, parser::{Parser, StatementOrExpressionOrLValue}, - token::{Attribute, SecondaryAttribute, Token}, + token::{Attribute, Token}, Kind, QuotedType, ResolvedGeneric, Shared, Type, TypeVariable, }; @@ -230,7 +230,7 @@ impl<'local, 'context> Interpreter<'local, 'context> { "unresolved_type_is_bool" => unresolved_type_is_bool(interner, arguments, location), "unresolved_type_is_field" => unresolved_type_is_field(interner, arguments, location), "unresolved_type_is_unit" => unresolved_type_is_unit(interner, arguments, location), - "zeroed" => zeroed(return_type), + "zeroed" => zeroed(return_type, location.span), _ => { let item = format!("Comptime evaluation for builtin function {name}"); Err(InterpreterError::Unimplemented { item, location }) @@ -348,24 +348,9 @@ fn struct_def_add_attribute( let (self_argument, attribute) = check_two_arguments(arguments, location)?; let attribute_location = attribute.1; let attribute = get_str(interner, attribute)?; - - let mut tokens = lex(&format!("#[{}]", attribute)); - if tokens.len() != 1 { - return Err(InterpreterError::InvalidAttribute { - attribute: attribute.to_string(), - location: attribute_location, - }); - } - - let token = tokens.remove(0); - let Token::Attribute(attribute) = token else { - return Err(InterpreterError::InvalidAttribute { - attribute: attribute.to_string(), - location: attribute_location, - }); - }; - - let Attribute::Secondary(attribute) = attribute else { + let attribute = format!("#[{}]", attribute); + let mut parser = Parser::for_str(&attribute); + let Some((Attribute::Secondary(attribute), _span)) = parser.parse_attribute() else { return Err(InterpreterError::InvalidAttribute { attribute: attribute.to_string(), location: attribute_location, @@ -374,7 +359,7 @@ fn struct_def_add_attribute( let struct_id = get_struct(self_argument)?; interner.update_struct_attributes(struct_id, |attributes| { - attributes.push(attribute.clone()); + attributes.push(attribute); }); Ok(Value::Unit) @@ -710,7 +695,7 @@ fn quoted_as_expr( }, ); - option(return_type, value) + option(return_type, value, location.span) } // fn as_module(quoted: Quoted) -> Option @@ -737,7 +722,7 @@ fn quoted_as_module( module.map(Value::ModuleDefinition) }); - option(return_type, option_value) + option(return_type, option_value, location.span) } // fn as_trait_constraint(quoted: Quoted) -> TraitConstraint @@ -869,11 +854,22 @@ fn type_as_constant( return_type: Type, location: Location, ) -> IResult { - type_as(arguments, return_type, location, |typ| { + type_as_or_err(arguments, return_type, location, |typ| { // Prefer to use `evaluate_to_u32` over matching on `Type::Constant` // since arithmetic generics may be `Type::InfixExpr`s which evaluate to // constants but are not actually the `Type::Constant` variant. - typ.evaluate_to_u32().map(Value::U32) + match typ.evaluate_to_u32(location.span) { + Ok(constant) => Ok(Some(Value::U32(constant))), + Err(err) => { + // Evaluating to a non-constant returns 'None' in user code + if err.is_non_constant_evaluated() { + Ok(None) + } else { + let err = Some(Box::new(err)); + Err(InterpreterError::NonIntegerArrayLength { typ, err, location }) + } + } + } }) } @@ -979,7 +975,6 @@ fn type_as_tuple( }) } -// Helper function for implementing the `type_as_...` functions. fn type_as( arguments: Vec<(Value, Location)>, return_type: Type, @@ -988,13 +983,26 @@ fn type_as( ) -> IResult where F: FnOnce(Type) -> Option, +{ + type_as_or_err(arguments, return_type, location, |x| Ok(f(x))) +} + +// Helper function for implementing the `type_as_...` functions. +fn type_as_or_err( + arguments: Vec<(Value, Location)>, + return_type: Type, + location: Location, + f: F, +) -> IResult +where + F: FnOnce(Type) -> IResult>, { let value = check_one_argument(arguments, location)?; let typ = get_type(value)?.follow_bindings(); - let option_value = f(typ); + let option_value = f(typ)?; - option(return_type, option_value) + option(return_type, option_value, location.span) } // fn type_eq(_first: Type, _second: Type) -> bool @@ -1029,7 +1037,7 @@ fn type_get_trait_impl( _ => None, }; - option(return_type, option_value) + option(return_type, option_value, location.span) } // fn implements(self, constraint: TraitConstraint) -> bool @@ -1150,7 +1158,7 @@ fn typed_expr_as_function_definition( } else { None }; - option(return_type, option_value) + option(return_type, option_value, location.span) } // fn get_type(self) -> Option @@ -1172,7 +1180,7 @@ fn typed_expr_get_type( } else { None }; - option(return_type, option_value) + option(return_type, option_value, location.span) } // fn as_mutable_reference(self) -> Option @@ -1256,16 +1264,16 @@ where let option_value = f(typ); - option(return_type, option_value) + option(return_type, option_value, location.span) } // fn zeroed() -> T -fn zeroed(return_type: Type) -> IResult { +fn zeroed(return_type: Type, span: Span) -> IResult { match return_type { Type::FieldElement => Ok(Value::Field(0u128.into())), Type::Array(length_type, elem) => { - if let Some(length) = length_type.evaluate_to_u32() { - let element = zeroed(elem.as_ref().clone())?; + if let Ok(length) = length_type.evaluate_to_u32(span) { + let element = zeroed(elem.as_ref().clone(), span)?; let array = std::iter::repeat(element).take(length as usize).collect(); Ok(Value::Array(array, Type::Array(length_type, elem))) } else { @@ -1288,7 +1296,7 @@ fn zeroed(return_type: Type) -> IResult { }, Type::Bool => Ok(Value::Bool(false)), Type::String(length_type) => { - if let Some(length) = length_type.evaluate_to_u32() { + if let Ok(length) = length_type.evaluate_to_u32(span) { Ok(Value::String(Rc::new("\0".repeat(length as usize)))) } else { // Assume we can resolve the length later @@ -1296,9 +1304,9 @@ fn zeroed(return_type: Type) -> IResult { } } Type::FmtString(length_type, captures) => { - let length = length_type.evaluate_to_u32(); + let length = length_type.evaluate_to_u32(span); let typ = Type::FmtString(length_type, captures); - if let Some(length) = length { + if let Ok(length) = length { Ok(Value::FormatString(Rc::new("\0".repeat(length as usize)), typ)) } else { // Assume we can resolve the length later @@ -1306,26 +1314,27 @@ fn zeroed(return_type: Type) -> IResult { } } Type::Unit => Ok(Value::Unit), - Type::Tuple(fields) => Ok(Value::Tuple(try_vecmap(fields, zeroed)?)), + Type::Tuple(fields) => Ok(Value::Tuple(try_vecmap(fields, |field| zeroed(field, span))?)), Type::Struct(struct_type, generics) => { let fields = struct_type.borrow().get_fields(&generics); let mut values = HashMap::default(); for (field_name, field_type) in fields { - let field_value = zeroed(field_type)?; + let field_value = zeroed(field_type, span)?; values.insert(Rc::new(field_name), field_value); } let typ = Type::Struct(struct_type, generics); Ok(Value::Struct(values, typ)) } - Type::Alias(alias, generics) => zeroed(alias.borrow().get_type(&generics)), + Type::Alias(alias, generics) => zeroed(alias.borrow().get_type(&generics), span), + Type::CheckedCast { to, .. } => zeroed(*to, span), typ @ Type::Function(..) => { // Using Value::Zeroed here is probably safer than using FuncId::dummy_id() or similar Ok(Value::Zeroed(typ)) } Type::MutableReference(element) => { - let element = zeroed(*element)?; + let element = zeroed(*element, span)?; Ok(Value::Pointer(Shared::new(element), false)) } // Optimistically assume we can resolve this type later or that the value is unused @@ -1389,7 +1398,7 @@ fn expr_as_assert( let option_type = tuple_types.pop().unwrap(); let message = message.map(|msg| Value::expression(msg.kind)); - let message = option(option_type, message).ok()?; + let message = option(option_type, message, location.span).ok()?; Some(Value::Tuple(vec![predicate, message])) } else { @@ -1435,7 +1444,7 @@ fn expr_as_assert_eq( let option_type = tuple_types.pop().unwrap(); let message = message.map(|message| Value::expression(message.kind)); - let message = option(option_type, message).ok()?; + let message = option(option_type, message, location.span).ok()?; Some(Value::Tuple(vec![lhs, rhs, message])) } else { @@ -1611,7 +1620,7 @@ fn expr_as_constructor( None }; - option(return_type, option_value) + option(return_type, option_value, location.span) } // fn as_for(self) -> Option<(Quoted, Expr, Expr)> @@ -1705,6 +1714,7 @@ fn expr_as_if( let alternative = option( alternative_option_type, if_expr.alternative.map(|e| Value::expression(e.kind)), + location.span, ); Some(Value::Tuple(vec![ @@ -1793,7 +1803,7 @@ fn expr_as_lambda( } else { Some(Value::UnresolvedType(typ.typ)) }; - let typ = option(option_unresolved_type.clone(), typ).unwrap(); + let typ = option(option_unresolved_type.clone(), typ, location.span).unwrap(); Value::Tuple(vec![pattern, typ]) }) .collect(); @@ -1812,7 +1822,7 @@ fn expr_as_lambda( Some(return_type) }; let return_type = return_type.map(Value::UnresolvedType); - let return_type = option(option_unresolved_type, return_type).ok()?; + let return_type = option(option_unresolved_type, return_type, location.span).ok()?; let body = Value::expression(lambda.body.kind); @@ -1846,7 +1856,7 @@ fn expr_as_let( Some(Value::UnresolvedType(let_statement.r#type.typ)) }; - let typ = option(option_type, typ).ok()?; + let typ = option(option_type, typ, location.span).ok()?; Some(Value::Tuple(vec![ Value::pattern(let_statement.pattern), @@ -2098,7 +2108,7 @@ where let expr_value = unwrap_expr_value(interner, expr_value); let option_value = f(expr_value); - option(return_type, option_value) + option(return_type, option_value, location.span) } // fn resolve(self, in_function: Option) -> TypedExpr @@ -2225,17 +2235,9 @@ fn function_def_add_attribute( let (self_argument, attribute) = check_two_arguments(arguments, location)?; let attribute_location = attribute.1; let attribute = get_str(interpreter.elaborator.interner, attribute)?; - - let mut tokens = lex(&format!("#[{}]", attribute)); - if tokens.len() != 1 { - return Err(InterpreterError::InvalidAttribute { - attribute: attribute.to_string(), - location: attribute_location, - }); - } - - let token = tokens.remove(0); - let Token::Attribute(attribute) = token else { + let attribute = format!("#[{}]", attribute); + let mut parser = Parser::for_str(&attribute); + let Some((attribute, _span)) = parser.parse_attribute() else { return Err(InterpreterError::InvalidAttribute { attribute: attribute.to_string(), location: attribute_location, @@ -2249,21 +2251,13 @@ fn function_def_add_attribute( match &attribute { Attribute::Function(attribute) => { - function_modifiers.attributes.function = Some(attribute.clone()); + function_modifiers.attributes.set_function(attribute.clone()); } Attribute::Secondary(attribute) => { function_modifiers.attributes.secondary.push(attribute.clone()); } } - if let Attribute::Secondary( - SecondaryAttribute::Tag(attribute) | SecondaryAttribute::Meta(attribute), - ) = attribute - { - let func_meta = interpreter.elaborator.interner.function_meta_mut(&func_id); - func_meta.custom_attributes.push(attribute); - } - Ok(Value::Unit) } @@ -2295,7 +2289,7 @@ fn function_def_has_named_attribute( let name = &*get_str(interner, name)?; let modifiers = interner.function_modifiers(&func_id); - if let Some(attribute) = &modifiers.attributes.function { + if let Some(attribute) = modifiers.attributes.function() { if name == attribute.name() { return Ok(Value::Bool(true)); } @@ -2764,12 +2758,12 @@ fn trait_def_as_trait_constraint( /// Creates a value that holds an `Option`. /// `option_type` must be a Type referencing the `Option` type. -pub(crate) fn option(option_type: Type, value: Option) -> IResult { +pub(crate) fn option(option_type: Type, value: Option, span: Span) -> IResult { let t = extract_option_generic_type(option_type.clone()); let (is_some, value) = match value { Some(value) => (Value::Bool(true), value), - None => (Value::Bool(false), zeroed(t)?), + None => (Value::Bool(false), zeroed(t, span)?), }; let mut fields = HashMap::default(); @@ -2818,9 +2812,10 @@ fn derive_generators( _ => panic!("ICE: Should only have an array return type"), }; - let Some(num_generators) = size.evaluate_to_u32() else { - return Err(InterpreterError::UnknownArrayLength { length: *size, location }); - }; + let num_generators = size.evaluate_to_u32(location.span).map_err(|err| { + let err = Box::new(err); + InterpreterError::UnknownArrayLength { length: *size, err, location } + })?; let generators = bn254_blackbox_solver::derive_generators( &domain_separator_string, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 9917207d217..51e62599b05 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -5,13 +5,13 @@ use crate::graph::CrateId; use crate::hir::comptime::InterpreterError; use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleId}; use crate::hir::resolution::errors::ResolverError; -use crate::hir::resolution::path_resolver; use crate::hir::type_check::TypeCheckError; +use crate::locations::ReferencesTracker; use crate::token::SecondaryAttribute; use crate::usage_tracker::UnusedItem; use crate::{Generics, Type}; -use crate::hir::resolution::import::{resolve_import, ImportDirective, PathResolution}; +use crate::hir::resolution::import::{resolve_import, ImportDirective}; use crate::hir::Context; use crate::ast::Expression; @@ -347,45 +347,23 @@ impl DefCollector { // Resolve unresolved imports collected from the crate, one by one. for collected_import in std::mem::take(&mut def_collector.imports) { - let module_id = collected_import.module_id; - let resolved_import = if context.def_interner.lsp_mode { - let mut references: Vec = Vec::new(); - let resolved_import = resolve_import( - crate_id, - &collected_import, - &context.def_interner, - &context.def_maps, - &mut context.usage_tracker, - &mut Some(&mut references), - ); - - let current_def_map = context.def_maps.get(&crate_id).unwrap(); - let file_id = current_def_map.file_id(module_id); + let local_module_id = collected_import.module_id; + let module_id = ModuleId { krate: crate_id, local_id: local_module_id }; + let current_def_map = context.def_maps.get(&crate_id).unwrap(); + let file_id = current_def_map.file_id(local_module_id); + + let resolved_import = resolve_import( + collected_import.path.clone(), + module_id, + &context.def_maps, + &mut context.usage_tracker, + Some(ReferencesTracker::new(&mut context.def_interner, file_id)), + ); - for (referenced, segment) in references.iter().zip(&collected_import.path.segments) - { - context.def_interner.add_reference( - *referenced, - Location::new(segment.ident.span(), file_id), - false, - ); - } - - resolved_import - } else { - resolve_import( - crate_id, - &collected_import, - &context.def_interner, - &context.def_maps, - &mut context.usage_tracker, - &mut None, - ) - }; match resolved_import { Ok(resolved_import) => { let current_def_map = context.def_maps.get_mut(&crate_id).unwrap(); - let file_id = current_def_map.file_id(module_id); + let file_id = current_def_map.file_id(local_module_id); let has_path_resolution_error = !resolved_import.errors.is_empty(); for error in resolved_import.errors { @@ -396,11 +374,11 @@ impl DefCollector { } // Populate module namespaces according to the imports used - let name = resolved_import.name; + let name = collected_import.name(); let visibility = collected_import.visibility; - let is_prelude = resolved_import.is_prelude; + let is_prelude = collected_import.is_prelude; for (module_def_id, item_visibility, _) in - resolved_import.resolved_namespace.iter_items() + resolved_import.namespace.iter_items() { if item_visibility < visibility { errors.push(( @@ -414,25 +392,26 @@ impl DefCollector { } let visibility = visibility.min(item_visibility); - let result = current_def_map.modules[resolved_import.module_scope.0] - .import(name.clone(), visibility, module_def_id, is_prelude); + let result = current_def_map.modules[local_module_id.0].import( + name.clone(), + visibility, + module_def_id, + is_prelude, + ); // If we error on path resolution don't also say it's unused (in case it ends up being unused) if !has_path_resolution_error { - let module_id = ModuleId { - krate: crate_id, - local_id: resolved_import.module_scope, - }; + let defining_module = + ModuleId { krate: crate_id, local_id: local_module_id }; + context.usage_tracker.add_unused_item( - module_id, + defining_module, name.clone(), UnusedItem::Import, visibility, ); if visibility != ItemVisibility::Private { - let local_id = resolved_import.module_scope; - let defining_module = ModuleId { krate: crate_id, local_id }; context.def_interner.register_name_for_auto_import( name.to_string(), module_def_id, @@ -442,14 +421,6 @@ impl DefCollector { } } - let last_segment = collected_import.path.last_ident(); - - add_import_reference( - module_def_id, - &last_segment, - &mut context.def_interner, - file_id, - ); if let Some(ref alias) = collected_import.alias { add_import_reference( module_def_id, @@ -558,17 +529,18 @@ fn inject_prelude( span: Span::default(), }; - if let Ok(PathResolution { item, errors }) = path_resolver::resolve_path( - &context.def_interner, - &context.def_maps, - ModuleId { krate: crate_id, local_id: crate_root }, - None, + if let Ok(resolved_import) = resolve_import( path, + ModuleId { krate: crate_id, local_id: crate_root }, + &context.def_maps, &mut context.usage_tracker, - &mut None, + None, // references tracker ) { - assert!(errors.is_empty(), "Tried to add private item to prelude"); - let module_id = item.module_id().expect("std::prelude should be a module"); + assert!(resolved_import.errors.is_empty(), "Tried to add private item to prelude"); + + let (module_def_id, _, _) = + resolved_import.namespace.types.expect("couldn't resolve std::prelude"); + let module_id = module_def_id.as_module().expect("std::prelude should be a module"); let prelude = context.module(module_id).scope().names(); for path in prelude { @@ -580,7 +552,6 @@ fn inject_prelude( ImportDirective { visibility: ItemVisibility::Private, module_id: crate_root, - self_type_module_id: None, path: Path { segments, kind: PathKind::Plain, span: Span::default() }, alias: None, is_prelude: true, 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 94c091f9791..a373441b4e0 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 @@ -81,7 +81,6 @@ pub fn collect_defs( collector.def_collector.imports.push(ImportDirective { visibility: import.visibility, module_id: collector.module_id, - self_type_module_id: None, path: import.path, alias: import.alias, is_prelude: false, @@ -542,7 +541,7 @@ impl<'a> ModCollector<'a> { name: Rc::new(name.to_string()), type_var: TypeVariable::unbound( type_variable_id, - Kind::Numeric(Box::new(typ)), + Kind::numeric(typ), ), span: name.span(), }); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs index 60ee2c52842..de94f73b44b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs @@ -169,7 +169,7 @@ impl CrateDefMap { module.value_definitions().filter_map(|id| { if let Some(func_id) = id.as_function() { let attributes = interner.function_attributes(&func_id); - match &attributes.function { + match attributes.function() { Some(FunctionAttribute::Test(scope)) => { let location = interner.function_meta(&func_id).name.location; Some(TestFunction::new(func_id, scope.clone(), location)) 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 67820bfd1b7..b82eafa5b9d 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 @@ -5,7 +5,7 @@ use thiserror::Error; use crate::{ ast::{Ident, UnsupportedNumericGenericType}, - hir::comptime::InterpreterError, + hir::{comptime::InterpreterError, type_check::TypeCheckError}, parser::ParserError, usage_tracker::UnusedItem, Type, @@ -125,11 +125,12 @@ pub enum ResolverError { NamedTypeArgs { span: Span, item_kind: &'static str }, #[error("Associated constants may only be a field or integer type")] AssociatedConstantsMustBeNumeric { span: Span }, - #[error("Overflow in `{lhs} {op} {rhs}`")] - OverflowInType { + #[error("Computing `{lhs} {op} {rhs}` failed with error {err}")] + BinaryOpError { lhs: FieldElement, op: crate::BinaryTypeOperator, rhs: FieldElement, + err: Box, span: Span, }, #[error("`quote` cannot be used in runtime code")] @@ -518,10 +519,10 @@ impl<'a> From<&'a ResolverError> for Diagnostic { *span, ) } - ResolverError::OverflowInType { lhs, op, rhs, span } => { + ResolverError::BinaryOpError { lhs, op, rhs, err, span } => { Diagnostic::simple_error( - format!("Overflow in `{lhs} {op} {rhs}`"), - "Overflow here".to_string(), + format!("Computing `{lhs} {op} {rhs}` failed with error {err}"), + String::new(), *span, ) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs index 7afb056cbaf..376b85bfbd9 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs @@ -4,110 +4,37 @@ use thiserror::Error; use crate::graph::CrateId; use crate::hir::def_collector::dc_crate::CompilationError; -use crate::node_interner::{ - FuncId, GlobalId, NodeInterner, ReferenceId, StructId, TraitId, TypeAliasId, -}; +use crate::locations::ReferencesTracker; use crate::usage_tracker::UsageTracker; -use crate::Type; use std::collections::BTreeMap; -use crate::ast::{Ident, ItemVisibility, Path, PathKind, PathSegment, UnresolvedType}; -use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleDefId, ModuleId, PerNs}; +use crate::ast::{Ident, ItemVisibility, Path, PathKind}; +use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleData, ModuleDefId, ModuleId, PerNs}; use super::errors::ResolverError; -use super::visibility::can_reference_module_id; +use super::visibility::item_in_module_is_visible; #[derive(Debug, Clone)] pub struct ImportDirective { pub visibility: ItemVisibility, pub module_id: LocalModuleId, - pub self_type_module_id: Option, pub path: Path, pub alias: Option, pub is_prelude: bool, } -struct NamespaceResolution { - module_id: ModuleId, - item: PathResolutionItem, - namespace: PerNs, - errors: Vec, -} - -type NamespaceResolutionResult = Result; - -#[derive(Debug)] -pub struct PathResolution { - pub item: PathResolutionItem, - pub errors: Vec, -} - -/// All possible items that result from resolving a Path. -/// Note that this item doesn't include the last turbofish in a Path, -/// only intermediate ones, if any. -#[derive(Debug, Clone)] -pub enum PathResolutionItem { - Module(ModuleId), - Struct(StructId), - TypeAlias(TypeAliasId), - Trait(TraitId), - Global(GlobalId), - ModuleFunction(FuncId), - StructFunction(StructId, Option, FuncId), - TypeAliasFunction(TypeAliasId, Option, FuncId), - TraitFunction(TraitId, Option, FuncId), -} - -impl PathResolutionItem { - pub fn function_id(&self) -> Option { - match self { - PathResolutionItem::ModuleFunction(func_id) - | PathResolutionItem::StructFunction(_, _, func_id) - | PathResolutionItem::TypeAliasFunction(_, _, func_id) - | PathResolutionItem::TraitFunction(_, _, func_id) => Some(*func_id), - _ => None, - } - } - - pub fn module_id(&self) -> Option { - match self { - Self::Module(module_id) => Some(*module_id), - _ => None, - } - } - - pub fn description(&self) -> &'static str { - match self { - PathResolutionItem::Module(..) => "module", - PathResolutionItem::Struct(..) => "type", - PathResolutionItem::TypeAlias(..) => "type alias", - PathResolutionItem::Trait(..) => "trait", - PathResolutionItem::Global(..) => "global", - PathResolutionItem::ModuleFunction(..) - | PathResolutionItem::StructFunction(..) - | PathResolutionItem::TypeAliasFunction(..) - | PathResolutionItem::TraitFunction(..) => "function", +impl ImportDirective { + /// Returns the name that's brought into scope: either the alias or the last segment of the path + pub fn name(&self) -> Ident { + match &self.alias { + None => self.path.last_ident(), + Some(ident) => ident.clone(), } } } -#[derive(Debug, Clone)] -pub struct Turbofish { - pub generics: Vec, - pub span: Span, -} - -/// Any item that can appear before the last segment in a path. -#[derive(Debug)] -enum IntermediatePathResolutionItem { - Module(ModuleId), - Struct(StructId, Option), - TypeAlias(TypeAliasId, Option), - Trait(TraitId, Option), -} - -pub(crate) type PathResolutionResult = Result; +type ImportResolutionResult = Result; #[derive(Debug, Clone, PartialEq, Eq, Error)] pub enum PathResolutionError { @@ -119,19 +46,15 @@ pub enum PathResolutionError { NoSuper(Span), #[error("turbofish (`::<_>`) not allowed on {item}")] TurbofishNotAllowedOnItem { item: String, span: Span }, + #[error("{ident} is a {kind}, not a module")] + NotAModule { ident: Ident, kind: &'static str }, } #[derive(Debug)] pub struct ResolvedImport { - // name of the namespace, either last path segment or an alias - pub name: Ident, // The symbol which we have resolved to - pub resolved_namespace: PerNs, - // The item which we have resolved to - pub item: PathResolutionItem, + pub namespace: PerNs, // The module which we must add the resolved namespace to - pub module_scope: LocalModuleId, - pub is_prelude: bool, pub errors: Vec, } @@ -159,452 +82,255 @@ impl<'a> From<&'a PathResolutionError> for CustomDiagnostic { PathResolutionError::TurbofishNotAllowedOnItem { item: _, span } => { CustomDiagnostic::simple_error(error.to_string(), String::new(), *span) } + PathResolutionError::NotAModule { ident, kind: _ } => { + CustomDiagnostic::simple_error(error.to_string(), String::new(), ident.span()) + } } } } +/// Resolves a Path in a `use` statement, assuming it's located in `importing_module`. +/// +/// If the imported name can't be found, `Err` will be returned. If it can be found, `Ok` +/// will be returned with a potential list of errors if, for example, one of the segments +/// is not accessible from the importing module (e.g. because it's private). pub fn resolve_import( - crate_id: CrateId, - import_directive: &ImportDirective, - interner: &NodeInterner, + path: Path, + importing_module: ModuleId, def_maps: &BTreeMap, usage_tracker: &mut UsageTracker, - path_references: &mut Option<&mut Vec>, -) -> Result { - let module_scope = import_directive.module_id; - let NamespaceResolution { - module_id: resolved_module, - item, - namespace: resolved_namespace, - mut errors, - } = resolve_path_to_ns( - import_directive, - crate_id, - crate_id, - interner, - def_maps, - usage_tracker, - path_references, - )?; - - let name = resolve_path_name(import_directive); - - let visibility = resolved_namespace - .values - .or(resolved_namespace.types) - .map(|(_, visibility, _)| visibility) - .expect("Found empty namespace"); - - if !(import_directive.self_type_module_id == Some(resolved_module) - || can_reference_module_id( - def_maps, - crate_id, - import_directive.module_id, - resolved_module, - visibility, - )) - { - errors.push(PathResolutionError::Private(name.clone())); - } - - Ok(ResolvedImport { - name, - resolved_namespace, - item, - module_scope, - is_prelude: import_directive.is_prelude, - errors, - }) + references_tracker: Option, +) -> ImportResolutionResult { + let (path, module_id, references_tracker) = + resolve_path_kind(path, importing_module, def_maps, references_tracker)?; + let mut solver = + ImportSolver::new(importing_module, def_maps, usage_tracker, references_tracker); + solver.resolve_name_in_module(path, module_id) } -fn resolve_path_to_ns( - import_directive: &ImportDirective, - crate_id: CrateId, - importing_crate: CrateId, - interner: &NodeInterner, +/// Given a Path and a ModuleId it's being used in, this function returns a plain Path +/// and a ModuleId where that plain Path should be resolved. That is, this method will +/// resolve the Path kind and translate it to a plain path. +/// +/// The third value in the tuple is a reference tracker that must be passed to this +/// method, which is used in case the path kind is `dep`: the segment after `dep` +/// will be linked to the root module of the external dependency. +pub fn resolve_path_kind<'r>( + path: Path, + importing_module: ModuleId, def_maps: &BTreeMap, - usage_tracker: &mut UsageTracker, - path_references: &mut Option<&mut Vec>, -) -> NamespaceResolutionResult { - let import_path = &import_directive.path.segments; - - match import_directive.path.kind { - crate::ast::PathKind::Crate => { - // Resolve from the root of the crate - resolve_path_from_crate_root( - crate_id, - importing_crate, - import_path, - interner, - def_maps, - usage_tracker, - path_references, - ) + references_tracker: Option>, +) -> Result<(Path, ModuleId, Option>), PathResolutionError> { + let mut solver = + PathResolutionTargetResolver { importing_module, def_maps, references_tracker }; + let (path, module_id) = solver.resolve(path)?; + Ok((path, module_id, solver.references_tracker)) +} + +struct PathResolutionTargetResolver<'def_maps, 'references_tracker> { + importing_module: ModuleId, + def_maps: &'def_maps BTreeMap, + references_tracker: Option>, +} + +impl<'def_maps, 'references_tracker> PathResolutionTargetResolver<'def_maps, 'references_tracker> { + fn resolve(&mut self, path: Path) -> Result<(Path, ModuleId), PathResolutionError> { + match path.kind { + PathKind::Crate => self.resolve_crate_path(path), + PathKind::Plain => self.resolve_plain_path(path, self.importing_module), + PathKind::Dep => self.resolve_dep_path(path), + PathKind::Super => self.resolve_super_path(path), } - crate::ast::PathKind::Plain => { - // There is a possibility that the import path is empty - // In that case, early return - if import_path.is_empty() { - return resolve_name_in_module( - crate_id, - importing_crate, - import_path, - import_directive.module_id, - interner, - def_maps, - true, // plain or crate - usage_tracker, - path_references, - ); - } + } - let def_map = &def_maps[&crate_id]; - let current_mod_id = ModuleId { krate: crate_id, local_id: import_directive.module_id }; - let current_mod = &def_map.modules[current_mod_id.local_id.0]; - let first_segment = - &import_path.first().expect("ice: could not fetch first segment").ident; - if current_mod.find_name(first_segment).is_none() { - // Resolve externally when first segment is unresolved - return resolve_external_dep( - crate_id, - // def_map, - import_directive, - interner, - def_maps, - usage_tracker, - path_references, - importing_crate, - ); - } + fn resolve_crate_path(&mut self, path: Path) -> Result<(Path, ModuleId), PathResolutionError> { + let root_module = self.def_maps[&self.importing_module.krate].root; + let current_module = ModuleId { krate: self.importing_module.krate, local_id: root_module }; + Ok((path, current_module)) + } - resolve_name_in_module( - crate_id, - importing_crate, - import_path, - import_directive.module_id, - interner, - def_maps, - true, // plain or crate - usage_tracker, - path_references, - ) + fn resolve_plain_path( + &mut self, + path: Path, + current_module: ModuleId, + ) -> Result<(Path, ModuleId), PathResolutionError> { + // There is a possibility that the import path is empty. In that case, early return. + // This happens on import statements such as `use crate` or `use std`. + if path.segments.is_empty() { + return Ok((path, current_module)); } - crate::ast::PathKind::Dep => resolve_external_dep( - crate_id, - import_directive, - interner, - def_maps, - usage_tracker, - path_references, - importing_crate, - ), - - crate::ast::PathKind::Super => { - if let Some(parent_module_id) = - def_maps[&crate_id].modules[import_directive.module_id.0].parent - { - resolve_name_in_module( - crate_id, - importing_crate, - import_path, - parent_module_id, - interner, - def_maps, - false, // plain or crate - usage_tracker, - path_references, - ) - } else { - let span_start = import_directive.path.span().start(); - let span = Span::from(span_start..span_start + 5); // 5 == "super".len() - Err(PathResolutionError::NoSuper(span)) - } + let first_segment = + &path.segments.first().expect("ice: could not fetch first segment").ident; + if get_module(self.def_maps, current_module).find_name(first_segment).is_none() { + // Resolve externally when first segment is unresolved + return self.resolve_dep_path(path); + } + + Ok((path, current_module)) + } + + fn resolve_dep_path( + &mut self, + mut path: Path, + ) -> Result<(Path, ModuleId), PathResolutionError> { + // Use extern_prelude to get the dep + let current_def_map = &self.def_maps[&self.importing_module.krate]; + + // Fetch the root module from the prelude + let crate_name = &path.segments.first().unwrap().ident; + let dep_module = current_def_map + .extern_prelude + .get(&crate_name.0.contents) + .ok_or_else(|| PathResolutionError::Unresolved(crate_name.to_owned()))?; + + if let Some(references_tracker) = &mut self.references_tracker { + let span = crate_name.span(); + references_tracker.add_reference(ModuleDefId::ModuleId(*dep_module), span, false); } + + // Now the path can be solved starting from the second segment as a plain path + path.kind = PathKind::Plain; + path.segments.remove(0); + + Ok((path, *dep_module)) + } + + fn resolve_super_path(&mut self, path: Path) -> Result<(Path, ModuleId), PathResolutionError> { + let Some(parent_module_id) = get_module(self.def_maps, self.importing_module).parent else { + let span_start = path.span.start(); + let span = Span::from(span_start..span_start + 5); // 5 == "super".len() + return Err(PathResolutionError::NoSuper(span)); + }; + + let current_module = + ModuleId { krate: self.importing_module.krate, local_id: parent_module_id }; + Ok((path, current_module)) } } -fn resolve_path_from_crate_root( - crate_id: CrateId, - importing_crate: CrateId, - import_path: &[PathSegment], - interner: &NodeInterner, - def_maps: &BTreeMap, - usage_tracker: &mut UsageTracker, - path_references: &mut Option<&mut Vec>, -) -> NamespaceResolutionResult { - let starting_mod = def_maps[&crate_id].root; - resolve_name_in_module( - crate_id, - importing_crate, - import_path, - starting_mod, - interner, - def_maps, - true, // plain or crate - usage_tracker, - path_references, - ) +struct ImportSolver<'def_maps, 'usage_tracker, 'references_tracker> { + importing_module: ModuleId, + def_maps: &'def_maps BTreeMap, + usage_tracker: &'usage_tracker mut UsageTracker, + references_tracker: Option>, } -#[allow(clippy::too_many_arguments)] -fn resolve_name_in_module( - krate: CrateId, - importing_crate: CrateId, - import_path: &[PathSegment], - starting_mod: LocalModuleId, - interner: &NodeInterner, - def_maps: &BTreeMap, - plain_or_crate: bool, - usage_tracker: &mut UsageTracker, - path_references: &mut Option<&mut Vec>, -) -> NamespaceResolutionResult { - let def_map = &def_maps[&krate]; - let mut current_mod_id = ModuleId { krate, local_id: starting_mod }; - let mut current_mod = &def_map.modules[current_mod_id.local_id.0]; - - let mut intermediate_item = IntermediatePathResolutionItem::Module(current_mod_id); - - // There is a possibility that the import path is empty - // In that case, early return - if import_path.is_empty() { - return Ok(NamespaceResolution { - module_id: current_mod_id, - item: PathResolutionItem::Module(current_mod_id), - namespace: PerNs::types(current_mod_id.into()), - errors: Vec::new(), - }); +impl<'def_maps, 'usage_tracker, 'references_tracker> + ImportSolver<'def_maps, 'usage_tracker, 'references_tracker> +{ + fn new( + importing_module: ModuleId, + def_maps: &'def_maps BTreeMap, + usage_tracker: &'usage_tracker mut UsageTracker, + references_tracker: Option>, + ) -> Self { + Self { importing_module, def_maps, usage_tracker, references_tracker } } - let first_segment = &import_path.first().expect("ice: could not fetch first segment").ident; - let mut current_ns = current_mod.find_name(first_segment); - if current_ns.is_none() { - return Err(PathResolutionError::Unresolved(first_segment.clone())); - } + fn resolve_name_in_module( + &mut self, + path: Path, + starting_module: ModuleId, + ) -> ImportResolutionResult { + // There is a possibility that the import path is empty. In that case, early return. + if path.segments.is_empty() { + return Ok(ResolvedImport { + namespace: PerNs::types(starting_module.into()), + errors: Vec::new(), + }); + } - usage_tracker.mark_as_referenced(current_mod_id, first_segment); + let plain_or_crate = matches!(path.kind, PathKind::Plain | PathKind::Crate); - let mut errors = Vec::new(); - for (index, (last_segment, current_segment)) in - import_path.iter().zip(import_path.iter().skip(1)).enumerate() - { - let last_ident = &last_segment.ident; - let current_ident = ¤t_segment.ident; - let last_segment_generics = &last_segment.generics; + // The current module and module ID as we resolve path segments + let mut current_module_id = starting_module; + let mut current_module = get_module(self.def_maps, starting_module); - let (typ, visibility) = match current_ns.types { - None => return Err(PathResolutionError::Unresolved(last_ident.clone())), - Some((typ, visibility, _)) => (typ, visibility), - }; + let first_segment = + &path.segments.first().expect("ice: could not fetch first segment").ident; + let mut current_ns = current_module.find_name(first_segment); + if current_ns.is_none() { + return Err(PathResolutionError::Unresolved(first_segment.clone())); + } - // In the type namespace, only Mod can be used in a path. - (current_mod_id, intermediate_item) = match typ { - ModuleDefId::ModuleId(id) => { - if let Some(path_references) = path_references { - path_references.push(ReferenceId::Module(id)); - } + self.usage_tracker.mark_as_referenced(current_module_id, first_segment); - if last_segment_generics.is_some() { - errors.push(PathResolutionError::TurbofishNotAllowedOnItem { - item: format!("module `{last_ident}`"), - span: last_segment.turbofish_span(), + let mut errors = Vec::new(); + for (index, (last_segment, current_segment)) in + path.segments.iter().zip(path.segments.iter().skip(1)).enumerate() + { + let last_ident = &last_segment.ident; + let current_ident = ¤t_segment.ident; + + let (typ, visibility) = match current_ns.types { + None => return Err(PathResolutionError::Unresolved(last_ident.clone())), + Some((typ, visibility, _)) => (typ, visibility), + }; + + self.add_reference(typ, last_segment.span, last_segment.ident.is_self_type_name()); + + // In the type namespace, only Mod can be used in a path. + current_module_id = match typ { + ModuleDefId::ModuleId(id) => id, + ModuleDefId::TypeId(id) => id.module_id(), + ModuleDefId::TypeAliasId(..) => { + return Err(PathResolutionError::NotAModule { + ident: last_segment.ident.clone(), + kind: "type alias", }); } - - (id, IntermediatePathResolutionItem::Module(id)) + ModuleDefId::TraitId(id) => id.0, + ModuleDefId::FunctionId(_) => panic!("functions cannot be in the type namespace"), + ModuleDefId::GlobalId(_) => panic!("globals cannot be in the type namespace"), + }; + + // If the path is plain or crate, the first segment will always refer to + // something that's visible from the current module. + if !((plain_or_crate && index == 0) + || self.item_in_module_is_visible(current_module_id, visibility)) + { + errors.push(PathResolutionError::Private(last_ident.clone())); } - ModuleDefId::FunctionId(_) => panic!("functions cannot be in the type namespace"), - // TODO: If impls are ever implemented, types can be used in a path - ModuleDefId::TypeId(id) => { - if let Some(path_references) = path_references { - path_references.push(ReferenceId::Struct(id)); - } - ( - id.module_id(), - IntermediatePathResolutionItem::Struct( - id, - last_segment_generics.as_ref().map(|generics| Turbofish { - generics: generics.clone(), - span: last_segment.turbofish_span(), - }), - ), - ) - } - ModuleDefId::TypeAliasId(id) => { - if let Some(path_references) = path_references { - path_references.push(ReferenceId::Alias(id)); - } + current_module = + &self.def_maps[¤t_module_id.krate].modules[current_module_id.local_id.0]; - let type_alias = interner.get_type_alias(id); - let type_alias = type_alias.borrow(); - - let module_id = match &type_alias.typ { - Type::Struct(struct_id, _generics) => struct_id.borrow().id.module_id(), - Type::Error => { - return Err(PathResolutionError::Unresolved(last_ident.clone())); - } - _ => { - // For now we only allow type aliases that point to structs. - // The more general case is captured here: https://github.com/noir-lang/noir/issues/6398 - panic!("Type alias in path not pointing to struct not yet supported") - } - }; - - ( - module_id, - IntermediatePathResolutionItem::TypeAlias( - id, - last_segment_generics.as_ref().map(|generics| Turbofish { - generics: generics.clone(), - span: last_segment.turbofish_span(), - }), - ), - ) + // Check if namespace + let found_ns = current_module.find_name(current_ident); + if found_ns.is_none() { + return Err(PathResolutionError::Unresolved(current_ident.clone())); } - ModuleDefId::TraitId(id) => { - if let Some(path_references) = path_references { - path_references.push(ReferenceId::Trait(id)); - } - ( - id.0, - IntermediatePathResolutionItem::Trait( - id, - last_segment_generics.as_ref().map(|generics| Turbofish { - generics: generics.clone(), - span: last_segment.turbofish_span(), - }), - ), - ) - } - ModuleDefId::GlobalId(_) => panic!("globals cannot be in the type namespace"), - }; + self.usage_tracker.mark_as_referenced(current_module_id, current_ident); - // If the path is plain or crate, the first segment will always refer to - // something that's visible from the current module. - if !((plain_or_crate && index == 0) - || can_reference_module_id( - def_maps, - importing_crate, - starting_mod, - current_mod_id, - visibility, - )) - { - errors.push(PathResolutionError::Private(last_ident.clone())); + current_ns = found_ns; } - current_mod = &def_maps[¤t_mod_id.krate].modules[current_mod_id.local_id.0]; + let (module_def_id, visibility, _) = + current_ns.values.or(current_ns.types).expect("Found empty namespace"); - // Check if namespace - let found_ns = current_mod.find_name(current_ident); + self.add_reference(module_def_id, path.segments.last().unwrap().ident.span(), false); - if found_ns.is_none() { - return Err(PathResolutionError::Unresolved(current_ident.clone())); + if !self.item_in_module_is_visible(current_module_id, visibility) { + errors.push(PathResolutionError::Private(path.last_ident())); } - usage_tracker.mark_as_referenced(current_mod_id, current_ident); - - current_ns = found_ns; + Ok(ResolvedImport { namespace: current_ns, errors }) } - let module_def_id = - current_ns.values.or(current_ns.types).map(|(id, _, _)| id).expect("Found empty namespace"); - - let item = merge_intermediate_path_resolution_item_with_module_def_id( - intermediate_item, - module_def_id, - ); - - Ok(NamespaceResolution { module_id: current_mod_id, item, namespace: current_ns, errors }) -} - -fn resolve_path_name(import_directive: &ImportDirective) -> Ident { - match &import_directive.alias { - None => import_directive.path.last_ident(), - Some(ident) => ident.clone(), + fn add_reference(&mut self, reference_id: ModuleDefId, span: Span, is_self_type_name: bool) { + if let Some(references_tracker) = &mut self.references_tracker { + references_tracker.add_reference(reference_id, span, is_self_type_name); + } } -} -fn resolve_external_dep( - crate_id: CrateId, - directive: &ImportDirective, - interner: &NodeInterner, - def_maps: &BTreeMap, - usage_tracker: &mut UsageTracker, - path_references: &mut Option<&mut Vec>, - importing_crate: CrateId, -) -> NamespaceResolutionResult { - // Use extern_prelude to get the dep - let path = &directive.path.segments; - - let current_def_map = &def_maps[&crate_id]; - - // Fetch the root module from the prelude - let crate_name = &path.first().unwrap().ident; - let dep_module = current_def_map - .extern_prelude - .get(&crate_name.0.contents) - .ok_or_else(|| PathResolutionError::Unresolved(crate_name.to_owned()))?; - - // Create an import directive for the dependency crate - // XXX: This will panic if the path is of the form `use std`. Ideal algorithm will not distinguish between crate and module - // See `singleton_import.nr` test case for a check that such cases are handled elsewhere. - let path_without_crate_name = &path[1..]; - - if let Some(path_references) = path_references { - path_references.push(ReferenceId::Module(*dep_module)); + fn item_in_module_is_visible(&self, module: ModuleId, visibility: ItemVisibility) -> bool { + item_in_module_is_visible(self.def_maps, self.importing_module, module, visibility) } - - let path = Path { - segments: path_without_crate_name.to_vec(), - kind: PathKind::Plain, - span: Span::default(), - }; - let dep_directive = ImportDirective { - visibility: ItemVisibility::Private, - module_id: dep_module.local_id, - self_type_module_id: directive.self_type_module_id, - path, - alias: directive.alias.clone(), - is_prelude: false, - }; - - resolve_path_to_ns( - &dep_directive, - dep_module.krate, - importing_crate, - interner, - def_maps, - usage_tracker, - path_references, - ) } -fn merge_intermediate_path_resolution_item_with_module_def_id( - intermediate_item: IntermediatePathResolutionItem, - module_def_id: ModuleDefId, -) -> PathResolutionItem { - match module_def_id { - ModuleDefId::ModuleId(module_id) => PathResolutionItem::Module(module_id), - ModuleDefId::TypeId(struct_id) => PathResolutionItem::Struct(struct_id), - ModuleDefId::TypeAliasId(type_alias_id) => PathResolutionItem::TypeAlias(type_alias_id), - ModuleDefId::TraitId(trait_id) => PathResolutionItem::Trait(trait_id), - ModuleDefId::GlobalId(global_id) => PathResolutionItem::Global(global_id), - ModuleDefId::FunctionId(func_id) => match intermediate_item { - IntermediatePathResolutionItem::Module(_) => { - PathResolutionItem::ModuleFunction(func_id) - } - IntermediatePathResolutionItem::Struct(struct_id, generics) => { - PathResolutionItem::StructFunction(struct_id, generics, func_id) - } - IntermediatePathResolutionItem::TypeAlias(alias_id, generics) => { - PathResolutionItem::TypeAliasFunction(alias_id, generics, func_id) - } - IntermediatePathResolutionItem::Trait(trait_id, generics) => { - PathResolutionItem::TraitFunction(trait_id, generics, func_id) - } - }, - } +fn get_module(def_maps: &BTreeMap, module: ModuleId) -> &ModuleData { + let message = "A crate should always be present for a given crate id"; + &def_maps.get(&module.krate).expect(message).modules[module.local_id.0] } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/mod.rs index 223b88b5c5d..44a0114074e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/mod.rs @@ -7,5 +7,4 @@ //! will have the same DefinitionId. pub mod errors; pub mod import; -pub mod path_resolver; pub mod visibility; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs deleted file mode 100644 index 98d4aee3f5c..00000000000 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs +++ /dev/null @@ -1,102 +0,0 @@ -use super::import::{resolve_import, ImportDirective, PathResolution, PathResolutionResult}; -use crate::ast::{ItemVisibility, Path}; -use crate::node_interner::{NodeInterner, ReferenceId}; -use crate::usage_tracker::UsageTracker; - -use std::collections::BTreeMap; - -use crate::graph::CrateId; -use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleId}; - -pub trait PathResolver { - /// Resolve the given path returning the resolved ModuleDefId. - /// If `path_references` is `Some`, a `ReferenceId` for each segment in `path` - /// will be resolved and pushed (some entries will be None if they don't refer to - /// a module or type). - fn resolve( - &self, - interner: &NodeInterner, - def_maps: &BTreeMap, - path: Path, - usage_tracker: &mut UsageTracker, - path_references: &mut Option<&mut Vec>, - ) -> PathResolutionResult; - - fn local_module_id(&self) -> LocalModuleId; - - fn module_id(&self) -> ModuleId; -} - -pub struct StandardPathResolver { - // Module that we are resolving the path in - module_id: ModuleId, - // The module of the self type, if any (for example, the ModuleId of a struct) - self_type_module_id: Option, -} - -impl StandardPathResolver { - pub fn new(module_id: ModuleId, self_type_module_id: Option) -> StandardPathResolver { - Self { module_id, self_type_module_id } - } -} - -impl PathResolver for StandardPathResolver { - fn resolve( - &self, - interner: &NodeInterner, - def_maps: &BTreeMap, - path: Path, - usage_tracker: &mut UsageTracker, - path_references: &mut Option<&mut Vec>, - ) -> PathResolutionResult { - resolve_path( - interner, - def_maps, - self.module_id, - self.self_type_module_id, - path, - usage_tracker, - path_references, - ) - } - - fn local_module_id(&self) -> LocalModuleId { - self.module_id.local_id - } - - fn module_id(&self) -> ModuleId { - self.module_id - } -} - -/// Resolve the given path to a function or a type. -/// In the case of a conflict, functions are given priority -pub fn resolve_path( - interner: &NodeInterner, - def_maps: &BTreeMap, - module_id: ModuleId, - self_type_module_id: Option, - path: Path, - usage_tracker: &mut UsageTracker, - path_references: &mut Option<&mut Vec>, -) -> PathResolutionResult { - // lets package up the path into an ImportDirective and resolve it using that - let import = ImportDirective { - visibility: ItemVisibility::Private, - module_id: module_id.local_id, - self_type_module_id, - path, - alias: None, - is_prelude: false, - }; - let resolved_import = resolve_import( - module_id.krate, - &import, - interner, - def_maps, - usage_tracker, - path_references, - )?; - - Ok(PathResolution { item: resolved_import.item, errors: resolved_import.errors }) -} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/visibility.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/visibility.rs index 492f303d2c4..c2fe887fe62 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/visibility.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/visibility.rs @@ -7,34 +7,43 @@ use std::collections::BTreeMap; use crate::ast::ItemVisibility; use crate::hir::def_map::{CrateDefMap, DefMaps, LocalModuleId, ModuleId}; -// Returns false if the given private function is being called from a non-child module, or -// if the given pub(crate) function is being called from another crate. Otherwise returns true. -pub fn can_reference_module_id( +/// Returns true if an item with the given visibility in the target module +/// is visible from the current module. For example: +/// ```text +/// mod foo { +/// ^^^ <-- target module +/// pub(crate) fn bar() {} +/// ^^^^^^^^^^ <- visibility +/// } +/// ``` +pub fn item_in_module_is_visible( def_maps: &BTreeMap, - importing_crate: CrateId, - current_module: LocalModuleId, + current_module: ModuleId, target_module: ModuleId, visibility: ItemVisibility, ) -> bool { // Note that if the target module is in a different crate from the current module then we will either // return true as the target module is public or return false as it is private without looking at the `CrateDefMap` in either case. - let same_crate = target_module.krate == importing_crate; + let same_crate = target_module.krate == current_module.krate; match visibility { ItemVisibility::Public => true, ItemVisibility::PublicCrate => same_crate, ItemVisibility::Private => { + if !same_crate { + return false; + } + let target_crate_def_map = &def_maps[&target_module.krate]; - same_crate - && (module_descendent_of_target( - target_crate_def_map, - target_module.local_id, - current_module, - ) || module_is_parent_of_struct_module( - target_crate_def_map, - current_module, - target_module.local_id, - )) + module_descendent_of_target( + target_crate_def_map, + target_module.local_id, + current_module.local_id, + ) || module_is_parent_of_struct_module( + target_crate_def_map, + current_module.local_id, + target_module.local_id, + ) } } } @@ -116,10 +125,9 @@ pub fn method_call_is_visible( ItemVisibility::Private => { if object_type.is_primitive() { let func_module = interner.function_module(func_id); - can_reference_module_id( + item_in_module_is_visible( def_maps, - current_module.krate, - current_module.local_id, + current_module, func_module, modifiers.visibility, ) 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 cb69053b72a..a63601a4280 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 @@ -11,7 +11,7 @@ use crate::ast::{ use crate::hir::resolution::errors::ResolverError; use crate::hir_def::expr::HirBinaryOp; use crate::hir_def::traits::TraitConstraint; -use crate::hir_def::types::Type; +use crate::hir_def::types::{BinaryTypeOperator, Kind, Type}; use crate::node_interner::NodeInterner; #[derive(Error, Debug, Clone, PartialEq, Eq)] @@ -34,12 +34,22 @@ pub enum Source { Return(FunctionReturnType, Span), } -#[derive(Error, Debug, Clone)] +#[derive(Error, Debug, Clone, PartialEq, Eq)] pub enum TypeCheckError { #[error("Operator {op:?} cannot be used in a {place:?}")] OpCannotBeUsed { op: HirBinaryOp, place: &'static str, span: Span }, + #[error("Division by zero: {lhs} / {rhs}")] + DivisionByZero { lhs: FieldElement, rhs: FieldElement, span: Span }, + #[error("Modulo on Field elements: {lhs} % {rhs}")] + ModuloOnFields { lhs: FieldElement, rhs: FieldElement, span: Span }, #[error("The value `{expr:?}` cannot fit into `{ty}` which has range `{range}`")] OverflowingAssignment { expr: FieldElement, ty: Type, range: String, span: Span }, + #[error( + "The value `{value}` cannot fit into `{kind}` which has a maximum size of `{maximum_size}`" + )] + OverflowingConstant { value: FieldElement, kind: Kind, maximum_size: FieldElement, span: Span }, + #[error("Evaluating `{op}` on `{lhs}`, `{rhs}` failed")] + FailingBinaryOp { op: BinaryTypeOperator, lhs: i128, rhs: i128, span: Span }, #[error("Type {typ:?} cannot be used in a {place:?}")] TypeCannotBeUsed { typ: Type, place: &'static str, span: Span }, #[error("Expected type {expected_typ:?} is not the same as {expr_typ:?}")] @@ -48,6 +58,14 @@ pub enum TypeCheckError { TypeMismatchWithSource { expected: Type, actual: Type, span: Span, source: Source }, #[error("Expected type {expected_kind:?} is not the same as {expr_kind:?}")] TypeKindMismatch { expected_kind: String, expr_kind: String, expr_span: Span }, + #[error("Evaluating {to} resulted in {to_value}, but {from_value} was expected")] + TypeCanonicalizationMismatch { + to: Type, + from: Type, + to_value: FieldElement, + from_value: FieldElement, + span: Span, + }, // TODO(https://github.com/noir-lang/noir/issues/6238): implement handling for larger types #[error("Expected type {expected_kind} when evaluating globals, but found {expr_kind} (this warning may become an error in the future)")] EvaluatedGlobalIsntU32 { expected_kind: String, expr_kind: String, expr_span: Span }, @@ -158,6 +176,8 @@ pub enum TypeCheckError { Unsafe { span: Span }, #[error("Converting an unconstrained fn to a non-unconstrained fn is unsafe")] UnsafeFn { span: Span }, + #[error("Expected a constant, but found `{typ}`")] + NonConstantEvaluated { typ: Type, span: Span }, #[error("Slices must have constant length")] NonConstantSliceLength { span: Span }, #[error("Only sized types may be used in the entry point to a program")] @@ -196,6 +216,10 @@ impl TypeCheckError { pub fn add_context(self, ctx: &'static str) -> Self { TypeCheckError::Context { err: Box::new(self), ctx } } + + pub(crate) fn is_non_constant_evaluated(&self) -> bool { + matches!(self, TypeCheckError::NonConstantEvaluated { .. }) + } } impl<'a> From<&'a TypeCheckError> for Diagnostic { @@ -216,6 +240,16 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic { String::new(), *span, ), + TypeCheckError::DivisionByZero { lhs, rhs, span } => Diagnostic::simple_error( + format!("Division by zero: {lhs} / {rhs}"), + String::new(), + *span, + ), + TypeCheckError::ModuloOnFields { lhs, rhs, span } => Diagnostic::simple_error( + format!("Modulo on Field elements: {lhs} % {rhs}"), + String::new(), + *span, + ), TypeCheckError::TypeMismatch { expected_typ, expr_typ, expr_span } => { Diagnostic::simple_error( format!("Expected type {expected_typ}, found type {expr_typ}"), @@ -230,6 +264,13 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic { *expr_span, ) } + TypeCheckError::TypeCanonicalizationMismatch { to, from, to_value, from_value, span } => { + Diagnostic::simple_error( + format!("Evaluating {to} resulted in {to_value}, but {from_value} was expected"), + format!("from evaluating {from} without simplifications"), + *span, + ) + } // TODO(https://github.com/noir-lang/noir/issues/6238): implement // handling for larger types TypeCheckError::EvaluatedGlobalIsntU32 { expected_kind, expr_kind, expr_span } => { @@ -320,11 +361,14 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic { | TypeCheckError::AmbiguousBitWidth { span, .. } | TypeCheckError::IntegerAndFieldBinaryOperation { span } | TypeCheckError::OverflowingAssignment { span, .. } + | TypeCheckError::OverflowingConstant { span, .. } + | TypeCheckError::FailingBinaryOp { span, .. } | TypeCheckError::FieldModulo { span } | TypeCheckError::FieldNot { span } | TypeCheckError::ConstrainedReferenceToUnconstrained { span } | TypeCheckError::UnconstrainedReferenceToConstrained { span } | TypeCheckError::UnconstrainedSliceReturnToConstrained { span } + | TypeCheckError::NonConstantEvaluated { span, .. } | TypeCheckError::NonConstantSliceLength { span } | TypeCheckError::StringIndexAssign { span } | TypeCheckError::InvalidShiftSize { span } => { 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 6ecfdefe996..db6c3507b15 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 @@ -9,7 +9,7 @@ use crate::ast::{BlockExpression, FunctionKind, FunctionReturnType, Visibility}; use crate::graph::CrateId; use crate::hir::def_map::LocalModuleId; use crate::node_interner::{ExprId, NodeInterner, StructId, TraitId, TraitImplId}; -use crate::token::CustomAttribute; + use crate::{ResolvedGeneric, Type}; /// A Hir function is a block expression with a list of statements. @@ -164,9 +164,6 @@ pub struct FuncMeta { /// If this function is from an impl (trait or regular impl), this /// is the object type of the impl. Otherwise this is None. pub self_type: Option, - - /// Custom attributes attached to this function. - pub custom_attributes: Vec, } #[derive(Debug, Clone)] diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/stmt.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/stmt.rs index b97e99583bb..0258cfd8ddb 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/stmt.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/stmt.rs @@ -105,7 +105,7 @@ impl HirPattern { } } - pub(crate) fn location(&self) -> Location { + pub fn location(&self) -> Location { match self { HirPattern::Identifier(ident) => ident.location, HirPattern::Mutable(_, location) 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 0eed79348e2..a0fea3aa774 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 @@ -5,6 +5,9 @@ use std::{ rc::Rc, }; +#[cfg(test)] +use proptest_derive::Arbitrary; + use acvm::{AcirField, FieldElement}; use crate::{ @@ -91,6 +94,14 @@ pub enum Type { /// like `fn foo(...) {}`. Unlike TypeVariables, they cannot be bound over. NamedGeneric(TypeVariable, Rc), + /// A cast (to, from) that's checked at monomorphization. + /// + /// Simplifications on arithmetic generics are only allowed on the LHS. + CheckedCast { + from: Box, + to: Box, + }, + /// A functions with arguments, a return type and environment. /// the environment should be `Unit` by default, /// for closures it should contain a `Tuple` type with the captured @@ -161,6 +172,11 @@ pub enum Kind { } impl Kind { + // Kind::Numeric constructor helper + pub fn numeric(typ: Type) -> Kind { + Kind::Numeric(Box::new(typ)) + } + pub(crate) fn is_error(&self) -> bool { match self.follow_bindings() { Self::Numeric(typ) => *typ == Type::Error, @@ -188,7 +204,7 @@ impl Kind { } pub(crate) fn u32() -> Self { - Self::Numeric(Box::new(Type::Integer(Signedness::Unsigned, IntegerBitSize::ThirtyTwo))) + Self::numeric(Type::Integer(Signedness::Unsigned, IntegerBitSize::ThirtyTwo)) } pub(crate) fn follow_bindings(&self) -> Self { @@ -197,7 +213,7 @@ impl Kind { Self::Normal => Self::Normal, Self::Integer => Self::Integer, Self::IntegerOrField => Self::IntegerOrField, - Self::Numeric(typ) => Self::Numeric(Box::new(typ.follow_bindings())), + Self::Numeric(typ) => Self::numeric(typ.follow_bindings()), } } @@ -255,10 +271,21 @@ impl Kind { } /// Ensure the given value fits in self.integral_maximum_size() - fn ensure_value_fits(&self, value: FieldElement) -> Option { + fn ensure_value_fits( + &self, + value: FieldElement, + span: Span, + ) -> Result { match self.integral_maximum_size() { - None => Some(value), - Some(maximum_size) => (value <= maximum_size).then_some(value), + None => Ok(value), + Some(maximum_size) => (value <= maximum_size).then_some(value).ok_or_else(|| { + TypeCheckError::OverflowingConstant { + value, + kind: self.clone(), + maximum_size, + span, + } + }), } } } @@ -652,6 +679,7 @@ impl Shared { /// A restricted subset of binary operators useable on /// type level integers for use in the array length positions of types. +#[cfg_attr(test, derive(Arbitrary))] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum BinaryTypeOperator { Addition, @@ -863,6 +891,7 @@ impl std::fmt::Display for Type { TypeBinding::Unbound(_, _) if name.is_empty() => write!(f, "_"), TypeBinding::Unbound(_, _) => write!(f, "{name}"), }, + Type::CheckedCast { to, .. } => write!(f, "{to}"), Type::Constant(x, _kind) => write!(f, "{x}"), Type::Forall(typevars, typ) => { let typevars = vecmap(typevars, |var| var.id().to_string()); @@ -887,7 +916,7 @@ impl std::fmt::Display for Type { } Type::Quoted(quoted) => write!(f, "{}", quoted), Type::InfixExpr(lhs, op, rhs) => { - let this = self.canonicalize(); + let this = self.canonicalize_checked(); // Prevent infinite recursion if this != *self { @@ -1064,6 +1093,7 @@ impl Type { | Type::TypeVariable(..) | Type::TraitAsType(..) | Type::NamedGeneric(..) + | Type::CheckedCast { .. } | Type::Forall(..) | Type::Constant(..) | Type::Quoted(..) @@ -1106,6 +1136,10 @@ impl Type { Type::NamedGeneric(_, _) => { named_generic_is_numeric(self, found_names); } + Type::CheckedCast { from, to } => { + to.find_numeric_type_vars(found_names); + from.find_numeric_type_vars(found_names); + } Type::TraitAsType(_, _, args) => { for arg in args.ordered.iter() { @@ -1187,9 +1221,10 @@ impl Type { | Type::Forall(_, _) | Type::Quoted(_) | Type::Slice(_) - | Type::InfixExpr(_, _, _) | Type::TraitAsType(..) => false, + Type::CheckedCast { to, .. } => to.is_valid_for_program_input(), + Type::Alias(alias, generics) => { let alias = alias.borrow(); alias.get_type(generics).is_valid_for_program_input() @@ -1205,6 +1240,10 @@ impl Type { .get_fields(generics) .into_iter() .all(|(_, field)| field.is_valid_for_program_input()), + + Type::InfixExpr(lhs, _, rhs) => { + lhs.is_valid_for_program_input() && rhs.is_valid_for_program_input() + } } } @@ -1239,6 +1278,8 @@ impl Type { | Type::Quoted(_) | Type::TraitAsType(..) => false, + Type::CheckedCast { to, .. } => to.is_valid_non_inlined_function_input(), + Type::Alias(alias, generics) => { let alias = alias.borrow(); alias.get_type(generics).is_valid_non_inlined_function_input() @@ -1280,6 +1321,8 @@ impl Type { } } + Type::CheckedCast { to, .. } => to.is_valid_for_unconstrained_boundary(), + // Quoted objects only exist at compile-time where the only execution // environment is the interpreter. In this environment, they are valid. Type::Quoted(_) => true, @@ -1312,6 +1355,7 @@ impl Type { pub fn generic_count(&self) -> usize { match self { Type::Forall(generics, _) => generics.len(), + Type::CheckedCast { to, .. } => to.generic_count(), Type::TypeVariable(type_variable) | Type::NamedGeneric(type_variable, _) => { match &*type_variable.borrow() { TypeBinding::Bound(binding) => binding.generic_count(), @@ -1351,6 +1395,7 @@ impl Type { pub(crate) fn kind(&self) -> Kind { match self { + Type::CheckedCast { to, .. } => to.kind(), Type::NamedGeneric(var, _) => var.kind(), Type::Constant(_, kind) => kind.clone(), Type::TypeVariable(var) => match &*var.borrow() { @@ -1386,32 +1431,33 @@ impl Type { if self_kind.unifies(&other_kind) { self_kind } else { - Kind::Numeric(Box::new(Type::Error)) + Kind::numeric(Type::Error) } } /// Returns the number of field elements required to represent the type once encoded. - pub fn field_count(&self) -> u32 { + pub fn field_count(&self, location: &Location) -> u32 { match self { Type::FieldElement | Type::Integer { .. } | Type::Bool => 1, Type::Array(size, typ) => { let length = size - .evaluate_to_u32() + .evaluate_to_u32(location.span) .expect("Cannot have variable sized arrays as a parameter to main"); let typ = typ.as_ref(); - length * typ.field_count() + length * typ.field_count(location) } Type::Struct(def, args) => { let struct_type = def.borrow(); let fields = struct_type.get_fields(args); - fields.iter().fold(0, |acc, (_, field_type)| acc + field_type.field_count()) + fields.iter().fold(0, |acc, (_, field_type)| acc + field_type.field_count(location)) } - Type::Alias(def, generics) => def.borrow().get_type(generics).field_count(), + Type::CheckedCast { to, .. } => to.field_count(location), + Type::Alias(def, generics) => def.borrow().get_type(generics).field_count(location), Type::Tuple(fields) => { - fields.iter().fold(0, |acc, field_typ| acc + field_typ.field_count()) + fields.iter().fold(0, |acc, field_typ| acc + field_typ.field_count(location)) } Type::String(size) => size - .evaluate_to_u32() + .evaluate_to_u32(location.span) .expect("Cannot have variable sized strings as a parameter to main"), Type::FmtString(_, _) | Type::Unit @@ -1582,6 +1628,7 @@ impl Type { match self { Type::TypeVariable(var) => Some((var.1.clone(), var.kind())), Type::NamedGeneric(var, _) => Some((var.1.clone(), var.kind())), + Type::CheckedCast { to, .. } => to.get_inner_type_variable(), _ => None, } } @@ -1696,6 +1743,10 @@ impl Type { } } + (CheckedCast { to, .. }, other) | (other, CheckedCast { to, .. }) => { + to.try_unify(other, bindings) + } + (NamedGeneric(binding, _), other) | (other, NamedGeneric(binding, _)) if !binding.borrow().is_unbound() => { @@ -1758,7 +1809,8 @@ impl Type { } (Constant(value, kind), other) | (other, Constant(value, kind)) => { - if let Some(other_value) = other.evaluate_to_field_element(kind) { + let dummy_span = Span::default(); + if let Ok(other_value) = other.evaluate_to_field_element(kind, dummy_span) { if *value == other_value && kind.unifies(&other.kind()) { Ok(()) } else { @@ -1926,41 +1978,106 @@ impl Type { /// If this type is a Type::Constant (used in array lengths), or is bound /// to a Type::Constant, return the constant as a u32. - pub fn evaluate_to_u32(&self) -> Option { - self.evaluate_to_field_element(&Kind::u32()) - .and_then(|field_element| field_element.try_to_u32()) + pub fn evaluate_to_u32(&self, span: Span) -> Result { + self.evaluate_to_field_element(&Kind::u32(), span).map(|field_element| { + field_element + .try_to_u32() + .expect("ICE: size should have already been checked by evaluate_to_field_element") + }) } // TODO(https://github.com/noir-lang/noir/issues/6260): remove // the unifies checks once all kinds checks are implemented? - pub(crate) fn evaluate_to_field_element(&self, kind: &Kind) -> Option { + pub(crate) fn evaluate_to_field_element( + &self, + kind: &Kind, + span: Span, + ) -> Result { + let run_simplifications = true; + self.evaluate_to_field_element_helper(kind, span, run_simplifications) + } + + /// evaluate_to_field_element with optional generic arithmetic simplifications + pub(crate) fn evaluate_to_field_element_helper( + &self, + kind: &Kind, + span: Span, + run_simplifications: bool, + ) -> Result { if let Some((binding, binding_kind)) = self.get_inner_type_variable() { if let TypeBinding::Bound(binding) = &*binding.borrow() { if kind.unifies(&binding_kind) { - return binding.evaluate_to_field_element(&binding_kind); + return binding.evaluate_to_field_element_helper( + &binding_kind, + span, + run_simplifications, + ); } } } - match self.canonicalize() { + let could_be_checked_cast = false; + match self.canonicalize_helper(could_be_checked_cast, run_simplifications) { Type::Constant(x, constant_kind) => { if kind.unifies(&constant_kind) { - kind.ensure_value_fits(x) + kind.ensure_value_fits(x, span) } else { - None + Err(TypeCheckError::TypeKindMismatch { + expected_kind: format!("{}", constant_kind), + expr_kind: format!("{}", kind), + expr_span: span, + }) } } Type::InfixExpr(lhs, op, rhs) => { let infix_kind = lhs.infix_kind(&rhs); if kind.unifies(&infix_kind) { - let lhs_value = lhs.evaluate_to_field_element(&infix_kind)?; - let rhs_value = rhs.evaluate_to_field_element(&infix_kind)?; - op.function(lhs_value, rhs_value, &infix_kind) + let lhs_value = lhs.evaluate_to_field_element_helper( + &infix_kind, + span, + run_simplifications, + )?; + let rhs_value = rhs.evaluate_to_field_element_helper( + &infix_kind, + span, + run_simplifications, + )?; + op.function(lhs_value, rhs_value, &infix_kind, span) } else { - None + Err(TypeCheckError::TypeKindMismatch { + expected_kind: format!("{}", kind), + expr_kind: format!("{}", infix_kind), + expr_span: span, + }) } } - _ => None, + Type::CheckedCast { from, to } => { + let to_value = to.evaluate_to_field_element(kind, span)?; + + // if both 'to' and 'from' evaluate to a constant, + // return None unless they match + let skip_simplifications = false; + if let Ok(from_value) = + from.evaluate_to_field_element_helper(kind, span, skip_simplifications) + { + if to_value == from_value { + Ok(to_value) + } else { + let to = *to.clone(); + let from = *from.clone(); + Err(TypeCheckError::TypeCanonicalizationMismatch { + to, + from, + to_value, + from_value, + span, + }) + } + } else { + Ok(to_value) + } + } + other => Err(TypeCheckError::NonConstantEvaluated { typ: other, span }), } } @@ -2182,6 +2299,11 @@ impl Type { let fields = fields.substitute_helper(type_bindings, substitute_bound_typevars); Type::FmtString(Box::new(size), Box::new(fields)) } + Type::CheckedCast { from, to } => { + let from = from.substitute_helper(type_bindings, substitute_bound_typevars); + let to = to.substitute_helper(type_bindings, substitute_bound_typevars); + Type::CheckedCast { from: Box::new(from), to: Box::new(to) } + } Type::NamedGeneric(binding, _) | Type::TypeVariable(binding) => { substitute_binding(binding) } @@ -2271,6 +2393,7 @@ impl Type { || args.named.iter().any(|arg| arg.typ.occurs(target_id)) } Type::Tuple(fields) => fields.iter().any(|field| field.occurs(target_id)), + Type::CheckedCast { from, to } => from.occurs(target_id) || to.occurs(target_id), Type::NamedGeneric(type_var, _) | Type::TypeVariable(type_var) => { match &*type_var.borrow() { TypeBinding::Bound(binding) => { @@ -2329,6 +2452,11 @@ impl Type { def.borrow().get_type(args).follow_bindings() } Tuple(args) => Tuple(vecmap(args, |arg| arg.follow_bindings())), + CheckedCast { from, to } => { + let from = Box::new(from.follow_bindings()); + let to = Box::new(to.follow_bindings()); + CheckedCast { from, to } + } TypeVariable(var) | NamedGeneric(var, _) => { if let TypeBinding::Bound(typ) = &*var.borrow() { return typ.follow_bindings(); @@ -2425,6 +2553,10 @@ impl Type { generic.typ.replace_named_generics_with_type_variables(); } } + Type::CheckedCast { from, to } => { + from.replace_named_generics_with_type_variables(); + to.replace_named_generics_with_type_variables(); + } Type::NamedGeneric(var, _) => { let type_binding = var.borrow(); if let TypeBinding::Bound(binding) = &*type_binding { @@ -2482,6 +2614,7 @@ impl Type { } } Type::Alias(alias, args) => alias.borrow().get_type(args).integral_maximum_size(), + Type::CheckedCast { to, .. } => to.integral_maximum_size(), Type::NamedGeneric(binding, _name) => match &*binding.borrow() { TypeBinding::Bound(typ) => typ.integral_maximum_size(), TypeBinding::Unbound(_, kind) => kind.integral_maximum_size(), @@ -2541,28 +2674,39 @@ fn convert_array_expression_to_slice( impl BinaryTypeOperator { /// Perform the actual rust numeric operation associated with this operator - pub fn function(self, a: FieldElement, b: FieldElement, kind: &Kind) -> Option { + pub fn function( + self, + a: FieldElement, + b: FieldElement, + kind: &Kind, + span: Span, + ) -> Result { match kind.follow_bindings().integral_maximum_size() { None => match self { - BinaryTypeOperator::Addition => Some(a + b), - BinaryTypeOperator::Subtraction => Some(a - b), - BinaryTypeOperator::Multiplication => Some(a * b), - BinaryTypeOperator::Division => (b != FieldElement::zero()).then(|| a / b), - BinaryTypeOperator::Modulo => None, + BinaryTypeOperator::Addition => Ok(a + b), + BinaryTypeOperator::Subtraction => Ok(a - b), + BinaryTypeOperator::Multiplication => Ok(a * b), + BinaryTypeOperator::Division => (b != FieldElement::zero()) + .then(|| a / b) + .ok_or(TypeCheckError::DivisionByZero { lhs: a, rhs: b, span }), + BinaryTypeOperator::Modulo => { + Err(TypeCheckError::ModuloOnFields { lhs: a, rhs: b, span }) + } }, Some(_maximum_size) => { let a = a.to_i128(); let b = b.to_i128(); + let err = TypeCheckError::FailingBinaryOp { op: self, lhs: a, rhs: b, span }; let result = match self { - BinaryTypeOperator::Addition => a.checked_add(b)?, - BinaryTypeOperator::Subtraction => a.checked_sub(b)?, - BinaryTypeOperator::Multiplication => a.checked_mul(b)?, - BinaryTypeOperator::Division => a.checked_div(b)?, - BinaryTypeOperator::Modulo => a.checked_rem(b)?, + BinaryTypeOperator::Addition => a.checked_add(b).ok_or(err)?, + BinaryTypeOperator::Subtraction => a.checked_sub(b).ok_or(err)?, + BinaryTypeOperator::Multiplication => a.checked_mul(b).ok_or(err)?, + BinaryTypeOperator::Division => a.checked_div(b).ok_or(err)?, + BinaryTypeOperator::Modulo => a.checked_rem(b).ok_or(err)?, }; - Some(result.into()) + Ok(result.into()) } } } @@ -2607,7 +2751,9 @@ impl From<&Type> for PrintableType { match value { Type::FieldElement => PrintableType::Field, Type::Array(size, typ) => { - let length = size.evaluate_to_u32().expect("Cannot print variable sized arrays"); + let dummy_span = Span::default(); + let length = + size.evaluate_to_u32(dummy_span).expect("Cannot print variable sized arrays"); let typ = typ.as_ref(); PrintableType::Array { length, typ: Box::new(typ.into()) } } @@ -2632,7 +2778,9 @@ impl From<&Type> for PrintableType { }, Type::Bool => PrintableType::Boolean, Type::String(size) => { - let size = size.evaluate_to_u32().expect("Cannot print variable sized strings"); + let dummy_span = Span::default(); + let size = + size.evaluate_to_u32(dummy_span).expect("Cannot print variable sized strings"); PrintableType::String { length: size } } Type::FmtString(_, _) => unreachable!("format strings cannot be printed"), @@ -2648,6 +2796,7 @@ impl From<&Type> for PrintableType { Type::Alias(alias, args) => alias.borrow().get_type(args).into(), Type::TraitAsType(..) => unreachable!(), Type::Tuple(types) => PrintableType::Tuple { types: vecmap(types, |typ| typ.into()) }, + Type::CheckedCast { to, .. } => to.as_ref().into(), Type::NamedGeneric(..) => unreachable!(), Type::Forall(..) => unreachable!(), Type::Function(arguments, return_type, env, unconstrained) => PrintableType::Function { @@ -2722,6 +2871,7 @@ impl std::fmt::Debug for Type { } Type::Unit => write!(f, "()"), Type::Error => write!(f, "error"), + Type::CheckedCast { to, .. } => write!(f, "{:?}", to), Type::NamedGeneric(binding, name) => match binding.kind() { Kind::Any | Kind::Normal | Kind::Integer | Kind::IntegerOrField => { write!(f, "{}{:?}", name, binding) @@ -2836,6 +2986,7 @@ impl std::hash::Hash for Type { vars.hash(state); typ.hash(state); } + Type::CheckedCast { to, .. } => to.hash(state), Type::Constant(value, _) => value.hash(state), Type::Quoted(typ) => typ.hash(state), Type::InfixExpr(lhs, op, rhs) => { @@ -2902,6 +3053,7 @@ impl PartialEq for Type { (Forall(lhs_vars, lhs_type), Forall(rhs_vars, rhs_type)) => { lhs_vars == rhs_vars && lhs_type == rhs_type } + (CheckedCast { to, .. }, other) | (other, CheckedCast { to, .. }) => **to == *other, (Constant(lhs, lhs_kind), Constant(rhs, rhs_kind)) => { lhs == rhs && lhs_kind == rhs_kind } 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 81f638ebca4..8cdf6f5502c 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,6 +1,7 @@ use std::collections::BTreeMap; use acvm::{AcirField, FieldElement}; +use noirc_errors::Span; use crate::{BinaryTypeOperator, Type, TypeBindings, UnificationError}; @@ -15,34 +16,81 @@ impl Type { /// - `canonicalize[((1 + N) + M) + 2] = (M + N) + 3` /// - `canonicalize[A + 2 * B + 3 - 2] = A + (B * 2) + 3 - 2` pub fn canonicalize(&self) -> Type { + match self.follow_bindings() { + Type::CheckedCast { from, to } => Type::CheckedCast { + from: Box::new(from.canonicalize_checked()), + to: Box::new(to.canonicalize_unchecked()), + }, + + other => { + let non_checked_cast = false; + let run_simplifications = true; + other.canonicalize_helper(non_checked_cast, run_simplifications) + } + } + } + + /// Only simplify constants and drop/skip any CheckedCast's + pub(crate) fn canonicalize_checked(&self) -> Type { + let found_checked_cast = true; + let skip_simplifications = false; + self.canonicalize_helper(found_checked_cast, skip_simplifications) + } + + /// Run all simplifications and drop/skip any CheckedCast's + fn canonicalize_unchecked(&self) -> Type { + let found_checked_cast = true; + let run_simplifications = true; + self.canonicalize_helper(found_checked_cast, run_simplifications) + } + + /// If found_checked_cast, then drop additional CheckedCast's + /// + /// If run_simplifications is false, then only: + /// - Attempt to evaluate each sub-expression to a constant + /// - Drop nested CheckedCast's + /// + /// Otherwise also attempt try_simplify_partial_constants, sort_commutative, + /// and other simplifications + pub(crate) fn canonicalize_helper( + &self, + found_checked_cast: bool, + run_simplifications: bool, + ) -> Type { match self.follow_bindings() { Type::InfixExpr(lhs, op, rhs) => { let kind = lhs.infix_kind(&rhs); + let dummy_span = Span::default(); // evaluate_to_field_element also calls canonicalize so if we just called // `self.evaluate_to_field_element(..)` we'd get infinite recursion. - if let (Some(lhs_u32), Some(rhs_u32)) = - (lhs.evaluate_to_field_element(&kind), rhs.evaluate_to_field_element(&kind)) - { - let kind = lhs.infix_kind(&rhs); - if let Some(result) = op.function(lhs_u32, rhs_u32, &kind) { + if let (Ok(lhs_value), Ok(rhs_value)) = ( + lhs.evaluate_to_field_element_helper(&kind, dummy_span, run_simplifications), + rhs.evaluate_to_field_element_helper(&kind, dummy_span, run_simplifications), + ) { + if let Ok(result) = op.function(lhs_value, rhs_value, &kind, dummy_span) { return Type::Constant(result, kind); } } - let lhs = lhs.canonicalize(); - let rhs = rhs.canonicalize(); + let lhs = lhs.canonicalize_helper(found_checked_cast, run_simplifications); + let rhs = rhs.canonicalize_helper(found_checked_cast, run_simplifications); + + if !run_simplifications { + return Type::InfixExpr(Box::new(lhs), op, Box::new(rhs)); + } + if let Some(result) = Self::try_simplify_non_constants_in_lhs(&lhs, op, &rhs) { - return result.canonicalize(); + return result.canonicalize_unchecked(); } if let Some(result) = Self::try_simplify_non_constants_in_rhs(&lhs, op, &rhs) { - return result.canonicalize(); + return result.canonicalize_unchecked(); } // Try to simplify partially constant expressions in the form `(N op1 C1) op2 C2` // where C1 and C2 are constants that can be combined (e.g. N + 5 - 3 = N + 2) if let Some(result) = Self::try_simplify_partial_constants(&lhs, op, &rhs) { - return result.canonicalize(); + return result.canonicalize_unchecked(); } if op.is_commutative() { @@ -51,6 +99,18 @@ impl Type { Type::InfixExpr(Box::new(lhs), op, Box::new(rhs)) } + Type::CheckedCast { from, to } => { + let inner_found_checked_cast = true; + let to = to.canonicalize_helper(inner_found_checked_cast, run_simplifications); + + if found_checked_cast { + return to; + } + + let from = from.canonicalize_checked(); + + Type::CheckedCast { from: Box::new(from), to: Box::new(to) } + } other => other, } } @@ -70,13 +130,16 @@ impl Type { // Push each non-constant term to `sorted` to sort them. Recur on InfixExprs with the same operator. while let Some(item) = queue.pop() { - match item.canonicalize() { - Type::InfixExpr(lhs, new_op, rhs) if new_op == op => { - queue.push(*lhs); - queue.push(*rhs); + match item.canonicalize_unchecked() { + Type::InfixExpr(lhs_inner, new_op, rhs_inner) if new_op == op => { + queue.push(*lhs_inner); + queue.push(*rhs_inner); } Type::Constant(new_constant, new_constant_kind) => { - if let Some(result) = op.function(constant, new_constant, &new_constant_kind) { + let dummy_span = Span::default(); + if let Ok(result) = + op.function(constant, new_constant, &new_constant_kind, dummy_span) + { constant = result; } else { let constant = Type::Constant(new_constant, new_constant_kind); @@ -126,20 +189,27 @@ impl Type { op: BinaryTypeOperator, rhs: &Type, ) -> Option { - let Type::InfixExpr(l_lhs, l_op, l_rhs) = lhs.follow_bindings() else { - return None; - }; + match lhs.follow_bindings() { + Type::CheckedCast { from, to } => { + // Apply operation directly to `from` while attempting simplification to `to`. + let from = Type::InfixExpr(from, op, Box::new(rhs.clone())); + let to = Self::try_simplify_non_constants_in_lhs(&to, op, rhs)?; + Some(Type::CheckedCast { from: Box::new(from), to: Box::new(to) }) + } + Type::InfixExpr(l_lhs, l_op, l_rhs) => { + // Note that this is exact, syntactic equality, not unification. + // `rhs` is expected to already be in canonical form. + if l_op.approx_inverse() != Some(op) + || l_op == BinaryTypeOperator::Division + || l_rhs.canonicalize_unchecked() != *rhs + { + return None; + } - // Note that this is exact, syntactic equality, not unification. - // `rhs` is expected to already be in canonical form. - if l_op.approx_inverse() != Some(op) - || l_op == BinaryTypeOperator::Division - || l_rhs.canonicalize() != *rhs - { - return None; + Some(*l_lhs) + } + _ => None, } - - Some(*l_lhs) } /// Try to simplify non-constant expressions in the form `N op1 (M op1 N)` @@ -156,23 +226,31 @@ impl Type { op: BinaryTypeOperator, rhs: &Type, ) -> Option { - let Type::InfixExpr(r_lhs, r_op, r_rhs) = rhs.follow_bindings() else { - return None; - }; + match rhs.follow_bindings() { + Type::CheckedCast { from, to } => { + // Apply operation directly to `from` while attempting simplification to `to`. + let from = Type::InfixExpr(Box::new(lhs.clone()), op, from); + let to = Self::try_simplify_non_constants_in_rhs(lhs, op, &to)?; + Some(Type::CheckedCast { from: Box::new(from), to: Box::new(to) }) + } + Type::InfixExpr(r_lhs, r_op, r_rhs) => { + // `N / (M * N)` should be simplified to `1 / M`, but we only handle + // simplifying to `M` in this function. + if op == BinaryTypeOperator::Division && r_op == BinaryTypeOperator::Multiplication + { + return None; + } - // `N / (M * N)` should be simplified to `1 / M`, but we only handle - // simplifying to `M` in this function. - if op == BinaryTypeOperator::Division && r_op == BinaryTypeOperator::Multiplication { - return None; - } + // Note that this is exact, syntactic equality, not unification. + // `lhs` is expected to already be in canonical form. + if r_op.inverse() != Some(op) || *lhs != r_rhs.canonicalize_unchecked() { + return None; + } - // Note that this is exact, syntactic equality, not unification. - // `lhs` is expected to already be in canonical form. - if r_op.inverse() != Some(op) || *lhs != r_rhs.canonicalize() { - return None; + Some(*r_lhs) + } + _ => None, } - - Some(*r_lhs) } /// Given: @@ -187,13 +265,15 @@ impl Type { rhs: &Type, ) -> Option<(Box, BinaryTypeOperator, FieldElement, FieldElement)> { let kind = lhs.infix_kind(rhs); - let rhs = rhs.evaluate_to_field_element(&kind)?; + let dummy_span = Span::default(); + let rhs = rhs.evaluate_to_field_element(&kind, dummy_span).ok()?; let Type::InfixExpr(l_type, l_op, l_rhs) = lhs.follow_bindings() else { return None; }; - let l_rhs = l_rhs.evaluate_to_field_element(&kind)?; + let dummy_span = Span::default(); + let l_rhs = l_rhs.evaluate_to_field_element(&kind, dummy_span).ok()?; Some((l_type, l_op, l_rhs, rhs)) } @@ -218,7 +298,9 @@ impl Type { if l_op == Subtraction { op = op.inverse()?; } - let result = op.function(l_const, r_const, &lhs.infix_kind(rhs))?; + let dummy_span = Span::default(); + let result = + op.function(l_const, r_const, &lhs.infix_kind(rhs), dummy_span).ok()?; let constant = Type::Constant(result, lhs.infix_kind(rhs)); Some(Type::InfixExpr(l_type, l_op, Box::new(constant))) } @@ -231,7 +313,9 @@ impl Type { if op == Division && (r_const == FieldElement::zero() || !divides_evenly) { None } else { - let result = op.function(l_const, r_const, &lhs.infix_kind(rhs))?; + let dummy_span = Span::default(); + let result = + op.function(l_const, r_const, &lhs.infix_kind(rhs), dummy_span).ok()?; let constant = Box::new(Type::Constant(result, lhs.infix_kind(rhs))); Some(Type::InfixExpr(l_type, l_op, constant)) } @@ -250,7 +334,8 @@ impl Type { if let Type::InfixExpr(lhs_a, op_a, rhs_a) = self { if let Some(inverse) = op_a.approx_inverse() { let kind = lhs_a.infix_kind(rhs_a); - if let Some(rhs_a_value) = rhs_a.evaluate_to_field_element(&kind) { + let dummy_span = Span::default(); + if let Ok(rhs_a_value) = rhs_a.evaluate_to_field_element(&kind, dummy_span) { let rhs_a = Box::new(Type::Constant(rhs_a_value, kind)); let new_other = Type::InfixExpr(Box::new(other.clone()), inverse, rhs_a); @@ -266,7 +351,8 @@ impl Type { if let Type::InfixExpr(lhs_b, op_b, rhs_b) = other { if let Some(inverse) = op_b.approx_inverse() { let kind = lhs_b.infix_kind(rhs_b); - if let Some(rhs_b_value) = rhs_b.evaluate_to_field_element(&kind) { + let dummy_span = Span::default(); + if let Ok(rhs_b_value) = rhs_b.evaluate_to_field_element(&kind, dummy_span) { let rhs_b = Box::new(Type::Constant(rhs_b_value, kind)); let new_self = Type::InfixExpr(Box::new(self.clone()), inverse, rhs_b); @@ -282,3 +368,301 @@ impl Type { Err(UnificationError) } } + +#[cfg(test)] +mod tests { + use acvm::{AcirField, FieldElement}; + + use crate::hir_def::types::{BinaryTypeOperator, Kind, Type, TypeVariable, TypeVariableId}; + + #[test] + fn solves_n_minus_one_plus_one_through_checked_casts() { + // We want to test that the inclusion of a `CheckedCast` won't prevent us from canonicalizing + // the expression `(N - 1) + 1` to `N` if there exists a `CheckedCast` on the `N - 1` term. + + let n = Type::NamedGeneric( + TypeVariable::unbound(TypeVariableId(0), Kind::u32()), + std::rc::Rc::new("N".to_owned()), + ); + let n_minus_one = Type::InfixExpr( + Box::new(n.clone()), + BinaryTypeOperator::Subtraction, + Box::new(Type::Constant(FieldElement::one(), Kind::u32())), + ); + let checked_cast_n_minus_one = + Type::CheckedCast { from: Box::new(n_minus_one.clone()), to: Box::new(n_minus_one) }; + + let n_minus_one_plus_one = Type::InfixExpr( + Box::new(checked_cast_n_minus_one.clone()), + BinaryTypeOperator::Addition, + Box::new(Type::Constant(FieldElement::one(), Kind::u32())), + ); + + let canonicalized_typ = n_minus_one_plus_one.canonicalize(); + + assert_eq!(n, canonicalized_typ); + + // We also want to check that if the `CheckedCast` is on the RHS then we'll still be able to canonicalize + // the expression `1 + (N - 1)` to `N`. + + let one_plus_n_minus_one = Type::InfixExpr( + Box::new(Type::Constant(FieldElement::one(), Kind::u32())), + BinaryTypeOperator::Addition, + Box::new(checked_cast_n_minus_one), + ); + + let canonicalized_typ = one_plus_n_minus_one.canonicalize(); + + assert_eq!(n, canonicalized_typ); + } + + #[test] + fn instantiate_after_canonicalize_smoke_test() { + let field_element_kind = Kind::numeric(Type::FieldElement); + let x_var = TypeVariable::unbound(TypeVariableId(0), field_element_kind.clone()); + let x_type = Type::TypeVariable(x_var.clone()); + let one = Type::Constant(FieldElement::one(), field_element_kind.clone()); + + let lhs = Type::InfixExpr( + Box::new(x_type.clone()), + BinaryTypeOperator::Addition, + Box::new(one.clone()), + ); + let rhs = + Type::InfixExpr(Box::new(one), BinaryTypeOperator::Addition, Box::new(x_type.clone())); + + // canonicalize + let lhs = lhs.canonicalize(); + let rhs = rhs.canonicalize(); + + // bind vars + let two = Type::Constant(FieldElement::from(2u128), field_element_kind.clone()); + x_var.bind(two); + + // canonicalize (expect constant) + let lhs = lhs.canonicalize(); + let rhs = rhs.canonicalize(); + + // ensure we've canonicalized to constants + assert!(matches!(lhs, Type::Constant(..))); + assert!(matches!(rhs, Type::Constant(..))); + + // ensure result kinds are the same as the original kind + assert_eq!(lhs.kind(), field_element_kind); + assert_eq!(rhs.kind(), field_element_kind); + + // ensure results are the same + assert_eq!(lhs, rhs); + } +} + +#[cfg(test)] +mod proptests { + + use acvm::{AcirField, FieldElement}; + use proptest::arbitrary::any; + use proptest::collection; + use proptest::prelude::*; + use proptest::result::maybe_ok; + use proptest::strategy; + + use crate::ast::{IntegerBitSize, Signedness}; + use crate::hir_def::types::{BinaryTypeOperator, Kind, Type, TypeVariable, TypeVariableId}; + + prop_compose! { + // maximum_size must be non-zero + fn arbitrary_u128_field_element(maximum_size: u128) + (u128_value in any::()) + -> FieldElement + { + assert!(maximum_size != 0); + FieldElement::from(u128_value % maximum_size) + } + } + + // NOTE: this is roughly the same method from acvm/tests/solver + prop_compose! { + // Use both `u128` and hex proptest strategies + fn arbitrary_field_element() + (u128_or_hex in maybe_ok(any::(), "[0-9a-f]{64}")) + -> FieldElement + { + match u128_or_hex { + Ok(number) => FieldElement::from(number), + Err(hex) => FieldElement::from_hex(&hex).expect("should accept any 32 byte hex string"), + } + } + } + + // Generate (arbitrary_unsigned_type, generator for that type) + fn arbitrary_unsigned_type_with_generator() -> BoxedStrategy<(Type, BoxedStrategy)> + { + prop_oneof![ + strategy::Just((Type::FieldElement, arbitrary_field_element().boxed())), + any::().prop_map(|bit_size| { + let typ = Type::Integer(Signedness::Unsigned, bit_size); + let maximum_size = typ.integral_maximum_size().unwrap().to_u128(); + (typ, arbitrary_u128_field_element(maximum_size).boxed()) + }), + strategy::Just((Type::Bool, arbitrary_u128_field_element(1).boxed())), + ] + .boxed() + } + + prop_compose! { + fn arbitrary_variable(typ: Type, num_variables: usize) + (variable_index in any::()) + -> Type { + assert!(num_variables != 0); + let id = TypeVariableId(variable_index % num_variables); + let kind = Kind::numeric(typ.clone()); + let var = TypeVariable::unbound(id, kind); + Type::TypeVariable(var) + } + } + + fn first_n_variables(typ: Type, num_variables: usize) -> impl Iterator { + (0..num_variables).map(move |id| { + let id = TypeVariableId(id); + let kind = Kind::numeric(typ.clone()); + TypeVariable::unbound(id, kind) + }) + } + + fn arbitrary_infix_expr( + typ: Type, + arbitrary_value: BoxedStrategy, + num_variables: usize, + ) -> impl Strategy { + let leaf = prop_oneof![ + arbitrary_variable(typ.clone(), num_variables), + arbitrary_value + .prop_map(move |value| Type::Constant(value, Kind::numeric(typ.clone()))), + ]; + + leaf.prop_recursive( + 8, // 8 levels deep maximum + 256, // Shoot for maximum size of 256 nodes + 10, // We put up to 10 items per collection + |inner| { + (inner.clone(), any::(), inner) + .prop_map(|(lhs, op, rhs)| Type::InfixExpr(Box::new(lhs), op, Box::new(rhs))) + }, + ) + } + + prop_compose! { + // (infix_expr, type, generator) + fn arbitrary_infix_expr_type_gen(num_variables: usize) + (type_and_gen in arbitrary_unsigned_type_with_generator()) + (infix_expr in arbitrary_infix_expr(type_and_gen.clone().0, type_and_gen.clone().1, num_variables), type_and_gen in Just(type_and_gen)) + -> (Type, Type, BoxedStrategy) { + let (typ, value_generator) = type_and_gen; + (infix_expr, typ, value_generator) + } + } + + prop_compose! { + // (Type::InfixExpr, numeric kind, bindings) + fn arbitrary_infix_expr_with_bindings_sized(num_variables: usize) + (infix_type_gen in arbitrary_infix_expr_type_gen(num_variables)) + (values in collection::vec(infix_type_gen.clone().2, num_variables), infix_type_gen in Just(infix_type_gen)) + -> (Type, Type, Vec<(TypeVariable, Type)>) { + let (infix_expr, typ, _value_generator) = infix_type_gen; + let bindings: Vec<_> = first_n_variables(typ.clone(), num_variables) + .zip(values.iter().map(|value| { + Type::Constant(*value, Kind::numeric(typ.clone())) + })) + .collect(); + (infix_expr, typ, bindings) + } + } + + prop_compose! { + // the lint misfires on 'num_variables' + #[allow(unused_variables)] + fn arbitrary_infix_expr_with_bindings(max_num_variables: usize) + (num_variables in any::().prop_map(move |num_variables| (num_variables % max_num_variables).clamp(1, max_num_variables))) + (infix_type_bindings in arbitrary_infix_expr_with_bindings_sized(num_variables), num_variables in Just(num_variables)) + -> (Type, Type, Vec<(TypeVariable, Type)>) { + infix_type_bindings + } + } + + proptest! { + #[test] + // Expect cases that don't resolve to constants, e.g. see + // `arithmetic_generics_checked_cast_indirect_zeros` + #[should_panic(expected = "matches!(infix, Type :: Constant(..))")] + fn instantiate_before_or_after_canonicalize(infix_type_bindings in arbitrary_infix_expr_with_bindings(10)) { + let (infix, typ, bindings) = infix_type_bindings; + + // canonicalize + let infix_canonicalized = infix.canonicalize(); + + // bind vars + for (var, binding) in bindings { + var.bind(binding); + } + + // attempt to canonicalize to a constant + let infix = infix.canonicalize(); + let infix_canonicalized = infix_canonicalized.canonicalize(); + + // ensure we've canonicalized to constants + prop_assert!(matches!(infix, Type::Constant(..))); + prop_assert!(matches!(infix_canonicalized, Type::Constant(..))); + + // ensure result kinds are the same as the original kind + let kind = Kind::numeric(typ); + prop_assert_eq!(infix.kind(), kind.clone()); + prop_assert_eq!(infix_canonicalized.kind(), kind); + + // ensure results are the same + prop_assert_eq!(infix, infix_canonicalized); + } + + #[test] + fn instantiate_before_or_after_canonicalize_checked_cast(infix_type_bindings in arbitrary_infix_expr_with_bindings(10)) { + let (infix, typ, bindings) = infix_type_bindings; + + // wrap in CheckedCast + let infix = Type::CheckedCast { + from: Box::new(infix.clone()), + to: Box::new(infix) + }; + + // canonicalize + let infix_canonicalized = infix.canonicalize(); + + // bind vars + for (var, binding) in bindings { + var.bind(binding); + } + + // attempt to canonicalize to a constant + let infix = infix.canonicalize(); + let infix_canonicalized = infix_canonicalized.canonicalize(); + + // ensure result kinds are the same as the original kind + let kind = Kind::numeric(typ); + prop_assert_eq!(infix.kind(), kind.clone()); + prop_assert_eq!(infix_canonicalized.kind(), kind.clone()); + + // ensure the results are still wrapped in CheckedCast's + match (&infix, &infix_canonicalized) { + (Type::CheckedCast { from, to }, Type::CheckedCast { from: from_canonicalized, to: to_canonicalized }) => { + // ensure from's are the same + prop_assert_eq!(from, from_canonicalized); + + // ensure to's have the same kinds + prop_assert_eq!(to.kind(), kind.clone()); + prop_assert_eq!(to_canonicalized.kind(), kind); + } + _ => { + prop_assert!(false, "expected CheckedCast"); + } + } + } + } +} 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 91ae544ddf0..68dc142ff10 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs @@ -1,4 +1,4 @@ -use crate::token::{Attribute, DocStyle}; +use crate::token::DocStyle; use super::{ errors::LexerErrorKind, @@ -139,7 +139,7 @@ impl<'a> Lexer<'a> { Some('f') => self.eat_format_string_or_alpha_numeric(), Some('r') => self.eat_raw_string_or_alpha_numeric(), Some('q') => self.eat_quote_or_alpha_numeric(), - Some('#') => self.eat_attribute(), + Some('#') => self.eat_attribute_start(), Some(ch) if ch.is_ascii_alphanumeric() || ch == '_' => self.eat_alpha_numeric(ch), Some(ch) => { // We don't report invalid tokens in the source as errors until parsing to @@ -282,7 +282,7 @@ impl<'a> Lexer<'a> { } } - fn eat_attribute(&mut self) -> SpannedTokenResult { + fn eat_attribute_start(&mut self) -> SpannedTokenResult { let start = self.position; let is_inner = if self.peek_char_is('!') { @@ -306,40 +306,9 @@ impl<'a> Lexer<'a> { self.next_char(); } - let contents_start = self.position + 1; - - let word = self.eat_while(None, |ch| ch != ']'); - - let contents_end = self.position; - - if !self.peek_char_is(']') { - return Err(LexerErrorKind::UnexpectedCharacter { - span: Span::single_char(self.position), - expected: "]".to_owned(), - found: self.next_char(), - }); - } - self.next_char(); - let end = self.position; - let span = Span::inclusive(start, end); - let contents_span = Span::inclusive(contents_start, contents_end); - - let attribute = Attribute::lookup_attribute(&word, span, contents_span, is_tag)?; - if is_inner { - match attribute { - Attribute::Function(attribute) => Err(LexerErrorKind::InvalidInnerAttribute { - span: Span::from(start..end), - found: attribute.to_string(), - }), - Attribute::Secondary(attribute) => { - Ok(Token::InnerAttribute(attribute).into_span(start, end)) - } - } - } else { - Ok(Token::Attribute(attribute).into_span(start, end)) - } + Ok(Token::AttributeStart { is_inner, is_tag }.into_span(start, end)) } //XXX(low): Can increase performance if we use iterator semantic and utilize some of the methods on String. See below @@ -371,11 +340,11 @@ impl<'a> Lexer<'a> { // Check if word an int type // if no error occurred, then it is either a valid integer type or it is not an int type - let parsed_token = IntType::lookup_int_type(&word)?; + let parsed_token = IntType::lookup_int_type(&word); // Check if it is an int type - if let Some(int_type_token) = parsed_token { - return Ok(int_type_token.into_span(start, end)); + if let Some(int_type) = parsed_token { + return Ok(Token::IntType(int_type).into_span(start, end)); } // Else it is just an identifier @@ -725,7 +694,6 @@ mod tests { use iter_extended::vecmap; use super::*; - use crate::token::{CustomAttribute, FunctionAttribute, SecondaryAttribute, TestScope}; #[test] fn test_single_multi_char() { @@ -785,173 +753,39 @@ mod tests { } #[test] - fn deprecated_attribute() { - let input = r#"#[deprecated]"#; - let mut lexer = Lexer::new(input); - - let token = lexer.next_token().unwrap(); - assert_eq!( - token.token(), - &Token::Attribute(Attribute::Secondary(SecondaryAttribute::Deprecated(None))) - ); - } - - #[test] - fn test_attribute_with_common_punctuation() { - let input = - r#"#[test(should_fail_with = "stmt. q? exclaim! & symbols, 1% shouldn't fail")]"#; - let mut lexer = Lexer::new(input); - - let token = lexer.next_token().unwrap().token().clone(); - assert_eq!( - token, - Token::Attribute(Attribute::Function(FunctionAttribute::Test( - TestScope::ShouldFailWith { - reason: "stmt. q? exclaim! & symbols, 1% shouldn't fail".to_owned().into() - } - ))) - ); - } - - #[test] - fn deprecated_attribute_with_note() { - let input = r#"#[deprecated("hello")]"#; - let mut lexer = Lexer::new(input); - - let token = lexer.next_token().unwrap(); - assert_eq!( - token.token(), - &Token::Attribute(Attribute::Secondary(crate::token::SecondaryAttribute::Deprecated( - "hello".to_string().into() - ))) - ); - } - - #[test] - fn test_custom_gate_syntax() { - let input = "#[foreign(sha256)]#[foreign(blake2s)]#[builtin(sum)]"; - - let expected = vec![ - Token::Attribute(Attribute::Function(FunctionAttribute::Foreign("sha256".to_string()))), - Token::Attribute(Attribute::Function(FunctionAttribute::Foreign( - "blake2s".to_string(), - ))), - Token::Attribute(Attribute::Function(FunctionAttribute::Builtin("sum".to_string()))), - ]; - - let mut lexer = Lexer::new(input); - for token in expected.into_iter() { - let got = lexer.next_token().unwrap(); - assert_eq!(got, token); - } - } - - #[test] - fn tag_attribute() { - let input = r#"#['custom(hello)]"#; + fn test_attribute_start() { + let input = r#"#[something]"#; let mut lexer = Lexer::new(input); let token = lexer.next_token().unwrap(); - assert_eq!( - token.token(), - &Token::Attribute(Attribute::Secondary(SecondaryAttribute::Tag(CustomAttribute { - contents: "custom(hello)".to_string(), - span: Span::from(0..17), - contents_span: Span::from(3..16) - }))) - ); + assert_eq!(token.token(), &Token::AttributeStart { is_inner: false, is_tag: false }); } #[test] - fn test_attribute() { - let input = r#"#[test]"#; + fn test_attribute_start_with_tag() { + let input = r#"#['something]"#; let mut lexer = Lexer::new(input); let token = lexer.next_token().unwrap(); - assert_eq!( - token.token(), - &Token::Attribute(Attribute::Function(FunctionAttribute::Test(TestScope::None))) - ); + assert_eq!(token.token(), &Token::AttributeStart { is_inner: false, is_tag: true }); } #[test] - fn fold_attribute() { - let input = r#"#[fold]"#; - - let mut lexer = Lexer::new(input); - let token = lexer.next_token().unwrap(); - - assert_eq!(token.token(), &Token::Attribute(Attribute::Function(FunctionAttribute::Fold))); - } - - #[test] - fn contract_library_method_attribute() { - let input = r#"#[contract_library_method]"#; - let mut lexer = Lexer::new(input); - - let token = lexer.next_token().unwrap(); - assert_eq!( - token.token(), - &Token::Attribute(Attribute::Secondary(SecondaryAttribute::ContractLibraryMethod)) - ); - } - - #[test] - fn test_attribute_with_valid_scope() { - let input = r#"#[test(should_fail)]"#; - let mut lexer = Lexer::new(input); - - let token = lexer.next_token().unwrap(); - assert_eq!( - token.token(), - &Token::Attribute(Attribute::Function(FunctionAttribute::Test( - TestScope::ShouldFailWith { reason: None } - ))) - ); - } - - #[test] - fn test_attribute_with_valid_scope_should_fail_with() { - let input = r#"#[test(should_fail_with = "hello")]"#; + fn test_inner_attribute_start() { + let input = r#"#![something]"#; let mut lexer = Lexer::new(input); let token = lexer.next_token().unwrap(); - assert_eq!( - token.token(), - &Token::Attribute(Attribute::Function(FunctionAttribute::Test( - TestScope::ShouldFailWith { reason: Some("hello".to_owned()) } - ))) - ); + assert_eq!(token.token(), &Token::AttributeStart { is_inner: true, is_tag: false }); } #[test] - fn test_attribute_with_invalid_scope() { - let input = r#"#[test(invalid_scope)]"#; - let mut lexer = Lexer::new(input); - - let token = lexer.next().unwrap(); - let err = match token { - Ok(_) => panic!("test has an invalid scope, so expected an error"), - Err(err) => err, - }; - - assert!(matches!(err, LexerErrorKind::MalformedTestAttribute { .. })); - } - - #[test] - fn test_inner_attribute() { - let input = r#"#![something]"#; + fn test_inner_attribute_start_with_tag() { + let input = r#"#!['something]"#; let mut lexer = Lexer::new(input); let token = lexer.next_token().unwrap(); - assert_eq!( - token.token(), - &Token::InnerAttribute(SecondaryAttribute::Meta(CustomAttribute { - contents: "something".to_string(), - span: Span::from(0..13), - contents_span: Span::from(3..12), - })) - ); + assert_eq!(token.token(), &Token::AttributeStart { is_inner: true, is_tag: true }); } #[test] 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 11001d27768..dbb28cf78c0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs @@ -1,9 +1,9 @@ use acvm::FieldElement; use noirc_errors::{Position, Span, Spanned}; -use std::fmt; +use std::fmt::{self, Display}; use crate::{ - lexer::errors::LexerErrorKind, + ast::{Expression, Path}, node_interner::{ ExprId, InternedExpressionKind, InternedPattern, InternedStatementKind, InternedUnresolvedTypeData, QuotedTypeId, @@ -28,8 +28,10 @@ pub enum BorrowedToken<'input> { FmtStr(&'input str), Keyword(Keyword), IntType(IntType), - Attribute(Attribute), - InnerAttribute(SecondaryAttribute), + AttributeStart { + is_inner: bool, + is_tag: bool, + }, LineComment(&'input str, Option), BlockComment(&'input str, Option), Quote(&'input Tokens), @@ -137,8 +139,10 @@ pub enum Token { FmtStr(String), Keyword(Keyword), IntType(IntType), - Attribute(Attribute), - InnerAttribute(SecondaryAttribute), + AttributeStart { + is_inner: bool, + is_tag: bool, + }, LineComment(String, Option), BlockComment(String, Option), // A `quote { ... }` along with the tokens in its token stream. @@ -254,8 +258,9 @@ pub fn token_to_borrowed_token(token: &Token) -> BorrowedToken<'_> { Token::FmtStr(ref b) => BorrowedToken::FmtStr(b), Token::RawStr(ref b, hashes) => BorrowedToken::RawStr(b, *hashes), Token::Keyword(k) => BorrowedToken::Keyword(*k), - Token::Attribute(ref a) => BorrowedToken::Attribute(a.clone()), - Token::InnerAttribute(ref a) => BorrowedToken::InnerAttribute(a.clone()), + Token::AttributeStart { is_inner, is_tag } => { + BorrowedToken::AttributeStart { is_inner: *is_inner, is_tag: *is_tag } + } Token::LineComment(ref s, _style) => BorrowedToken::LineComment(s, *_style), Token::BlockComment(ref s, _style) => BorrowedToken::BlockComment(s, *_style), Token::Quote(stream) => BorrowedToken::Quote(stream), @@ -376,8 +381,17 @@ impl fmt::Display for Token { write!(f, "r{h}{b:?}{h}") } Token::Keyword(k) => write!(f, "{k}"), - Token::Attribute(ref a) => write!(f, "{a}"), - Token::InnerAttribute(ref a) => write!(f, "#![{}]", a.contents()), + Token::AttributeStart { is_inner, is_tag } => { + write!(f, "#")?; + if is_inner { + write!(f, "!")?; + } + write!(f, "[")?; + if is_tag { + write!(f, "'")?; + } + Ok(()) + } Token::LineComment(ref s, style) => match style { Some(DocStyle::Inner) => write!(f, "//!{s}"), Some(DocStyle::Outer) => write!(f, "///{s}"), @@ -503,8 +517,6 @@ impl Token { | Token::RawStr(..) | Token::FmtStr(_) => TokenKind::Literal, Token::Keyword(_) => TokenKind::Keyword, - Token::Attribute(_) => TokenKind::Attribute, - Token::InnerAttribute(_) => TokenKind::InnerAttribute, Token::UnquoteMarker(_) => TokenKind::UnquoteMarker, Token::Quote(_) => TokenKind::Quote, Token::QuotedType(_) => TokenKind::QuotedType, @@ -585,7 +597,7 @@ impl IntType { // XXX: Result // Is not the best API. We could split this into two functions. One that checks if the // word is a integer, which only returns an Option - pub(crate) fn lookup_int_type(word: &str) -> Result, LexerErrorKind> { + pub fn lookup_int_type(word: &str) -> Option { // Check if the first string is a 'u' or 'i' let is_signed = if word.starts_with('i') { @@ -593,20 +605,20 @@ impl IntType { } else if word.starts_with('u') { false } else { - return Ok(None); + return None; }; // Word start with 'u' or 'i'. Check if the latter is an integer let str_as_u32 = match word[1..].parse::() { Ok(str_as_u32) => str_as_u32, - Err(_) => return Ok(None), + Err(_) => return None, }; if is_signed { - Ok(Some(Token::IntType(IntType::Signed(str_as_u32)))) + Some(IntType::Signed(str_as_u32)) } else { - Ok(Some(Token::IntType(IntType::Unsigned(str_as_u32)))) + Some(IntType::Unsigned(str_as_u32)) } } } @@ -622,25 +634,6 @@ pub enum TestScope { None, } -impl TestScope { - fn lookup_str(string: &str) -> Option { - match string.trim() { - "should_fail" => Some(TestScope::ShouldFailWith { reason: None }), - s if s.starts_with("should_fail_with") => { - let parts: Vec<&str> = s.splitn(2, '=').collect(); - if parts.len() == 2 { - let reason = parts[1].trim(); - let reason = reason.trim_matches('"'); - Some(TestScope::ShouldFailWith { reason: Some(reason.to_string()) }) - } else { - None - } - } - _ => None, - } - } -} - impl fmt::Display for TestScope { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -653,13 +646,13 @@ impl fmt::Display for TestScope { } } -#[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] +#[derive(PartialEq, Eq, Debug, Clone)] // Attributes are special language markers in the target language // An example of one is `#[SHA256]` . Currently only Foreign attributes are supported // Calls to functions which have the foreign attribute are executed in the host language pub struct Attributes { // Each function can have a single Primary Attribute - pub function: Option, + pub function: Option<(FunctionAttribute, usize /* index in list */)>, // Each function can have many Secondary Attributes pub secondary: Vec, } @@ -669,6 +662,15 @@ impl Attributes { Self { function: None, secondary: Vec::new() } } + pub fn function(&self) -> Option<&FunctionAttribute> { + self.function.as_ref().map(|(attr, _)| attr) + } + + pub fn set_function(&mut self, function: FunctionAttribute) { + // Assume the index in the list doesn't matter anymore at this point + self.function = Some((function, 0)); + } + /// Returns true if one of the secondary attributes is `contract_library_method` /// /// This is useful for finding out if we should compile a contract method @@ -680,7 +682,7 @@ impl Attributes { } pub fn is_test_function(&self) -> bool { - matches!(self.function, Some(FunctionAttribute::Test(_))) + matches!(self.function(), Some(FunctionAttribute::Test(_))) } /// True if these attributes mean the given function is an entry point function if it was @@ -708,11 +710,11 @@ impl Attributes { } pub fn is_foldable(&self) -> bool { - self.function.as_ref().map_or(false, |func_attribute| func_attribute.is_foldable()) + self.function().map_or(false, |func_attribute| func_attribute.is_foldable()) } pub fn is_no_predicates(&self) -> bool { - self.function.as_ref().map_or(false, |func_attribute| func_attribute.is_no_predicates()) + self.function().map_or(false, |func_attribute| func_attribute.is_no_predicates()) } pub fn has_varargs(&self) -> bool { @@ -727,7 +729,7 @@ impl Attributes { /// An Attribute can be either a Primary Attribute or a Secondary Attribute /// A Primary Attribute can alter the function type, thus there can only be one /// A secondary attribute has no effect and is either consumed by a library or used as a notice for the developer -#[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] +#[derive(PartialEq, Eq, Debug, Clone)] pub enum Attribute { Function(FunctionAttribute), Secondary(SecondaryAttribute), @@ -742,115 +744,6 @@ impl fmt::Display for Attribute { } } -impl Attribute { - /// If the string is a fixed attribute return that, else - /// return the custom attribute - pub(crate) fn lookup_attribute( - word: &str, - span: Span, - contents_span: Span, - is_tag: bool, - ) -> Result { - // See if we can parse the word into "name ( contents )". - // We first split into "first_segment ( rest". - let word_segments = if let Some((first_segment, rest)) = word.trim().split_once('(') { - // Now we try to remove the final ")" (it must be at the end, if it exists) - if let Some(middle) = rest.strip_suffix(')') { - vec![first_segment.trim(), middle.trim()] - } else { - vec![word] - } - } else { - vec![word] - }; - - let validate = |slice: &str| { - let is_valid = slice - .chars() - .all(|ch| { - ch.is_ascii_alphabetic() - || ch.is_numeric() - || ch.is_ascii_punctuation() - || ch == ' ' - }) - .then_some(()); - - is_valid.ok_or(LexerErrorKind::MalformedFuncAttribute { span, found: word.to_owned() }) - }; - - if is_tag { - return Ok(Attribute::Secondary(SecondaryAttribute::Tag(CustomAttribute { - contents: word.to_owned(), - span, - contents_span, - }))); - } - - let attribute = match &word_segments[..] { - // Primary Attributes - ["foreign", name] => { - validate(name)?; - Attribute::Function(FunctionAttribute::Foreign(name.to_string())) - } - ["builtin", name] => { - validate(name)?; - Attribute::Function(FunctionAttribute::Builtin(name.to_string())) - } - ["oracle", name] => { - validate(name)?; - Attribute::Function(FunctionAttribute::Oracle(name.to_string())) - } - ["test"] => Attribute::Function(FunctionAttribute::Test(TestScope::None)), - ["fold"] => Attribute::Function(FunctionAttribute::Fold), - ["no_predicates"] => Attribute::Function(FunctionAttribute::NoPredicates), - ["inline_always"] => Attribute::Function(FunctionAttribute::InlineAlways), - ["test", name] => { - validate(name)?; - match TestScope::lookup_str(name) { - Some(scope) => Attribute::Function(FunctionAttribute::Test(scope)), - None => return Err(LexerErrorKind::MalformedTestAttribute { span }), - } - } - ["field", name] => { - validate(name)?; - Attribute::Secondary(SecondaryAttribute::Field(name.to_string())) - } - // Secondary attributes - ["deprecated"] => Attribute::Secondary(SecondaryAttribute::Deprecated(None)), - ["contract_library_method"] => { - Attribute::Secondary(SecondaryAttribute::ContractLibraryMethod) - } - ["abi", tag] => Attribute::Secondary(SecondaryAttribute::Abi(tag.to_string())), - ["export"] => Attribute::Secondary(SecondaryAttribute::Export), - ["deprecated", name] => { - if !name.starts_with('"') && !name.ends_with('"') { - return Err(LexerErrorKind::MalformedFuncAttribute { - span, - found: word.to_owned(), - }); - } - - Attribute::Secondary(SecondaryAttribute::Deprecated( - name.trim_matches('"').to_string().into(), - )) - } - ["varargs"] => Attribute::Secondary(SecondaryAttribute::Varargs), - ["use_callers_scope"] => Attribute::Secondary(SecondaryAttribute::UseCallersScope), - ["allow", tag] => Attribute::Secondary(SecondaryAttribute::Allow(tag.to_string())), - tokens => { - tokens.iter().try_for_each(|token| validate(token))?; - Attribute::Secondary(SecondaryAttribute::Meta(CustomAttribute { - contents: word.to_owned(), - span, - contents_span, - })) - } - }; - - Ok(attribute) - } -} - /// Primary Attributes are those which a function can only have one of. /// They change the FunctionKind and thus have direct impact on the IR output #[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] @@ -946,7 +839,7 @@ impl fmt::Display for FunctionAttribute { /// Secondary attributes are those which a function can have many of. /// They are not able to change the `FunctionKind` and thus do not have direct impact on the IR output /// They are often consumed by libraries or used as notices for the developer -#[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] +#[derive(PartialEq, Eq, Debug, Clone)] pub enum SecondaryAttribute { Deprecated(Option), // This is an attribute to specify that a function @@ -960,7 +853,7 @@ pub enum SecondaryAttribute { Tag(CustomAttribute), /// An attribute expected to run a comptime function of the same name: #[foo] - Meta(CustomAttribute), + Meta(MetaAttribute), Abi(String), @@ -977,14 +870,6 @@ pub enum SecondaryAttribute { } impl SecondaryAttribute { - pub(crate) fn as_custom(&self) -> Option<&CustomAttribute> { - if let Self::Tag(attribute) = self { - Some(attribute) - } else { - None - } - } - pub(crate) fn name(&self) -> Option { match self { SecondaryAttribute::Deprecated(_) => Some("deprecated".to_string()), @@ -994,7 +879,7 @@ impl SecondaryAttribute { SecondaryAttribute::Export => Some("export".to_string()), SecondaryAttribute::Field(_) => Some("field".to_string()), SecondaryAttribute::Tag(custom) => custom.name(), - SecondaryAttribute::Meta(custom) => custom.name(), + SecondaryAttribute::Meta(meta) => Some(meta.name.last_name().to_string()), SecondaryAttribute::Abi(_) => Some("abi".to_string()), SecondaryAttribute::Varargs => Some("varargs".to_string()), SecondaryAttribute::UseCallersScope => Some("use_callers_scope".to_string()), @@ -1020,7 +905,7 @@ impl SecondaryAttribute { format!("deprecated({note:?})") } SecondaryAttribute::Tag(ref attribute) => format!("'{}", attribute.contents), - SecondaryAttribute::Meta(ref attribute) => attribute.contents.to_string(), + SecondaryAttribute::Meta(ref meta) => meta.to_string(), SecondaryAttribute::ContractLibraryMethod => "contract_library_method".to_string(), SecondaryAttribute::Export => "export".to_string(), SecondaryAttribute::Field(ref k) => format!("field({k})"), @@ -1038,6 +923,25 @@ impl fmt::Display for SecondaryAttribute { } } +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct MetaAttribute { + pub name: Path, + pub arguments: Vec, + pub span: Span, +} + +impl Display for MetaAttribute { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.arguments.is_empty() { + write!(f, "{}", self.name) + } else { + let args = + self.arguments.iter().map(ToString::to_string).collect::>().join(", "); + write!(f, "{}({})", self.name, args) + } + } +} + #[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] pub struct CustomAttribute { pub contents: String, @@ -1059,38 +963,6 @@ impl CustomAttribute { } } -impl AsRef for FunctionAttribute { - fn as_ref(&self) -> &str { - match self { - FunctionAttribute::Foreign(string) => string, - FunctionAttribute::Builtin(string) => string, - FunctionAttribute::Oracle(string) => string, - FunctionAttribute::Test { .. } => "", - FunctionAttribute::Fold => "", - FunctionAttribute::NoPredicates => "", - FunctionAttribute::InlineAlways => "", - } - } -} - -impl AsRef for SecondaryAttribute { - fn as_ref(&self) -> &str { - match self { - SecondaryAttribute::Deprecated(Some(string)) => string, - SecondaryAttribute::Deprecated(None) => "", - SecondaryAttribute::Tag(attribute) => &attribute.contents, - SecondaryAttribute::Meta(attribute) => &attribute.contents, - SecondaryAttribute::Field(string) - | SecondaryAttribute::Abi(string) - | SecondaryAttribute::Allow(string) => string, - SecondaryAttribute::ContractLibraryMethod => "", - SecondaryAttribute::Export => "", - SecondaryAttribute::Varargs => "", - SecondaryAttribute::UseCallersScope => "", - } - } -} - /// Note that `self` is not present - it is a contextual keyword rather than a true one as it is /// only special within `impl`s. Otherwise `self` functions as a normal identifier. #[derive(PartialEq, Eq, Hash, Debug, Copy, Clone, PartialOrd, Ord, strum_macros::EnumIter)] diff --git a/noir/noir-repo/compiler/noirc_frontend/src/locations.rs b/noir/noir-repo/compiler/noirc_frontend/src/locations.rs index 4dd699251a6..ecae5b19a95 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/locations.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/locations.rs @@ -1,14 +1,11 @@ use fm::FileId; -use noirc_errors::Location; +use noirc_errors::{Location, Span}; use rangemap::RangeMap; use rustc_hash::FxHashMap as HashMap; use crate::{ ast::{FunctionDefinition, ItemVisibility}, - hir::{ - def_map::{ModuleDefId, ModuleId}, - resolution::import::PathResolutionItem, - }, + hir::def_map::{ModuleDefId, ModuleId}, node_interner::{ DefinitionId, FuncId, GlobalId, NodeInterner, ReferenceId, StructId, TraitId, TypeAliasId, }, @@ -37,6 +34,27 @@ impl LocationIndices { } } +pub struct ReferencesTracker<'a> { + interner: &'a mut NodeInterner, + file_id: FileId, +} + +impl<'a> ReferencesTracker<'a> { + pub fn new(interner: &'a mut NodeInterner, file_id: FileId) -> Self { + Self { interner, file_id } + } + + pub(crate) fn add_reference( + &mut self, + module_def_id: ModuleDefId, + span: Span, + is_self_type: bool, + ) { + let location = Location::new(span, self.file_id); + self.interner.add_module_def_id_reference(module_def_id, location, is_self_type); + } +} + impl NodeInterner { pub fn reference_location(&self, reference: ReferenceId) -> Location { match reference { @@ -102,37 +120,6 @@ impl NodeInterner { }; } - pub(crate) fn add_path_resolution_kind_reference( - &mut self, - kind: PathResolutionItem, - location: Location, - is_self_type: bool, - ) { - match kind { - PathResolutionItem::Module(module_id) => { - self.add_module_reference(module_id, location); - } - PathResolutionItem::Struct(struct_id) => { - self.add_struct_reference(struct_id, location, is_self_type); - } - PathResolutionItem::TypeAlias(type_alias_id) => { - self.add_alias_reference(type_alias_id, location); - } - PathResolutionItem::Trait(trait_id) => { - self.add_trait_reference(trait_id, location, is_self_type); - } - PathResolutionItem::Global(global_id) => { - self.add_global_reference(global_id, location); - } - PathResolutionItem::ModuleFunction(func_id) - | PathResolutionItem::StructFunction(_, _, func_id) - | PathResolutionItem::TypeAliasFunction(_, _, func_id) - | PathResolutionItem::TraitFunction(_, _, func_id) => { - self.add_function_reference(func_id, location); - } - } - } - pub(crate) fn add_module_reference(&mut self, id: ModuleId, location: Location) { self.add_reference(ReferenceId::Module(id), location, false); } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs index 7c7f87b7b8b..8f6817dc15d 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs @@ -237,13 +237,11 @@ pub enum InlineType { impl From<&Attributes> for InlineType { fn from(attributes: &Attributes) -> Self { - attributes.function.as_ref().map_or(InlineType::default(), |func_attribute| { - match func_attribute { - FunctionAttribute::Fold => InlineType::Fold, - FunctionAttribute::NoPredicates => InlineType::NoPredicates, - FunctionAttribute::InlineAlways => InlineType::InlineAlways, - _ => InlineType::default(), - } + attributes.function().map_or(InlineType::default(), |func_attribute| match func_attribute { + FunctionAttribute::Fold => InlineType::Fold, + FunctionAttribute::NoPredicates => InlineType::NoPredicates, + FunctionAttribute::InlineAlways => InlineType::InlineAlways, + _ => InlineType::default(), }) } } 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 e2ff94f521b..c137a6fc90a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/errors.rs @@ -1,10 +1,13 @@ use noirc_errors::{CustomDiagnostic, FileDiagnostic, Location}; -use crate::{hir::comptime::InterpreterError, Type}; +use crate::{ + hir::{comptime::InterpreterError, type_check::TypeCheckError}, + Type, +}; #[derive(Debug)] pub enum MonomorphizationError { - UnknownArrayLength { length: Type, location: Location }, + UnknownArrayLength { length: Type, err: TypeCheckError, location: Location }, UnknownConstant { location: Location }, NoDefaultType { location: Location }, InternalError { message: &'static str, location: Location }, @@ -12,6 +15,7 @@ pub enum MonomorphizationError { ComptimeFnInRuntimeCode { name: String, location: Location }, ComptimeTypeInRuntimeCode { typ: String, location: Location }, CheckedTransmuteFailed { actual: Type, expected: Type, location: Location }, + CheckedCastFailed { actual: Type, expected: Type, location: Location }, } impl MonomorphizationError { @@ -23,6 +27,7 @@ impl MonomorphizationError { | MonomorphizationError::ComptimeFnInRuntimeCode { location, .. } | MonomorphizationError::ComptimeTypeInRuntimeCode { location, .. } | MonomorphizationError::CheckedTransmuteFailed { location, .. } + | MonomorphizationError::CheckedCastFailed { location, .. } | MonomorphizationError::NoDefaultType { location, .. } => *location, MonomorphizationError::InterpreterError(error) => error.get_location(), } @@ -41,14 +46,17 @@ impl From for FileDiagnostic { impl MonomorphizationError { fn into_diagnostic(self) -> CustomDiagnostic { let message = match &self { - MonomorphizationError::UnknownArrayLength { length, .. } => { - format!("Could not determine array length `{length}`") + MonomorphizationError::UnknownArrayLength { length, err, .. } => { + format!("Could not determine array length `{length}`, encountered error: `{err}`") } MonomorphizationError::UnknownConstant { .. } => { "Could not resolve constant".to_string() } MonomorphizationError::CheckedTransmuteFailed { actual, expected, .. } => { - format!("checked_transmute failed: `{actual}` != `{expected}`") + format!("checked_transmute failed: `{actual:?}` != `{expected:?}`") + } + MonomorphizationError::CheckedCastFailed { actual, expected, .. } => { + format!("Arithmetic generics simplification failed: `{actual:?}` != `{expected:?}`") } MonomorphizationError::NoDefaultType { location } => { let message = "Type annotation needed".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 21a2d533354..0ec26a5ca83 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -10,7 +10,7 @@ //! function, will monomorphize the entire reachable program. use crate::ast::{FunctionKind, IntegerBitSize, Signedness, UnaryOp, Visibility}; use crate::hir::comptime::InterpreterError; -use crate::hir::type_check::NoMatchingImplFoundError; +use crate::hir::type_check::{NoMatchingImplFoundError, TypeCheckError}; use crate::node_interner::{ExprId, ImplSearchErrorKind}; use crate::{ debug::DebugInstrumenter, @@ -221,14 +221,14 @@ impl<'interner> Monomorphizer<'interner> { let attributes = self.interner.function_attributes(&id); match self.interner.function_meta(&id).kind { FunctionKind::LowLevel => { - let attribute = attributes.function.as_ref().expect("all low level functions must contain a function attribute which contains the opcode which it links to"); + let attribute = attributes.function().expect("all low level functions must contain a function attribute which contains the opcode which it links to"); let opcode = attribute.foreign().expect( "ice: function marked as foreign, but attribute kind does not match this", ); Definition::LowLevel(opcode.to_string()) } FunctionKind::Builtin => { - let attribute = attributes.function.as_ref().expect("all builtin functions must contain a function attribute which contains the opcode which it links to"); + let attribute = attributes.function().expect("all builtin functions must contain a function attribute which contains the opcode which it links to"); let opcode = attribute.builtin().expect( "ice: function marked as builtin, but attribute kind does not match this", ); @@ -240,7 +240,7 @@ impl<'interner> Monomorphizer<'interner> { Definition::Function(id) } FunctionKind::Oracle => { - let attribute = attributes.function.as_ref().expect("all oracle functions must contain a function attribute which contains the opcode which it links to"); + let attribute = attributes.function().expect("all oracle functions must contain a function attribute which contains the opcode which it links to"); let opcode = attribute.oracle().expect( "ice: function marked as builtin, but attribute kind does not match this", ); @@ -570,9 +570,9 @@ impl<'interner> Monomorphizer<'interner> { let location = self.interner.expr_location(&array); let typ = Self::convert_type(&self.interner.id_type(array), location)?; - let length = length.evaluate_to_u32().ok_or_else(|| { + let length = length.evaluate_to_u32(location.span).map_err(|err| { let location = self.interner.expr_location(&array); - MonomorphizationError::UnknownArrayLength { location, length } + MonomorphizationError::UnknownArrayLength { location, err, length } })?; let contents = try_vecmap(0..length, |_| self.expr(repeated_element))?; @@ -922,17 +922,23 @@ impl<'interner> Monomorphizer<'interner> { TypeBinding::Unbound(_, _) => { unreachable!("Unbound type variable used in expression") } - TypeBinding::Bound(binding) => binding - .evaluate_to_field_element(&Kind::Numeric(numeric_typ.clone())) - .unwrap_or_else(|| { - panic!("Non-numeric type variable used in expression expecting a value") - }), + TypeBinding::Bound(binding) => { + let location = self.interner.id_location(expr_id); + binding + .evaluate_to_field_element( + &Kind::Numeric(numeric_typ.clone()), + location.span, + ) + .map_err(|err| MonomorphizationError::UnknownArrayLength { + length: binding.clone(), + err, + location, + })? + } }; let location = self.interner.id_location(expr_id); - if !Kind::Numeric(numeric_typ.clone()) - .unifies(&Kind::Numeric(Box::new(typ.clone()))) - { + if !Kind::Numeric(numeric_typ.clone()).unifies(&Kind::numeric(typ.clone())) { let message = "ICE: Generic's kind does not match expected type"; return Err(MonomorphizationError::InternalError { location, message }); } @@ -951,20 +957,51 @@ impl<'interner> Monomorphizer<'interner> { HirType::FieldElement => ast::Type::Field, HirType::Integer(sign, bits) => ast::Type::Integer(*sign, *bits), HirType::Bool => ast::Type::Bool, - HirType::String(size) => ast::Type::String(size.evaluate_to_u32().unwrap_or(0)), + HirType::String(size) => { + let size = match size.evaluate_to_u32(location.span) { + Ok(size) => size, + // only default variable sizes to size 0 + Err(TypeCheckError::NonConstantEvaluated { .. }) => 0, + Err(err) => { + let length = size.as_ref().clone(); + return Err(MonomorphizationError::UnknownArrayLength { + location, + err, + length, + }); + } + }; + ast::Type::String(size) + } HirType::FmtString(size, fields) => { - let size = size.evaluate_to_u32().unwrap_or(0); + let size = match size.evaluate_to_u32(location.span) { + Ok(size) => size, + // only default variable sizes to size 0 + Err(TypeCheckError::NonConstantEvaluated { .. }) => 0, + Err(err) => { + let length = size.as_ref().clone(); + return Err(MonomorphizationError::UnknownArrayLength { + location, + err, + length, + }); + } + }; let fields = Box::new(Self::convert_type(fields.as_ref(), location)?); ast::Type::FmtString(size, fields) } HirType::Unit => ast::Type::Unit, HirType::Array(length, element) => { let element = Box::new(Self::convert_type(element.as_ref(), location)?); - let length = match length.evaluate_to_u32() { - Some(length) => length, - None => { + let length = match length.evaluate_to_u32(location.span) { + Ok(length) => length, + Err(err) => { let length = length.as_ref().clone(); - return Err(MonomorphizationError::UnknownArrayLength { location, length }); + return Err(MonomorphizationError::UnknownArrayLength { + location, + err, + length, + }); } }; ast::Type::Array(length, element) @@ -988,6 +1025,11 @@ impl<'interner> Monomorphizer<'interner> { ast::Type::Field } + HirType::CheckedCast { from, to } => { + Self::check_checked_cast(from, to, location)?; + Self::convert_type(to, location)? + } + HirType::TypeVariable(ref binding) => { let type_var_kind = match &*binding.borrow() { TypeBinding::Bound(ref binding) => { @@ -1094,6 +1136,11 @@ impl<'interner> Monomorphizer<'interner> { Ok(()) } } + HirType::CheckedCast { from, to } => { + Self::check_checked_cast(from, to, location)?; + Self::check_type(to, location) + } + 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), @@ -1165,6 +1212,40 @@ impl<'interner> Monomorphizer<'interner> { } } + /// Check that the 'from' and to' sides of a CheckedCast unify and + /// that if the 'to' side evaluates to a field element, that the 'from' side + /// evaluates to the same field element + fn check_checked_cast( + from: &Type, + to: &Type, + location: Location, + ) -> Result<(), MonomorphizationError> { + if from.unify(to).is_err() { + return Err(MonomorphizationError::CheckedCastFailed { + actual: to.clone(), + expected: from.clone(), + location, + }); + } + let to_value = to.evaluate_to_field_element(&to.kind(), location.span); + if to_value.is_ok() { + let skip_simplifications = false; + let from_value = from.evaluate_to_field_element_helper( + &to.kind(), + location.span, + skip_simplifications, + ); + if from_value.is_err() || from_value.unwrap() != to_value.clone().unwrap() { + return Err(MonomorphizationError::CheckedCastFailed { + actual: HirType::Constant(to_value.unwrap(), to.kind()), + expected: from.clone(), + location, + }); + } + } + Ok(()) + } + fn is_function_closure(&self, t: ast::Type) -> bool { if self.is_function_closure_type(&t) { true 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 c743d564339..736d37fe83f 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs @@ -2439,6 +2439,7 @@ fn get_type_method_key(typ: &Type) -> Option { | Type::Error | Type::Struct(_, _) | Type::InfixExpr(..) + | Type::CheckedCast { .. } | Type::TraitAsType(..) => None, } } 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 3315b38a351..63471efac43 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs @@ -95,6 +95,15 @@ pub enum ParserErrorReason { AssociatedTypesNotAllowedInPaths, #[error("Associated types are not allowed on a method call")] AssociatedTypesNotAllowedInMethodCalls, + #[error( + "Wrong number of arguments for attribute `{}`. Expected {}, found {}", + name, + if min == max { min.to_string() } else { format!("between {} and {}", min, max) }, + found + )] + WrongNumberOfAttributeArguments { name: String, min: usize, max: usize, found: usize }, + #[error("The `deprecated` attribute expects a string argument")] + DeprecatedAttributeExpectsAStringArgument, } /// Represents a parsing error, or a parsing error in the making. 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 0030144b5e1..f369839ddd4 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs @@ -318,6 +318,30 @@ impl<'a> Parser<'a> { } } + fn eat_attribute_start(&mut self) -> Option { + if matches!(self.token.token(), Token::AttributeStart { is_inner: false, .. }) { + let token = self.bump(); + match token.into_token() { + Token::AttributeStart { is_tag, .. } => Some(is_tag), + _ => unreachable!(), + } + } else { + None + } + } + + fn eat_inner_attribute_start(&mut self) -> Option { + if matches!(self.token.token(), Token::AttributeStart { is_inner: true, .. }) { + let token = self.bump(); + match token.into_token() { + Token::AttributeStart { is_tag, .. } => Some(is_tag), + _ => unreachable!(), + } + } else { + None + } + } + fn eat_comma(&mut self) -> bool { self.eat(Token::Comma) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/attributes.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/attributes.rs index ffba74003b7..12cb37edb4b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/attributes.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/attributes.rs @@ -1,32 +1,87 @@ use noirc_errors::Span; +use crate::ast::{Expression, ExpressionKind, Ident, Literal, Path}; +use crate::lexer::errors::LexerErrorKind; +use crate::parser::labels::ParsingRuleLabel; use crate::parser::ParserErrorReason; -use crate::token::SecondaryAttribute; -use crate::token::{Attribute, Token, TokenKind}; +use crate::token::{Attribute, FunctionAttribute, MetaAttribute, TestScope, Token}; +use crate::token::{CustomAttribute, SecondaryAttribute}; use super::parse_many::without_separator; use super::Parser; impl<'a> Parser<'a> { - /// InnerAttribute = inner_attribute + /// InnerAttribute = '#![' SecondaryAttribute ']' pub(super) fn parse_inner_attribute(&mut self) -> Option { - let token = self.eat_kind(TokenKind::InnerAttribute)?; - match token.into_token() { - Token::InnerAttribute(attribute) => Some(attribute), - _ => unreachable!(), + let start_span = self.current_token_span; + let is_tag = self.eat_inner_attribute_start()?; + let attribute = if is_tag { + self.parse_tag_attribute(start_span) + } else { + self.parse_non_tag_attribute(start_span) + }; + + match attribute { + Attribute::Function(function_attribute) => { + self.errors.push( + LexerErrorKind::InvalidInnerAttribute { + span: self.span_since(start_span), + found: function_attribute.to_string(), + } + .into(), + ); + None + } + Attribute::Secondary(secondary_attribute) => Some(secondary_attribute), } } - /// Attributes = attribute* + /// Attributes = Attribute* pub(super) fn parse_attributes(&mut self) -> Vec<(Attribute, Span)> { self.parse_many("attributes", without_separator(), Self::parse_attribute) } - fn parse_attribute(&mut self) -> Option<(Attribute, Span)> { - self.eat_kind(TokenKind::Attribute).map(|token| match token.into_token() { - Token::Attribute(attribute) => (attribute, self.previous_token_span), - _ => unreachable!(), - }) + /// Attribute = '#[' (FunctionAttribute | SecondaryAttribute) ']' + /// + /// FunctionAttribute + /// = 'builtin' '(' AttributeValue ')' + /// | 'fold' + /// | 'foreign' '(' AttributeValue ')' + /// | 'inline_always' + /// | 'no_predicates' + /// | 'oracle' '(' AttributeValue ')' + /// | 'recursive' + /// | 'test' + /// | 'test' '(' 'should_fail' ')' + /// | 'test' '(' 'should_fail_with' '=' string ')' + /// + /// SecondaryAttribute + /// = 'abi' '(' AttributeValue ')' + /// | 'allow' '(' AttributeValue ')' + /// | 'deprecated' + /// | 'deprecated' '(' string ')' + /// | 'contract_library_method' + /// | 'export' + /// | 'field' '(' AttributeValue ')' + /// | 'use_callers_scope' + /// | 'varargs' + /// | MetaAttribute + /// + /// MetaAttribute + /// = Path Arguments? + /// + /// AttributeValue + /// = Path + /// | integer + pub(crate) fn parse_attribute(&mut self) -> Option<(Attribute, Span)> { + let start_span = self.current_token_span; + let is_tag = self.eat_attribute_start()?; + let attribute = if is_tag { + self.parse_tag_attribute(start_span) + } else { + self.parse_non_tag_attribute(start_span) + }; + Some((attribute, self.span_since(start_span))) } pub(super) fn validate_secondary_attributes( @@ -44,17 +99,315 @@ impl<'a> Parser<'a> { }) .collect() } + + fn parse_tag_attribute(&mut self, start_span: Span) -> Attribute { + let contents_start_span = self.current_token_span; + let mut contents_span = contents_start_span; + let mut contents = String::new(); + + let mut brackets_count = 1; // 1 because of the starting `#[` + + while !self.at_eof() { + if self.at(Token::LeftBracket) { + brackets_count += 1; + } else if self.at(Token::RightBracket) { + brackets_count -= 1; + if brackets_count == 0 { + contents_span = self.span_since(contents_start_span); + self.bump(); + break; + } + } + + contents.push_str(&self.token.to_string()); + self.bump(); + } + + Attribute::Secondary(SecondaryAttribute::Tag(CustomAttribute { + contents, + span: self.span_since(start_span), + contents_span, + })) + } + + fn parse_non_tag_attribute(&mut self, start_span: Span) -> Attribute { + if matches!(&self.token.token(), Token::Keyword(..)) + && (self.next_is(Token::LeftParen) || self.next_is(Token::RightBracket)) + { + // This is a Meta attribute with the syntax `keyword(arg1, arg2, .., argN)` + let path = Path::from_single(self.token.to_string(), self.current_token_span); + self.bump(); + self.parse_meta_attribute(path, start_span) + } else if let Some(path) = self.parse_path_no_turbofish() { + if let Some(ident) = path.as_ident() { + if ident.0.contents == "test" { + // The test attribute is the only secondary attribute that has `a = b` in its syntax + // (`should_fail_with = "..."``) so we parse it differently. + self.parse_test_attribute(start_span) + } else { + // Every other attribute has the form `name(arg1, arg2, .., argN)` + self.parse_ident_attribute_other_than_test(ident, start_span) + } + } else { + // This is a Meta attribute with the syntax `path(arg1, arg2, .., argN)` + self.parse_meta_attribute(path, start_span) + } + } else { + self.expected_label(ParsingRuleLabel::Path); + self.parse_tag_attribute(start_span) + } + } + + fn parse_meta_attribute(&mut self, name: Path, start_span: Span) -> Attribute { + let arguments = self.parse_arguments().unwrap_or_default(); + self.skip_until_right_bracket(); + Attribute::Secondary(SecondaryAttribute::Meta(MetaAttribute { + name, + arguments, + span: self.span_since(start_span), + })) + } + + fn parse_ident_attribute_other_than_test( + &mut self, + ident: &Ident, + start_span: Span, + ) -> Attribute { + let arguments = self.parse_arguments().unwrap_or_default(); + self.skip_until_right_bracket(); + match ident.0.contents.as_str() { + "abi" => self.parse_single_name_attribute(ident, arguments, start_span, |name| { + Attribute::Secondary(SecondaryAttribute::Abi(name)) + }), + "allow" => self.parse_single_name_attribute(ident, arguments, start_span, |name| { + Attribute::Secondary(SecondaryAttribute::Allow(name)) + }), + "builtin" => self.parse_single_name_attribute(ident, arguments, start_span, |name| { + Attribute::Function(FunctionAttribute::Builtin(name)) + }), + "deprecated" => self.parse_deprecated_attribute(ident, arguments), + "contract_library_method" => { + let attr = Attribute::Secondary(SecondaryAttribute::ContractLibraryMethod); + self.parse_no_args_attribute(ident, arguments, attr) + } + "export" => { + let attr = Attribute::Secondary(SecondaryAttribute::Export); + self.parse_no_args_attribute(ident, arguments, attr) + } + "field" => self.parse_single_name_attribute(ident, arguments, start_span, |name| { + Attribute::Secondary(SecondaryAttribute::Field(name)) + }), + "fold" => { + let attr = Attribute::Function(FunctionAttribute::Fold); + self.parse_no_args_attribute(ident, arguments, attr) + } + "foreign" => self.parse_single_name_attribute(ident, arguments, start_span, |name| { + Attribute::Function(FunctionAttribute::Foreign(name)) + }), + "inline_always" => { + let attr = Attribute::Function(FunctionAttribute::InlineAlways); + self.parse_no_args_attribute(ident, arguments, attr) + } + "no_predicates" => { + let attr = Attribute::Function(FunctionAttribute::NoPredicates); + self.parse_no_args_attribute(ident, arguments, attr) + } + "oracle" => self.parse_single_name_attribute(ident, arguments, start_span, |name| { + Attribute::Function(FunctionAttribute::Oracle(name)) + }), + "use_callers_scope" => { + let attr = Attribute::Secondary(SecondaryAttribute::UseCallersScope); + self.parse_no_args_attribute(ident, arguments, attr) + } + "varargs" => { + let attr = Attribute::Secondary(SecondaryAttribute::Varargs); + self.parse_no_args_attribute(ident, arguments, attr) + } + _ => Attribute::Secondary(SecondaryAttribute::Meta(MetaAttribute { + name: Path::from_ident(ident.clone()), + arguments, + span: self.span_since(start_span), + })), + } + } + + fn parse_deprecated_attribute( + &mut self, + ident: &Ident, + mut arguments: Vec, + ) -> Attribute { + if arguments.is_empty() { + return Attribute::Secondary(SecondaryAttribute::Deprecated(None)); + } + + if arguments.len() > 1 { + self.push_error( + ParserErrorReason::WrongNumberOfAttributeArguments { + name: ident.to_string(), + min: 0, + max: 1, + found: arguments.len(), + }, + ident.span(), + ); + return Attribute::Secondary(SecondaryAttribute::Deprecated(None)); + } + + let argument = arguments.remove(0); + let ExpressionKind::Literal(Literal::Str(message)) = argument.kind else { + self.push_error( + ParserErrorReason::DeprecatedAttributeExpectsAStringArgument, + argument.span, + ); + return Attribute::Secondary(SecondaryAttribute::Deprecated(None)); + }; + + Attribute::Secondary(SecondaryAttribute::Deprecated(Some(message))) + } + + fn parse_test_attribute(&mut self, start_span: Span) -> Attribute { + let scope = if self.eat_left_paren() { + let scope = if let Some(ident) = self.eat_ident() { + match ident.0.contents.as_str() { + "should_fail" => Some(TestScope::ShouldFailWith { reason: None }), + "should_fail_with" => { + self.eat_or_error(Token::Assign); + if let Some(reason) = self.eat_str() { + Some(TestScope::ShouldFailWith { reason: Some(reason) }) + } else { + Some(TestScope::ShouldFailWith { reason: None }) + } + } + _ => None, + } + } else { + None + }; + self.eat_or_error(Token::RightParen); + scope + } else { + Some(TestScope::None) + }; + + self.skip_until_right_bracket(); + + let scope = if let Some(scope) = scope { + scope + } else { + self.errors.push( + LexerErrorKind::MalformedTestAttribute { span: self.span_since(start_span) }.into(), + ); + TestScope::None + }; + + Attribute::Function(FunctionAttribute::Test(scope)) + } + + fn parse_single_name_attribute( + &mut self, + ident: &Ident, + mut arguments: Vec, + start_span: Span, + f: F, + ) -> Attribute + where + F: FnOnce(String) -> Attribute, + { + if arguments.len() != 1 { + self.push_error( + ParserErrorReason::WrongNumberOfAttributeArguments { + name: ident.to_string(), + min: 1, + max: 1, + found: arguments.len(), + }, + self.current_token_span, + ); + return f(String::new()); + } + + let argument = arguments.remove(0); + match argument.kind { + ExpressionKind::Variable(..) | ExpressionKind::Literal(Literal::Integer(..)) => { + f(argument.to_string()) + } + _ => { + let span = self.span_since(start_span); + self.errors.push( + LexerErrorKind::MalformedFuncAttribute { span, found: argument.to_string() } + .into(), + ); + f(String::new()) + } + } + } + + fn parse_no_args_attribute( + &mut self, + ident: &Ident, + arguments: Vec, + attribute: Attribute, + ) -> Attribute { + if !arguments.is_empty() { + self.push_error( + ParserErrorReason::WrongNumberOfAttributeArguments { + name: ident.to_string(), + min: 0, + max: 0, + found: arguments.len(), + }, + ident.span(), + ); + } + + attribute + } + + fn skip_until_right_bracket(&mut self) { + let mut brackets_count = 1; // 1 because of the starting `#[` + + while !self.at_eof() { + if self.at(Token::LeftBracket) { + brackets_count += 1; + } else if self.at(Token::RightBracket) { + brackets_count -= 1; + if brackets_count == 0 { + self.bump(); + break; + } + } + + self.expected_token(Token::RightBracket); + self.bump(); + } + } } #[cfg(test)] mod tests { + use noirc_errors::Span; + use crate::{ parser::{parser::tests::expect_no_errors, Parser}, token::{Attribute, FunctionAttribute, SecondaryAttribute, TestScope}, }; + fn parse_inner_secondary_attribute_no_errors(src: &str, expected: SecondaryAttribute) { + let mut parser = Parser::for_str(src); + let attribute = parser.parse_inner_attribute(); + expect_no_errors(&parser.errors); + assert_eq!(attribute.unwrap(), expected); + } + + fn parse_attribute_no_errors(src: &str, expected: Attribute) { + let mut parser = Parser::for_str(src); + let (attribute, _span) = parser.parse_attribute().unwrap(); + expect_no_errors(&parser.errors); + assert_eq!(attribute, expected); + } + #[test] - fn parses_inner_attribute() { + fn parses_inner_attribute_as_tag() { let src = "#!['hello]"; let mut parser = Parser::for_str(src); let Some(SecondaryAttribute::Tag(custom)) = parser.parse_inner_attribute() else { @@ -62,6 +415,210 @@ mod tests { }; expect_no_errors(&parser.errors); assert_eq!(custom.contents, "hello"); + assert_eq!(custom.span, Span::from(0..src.len() as u32)); + assert_eq!(custom.contents_span, Span::from(4..src.len() as u32 - 1)); + } + + #[test] + fn parses_inner_attribute_as_tag_with_nested_brackets() { + let src = "#!['hello[1]]"; + let mut parser = Parser::for_str(src); + let Some(SecondaryAttribute::Tag(custom)) = parser.parse_inner_attribute() else { + panic!("Expected inner tag attribute"); + }; + expect_no_errors(&parser.errors); + assert_eq!(custom.contents, "hello[1]"); + } + + #[test] + fn parses_inner_attribute_deprecated() { + let src = "#![deprecated]"; + let expected = SecondaryAttribute::Deprecated(None); + parse_inner_secondary_attribute_no_errors(src, expected); + } + + #[test] + fn parses_inner_attribute_deprecated_with_message() { + let src = "#![deprecated(\"use something else\")]"; + let expected = SecondaryAttribute::Deprecated(Some("use something else".to_string())); + parse_inner_secondary_attribute_no_errors(src, expected); + } + + #[test] + fn parses_inner_attribute_contract_library_method() { + let src = "#![contract_library_method]"; + let expected = SecondaryAttribute::ContractLibraryMethod; + parse_inner_secondary_attribute_no_errors(src, expected); + } + + #[test] + fn parses_inner_attribute_export() { + let src = "#![export]"; + let expected = SecondaryAttribute::Export; + parse_inner_secondary_attribute_no_errors(src, expected); + } + + #[test] + fn parses_inner_attribute_varargs() { + let src = "#![varargs]"; + let expected = SecondaryAttribute::Varargs; + parse_inner_secondary_attribute_no_errors(src, expected); + } + + #[test] + fn parses_inner_attribute_use_callers_scope() { + let src = "#![use_callers_scope]"; + let expected = SecondaryAttribute::UseCallersScope; + parse_inner_secondary_attribute_no_errors(src, expected); + } + + #[test] + fn parses_attribute_abi() { + let src = "#[abi(foo)]"; + let expected = Attribute::Secondary(SecondaryAttribute::Abi("foo".to_string())); + parse_attribute_no_errors(src, expected); + } + + #[test] + fn parses_attribute_foreign() { + let src = "#[foreign(foo)]"; + let expected = Attribute::Function(FunctionAttribute::Foreign("foo".to_string())); + parse_attribute_no_errors(src, expected); + } + + #[test] + fn parses_attribute_builtin() { + let src = "#[builtin(foo)]"; + let expected = Attribute::Function(FunctionAttribute::Builtin("foo".to_string())); + parse_attribute_no_errors(src, expected); + } + + #[test] + fn parses_attribute_oracle() { + let src = "#[oracle(foo)]"; + let expected = Attribute::Function(FunctionAttribute::Oracle("foo".to_string())); + parse_attribute_no_errors(src, expected); + } + + #[test] + fn parses_attribute_fold() { + let src = "#[fold]"; + let expected = Attribute::Function(FunctionAttribute::Fold); + parse_attribute_no_errors(src, expected); + } + + #[test] + fn parses_attribute_no_predicates() { + let src = "#[no_predicates]"; + let expected = Attribute::Function(FunctionAttribute::NoPredicates); + parse_attribute_no_errors(src, expected); + } + + #[test] + fn parses_attribute_inline_always() { + let src = "#[inline_always]"; + let expected = Attribute::Function(FunctionAttribute::InlineAlways); + parse_attribute_no_errors(src, expected); + } + + #[test] + fn parses_attribute_field() { + let src = "#[field(bn254)]"; + let expected = Attribute::Secondary(SecondaryAttribute::Field("bn254".to_string())); + parse_attribute_no_errors(src, expected); + } + + #[test] + fn parses_attribute_field_with_integer() { + let src = "#[field(23)]"; + let expected = Attribute::Secondary(SecondaryAttribute::Field("23".to_string())); + parse_attribute_no_errors(src, expected); + } + + #[test] + fn parses_attribute_allow() { + let src = "#[allow(unused_vars)]"; + let expected = Attribute::Secondary(SecondaryAttribute::Allow("unused_vars".to_string())); + parse_attribute_no_errors(src, expected); + } + + #[test] + fn parses_attribute_test_no_scope() { + let src = "#[test]"; + let expected = Attribute::Function(FunctionAttribute::Test(TestScope::None)); + parse_attribute_no_errors(src, expected); + } + + #[test] + fn parses_attribute_test_should_fail() { + let src = "#[test(should_fail)]"; + let expected = Attribute::Function(FunctionAttribute::Test(TestScope::ShouldFailWith { + reason: None, + })); + parse_attribute_no_errors(src, expected); + } + + #[test] + fn parses_attribute_test_should_fail_with() { + let src = "#[test(should_fail_with = \"reason\")]"; + let expected = Attribute::Function(FunctionAttribute::Test(TestScope::ShouldFailWith { + reason: Some("reason".to_string()), + })); + parse_attribute_no_errors(src, expected); + } + + #[test] + fn parses_meta_attribute_single_identifier_no_arguments() { + let src = "#[foo]"; + let mut parser = Parser::for_str(src); + let (attribute, _span) = parser.parse_attribute().unwrap(); + expect_no_errors(&parser.errors); + let Attribute::Secondary(SecondaryAttribute::Meta(meta)) = attribute else { + panic!("Expected meta attribute"); + }; + assert_eq!(meta.name.to_string(), "foo"); + assert!(meta.arguments.is_empty()); + } + + #[test] + fn parses_meta_attribute_single_identifier_as_keyword() { + let src = "#[dep]"; + let mut parser = Parser::for_str(src); + let (attribute, _span) = parser.parse_attribute().unwrap(); + expect_no_errors(&parser.errors); + let Attribute::Secondary(SecondaryAttribute::Meta(meta)) = attribute else { + panic!("Expected meta attribute"); + }; + assert_eq!(meta.name.to_string(), "dep"); + assert!(meta.arguments.is_empty()); + } + + #[test] + fn parses_meta_attribute_single_identifier_with_arguments() { + let src = "#[foo(1, 2, 3)]"; + let mut parser = Parser::for_str(src); + let (attribute, _span) = parser.parse_attribute().unwrap(); + expect_no_errors(&parser.errors); + let Attribute::Secondary(SecondaryAttribute::Meta(meta)) = attribute else { + panic!("Expected meta attribute"); + }; + assert_eq!(meta.name.to_string(), "foo"); + assert_eq!(meta.arguments.len(), 3); + assert_eq!(meta.arguments[0].to_string(), "1"); + } + + #[test] + fn parses_meta_attribute_path_with_arguments() { + let src = "#[foo::bar(1, 2, 3)]"; + let mut parser = Parser::for_str(src); + let (attribute, _span) = parser.parse_attribute().unwrap(); + expect_no_errors(&parser.errors); + let Attribute::Secondary(SecondaryAttribute::Meta(meta)) = attribute else { + panic!("Expected meta attribute"); + }; + assert_eq!(meta.name.to_string(), "foo::bar"); + assert_eq!(meta.arguments.len(), 3); + assert_eq!(meta.arguments[0].to_string(), "1"); } #[test] 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 a60bc6e7c1d..438757b5d79 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 @@ -246,22 +246,23 @@ impl<'a> Parser<'a> { } fn validate_attributes(&mut self, attributes: Vec<(Attribute, Span)>) -> Attributes { - let mut primary = None; + let mut function = None; let mut secondary = Vec::new(); - for (attribute, span) in attributes { + for (index, (attribute, span)) in attributes.into_iter().enumerate() { match attribute { Attribute::Function(attr) => { - if primary.is_some() { + if function.is_none() { + function = Some((attr, index)); + } else { self.push_error(ParserErrorReason::MultipleFunctionAttributesFound, span); } - primary = Some(attr); } Attribute::Secondary(attr) => secondary.push(attr), } } - Attributes { function: primary, secondary } + Attributes { function, secondary } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs index 17accbd8366..f72741721d8 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs @@ -1,6 +1,7 @@ #![cfg(test)] mod aliases; +mod arithmetic_generics; mod bound_checks; mod imports; mod metaprogramming; @@ -36,6 +37,8 @@ use crate::hir::def_collector::dc_crate::DefCollector; use crate::hir::def_map::{CrateDefMap, LocalModuleId}; use crate::hir_def::expr::HirExpression; use crate::hir_def::stmt::HirStatement; +use crate::monomorphization::ast::Program; +use crate::monomorphization::errors::MonomorphizationError; use crate::monomorphization::monomorphize; use crate::parser::{ItemKind, ParserErrorReason}; use crate::token::SecondaryAttribute; @@ -57,6 +60,15 @@ pub(crate) fn remove_experimental_warnings(errors: &mut Vec<(CompilationError, F } pub(crate) fn get_program(src: &str) -> (ParsedModule, Context, Vec<(CompilationError, FileId)>) { + get_program_with_maybe_parser_errors( + src, false, // allow parser errors + ) +} + +pub(crate) fn get_program_with_maybe_parser_errors( + src: &str, + allow_parser_errors: bool, +) -> (ParsedModule, Context, Vec<(CompilationError, FileId)>) { let root = std::path::Path::new("/"); let fm = FileManager::new(root); @@ -69,7 +81,7 @@ pub(crate) fn get_program(src: &str) -> (ParsedModule, Context, Vec<(Compilation let mut errors = vecmap(parser_errors, |e| (e.into(), root_file_id)); remove_experimental_warnings(&mut errors); - if !has_parser_error(&errors) { + if allow_parser_errors || !has_parser_error(&errors) { let inner_attributes: Vec = program .items .iter() @@ -1239,10 +1251,18 @@ fn resolve_fmt_strings() { } } -fn check_rewrite(src: &str, expected: &str) { +fn monomorphize_program(src: &str) -> Result { let (_program, mut context, _errors) = get_program(src); let main_func_id = context.def_interner.find_function("main").unwrap(); - let program = monomorphize(main_func_id, &mut context.def_interner).unwrap(); + monomorphize(main_func_id, &mut context.def_interner) +} + +fn get_monomorphization_error(src: &str) -> Option { + monomorphize_program(src).err() +} + +fn check_rewrite(src: &str, expected: &str) { + let program = monomorphize_program(src).unwrap(); assert!(format!("{}", program) == expected); } @@ -1982,9 +2002,9 @@ fn numeric_generic_u16_array_size() { fn numeric_generic_field_larger_than_u32() { let src = r#" global A: Field = 4294967297; - + fn foo() { } - + fn main() { let _ = foo::(); } @@ -2014,14 +2034,14 @@ fn numeric_generic_field_arithmetic_larger_than_u32() { F } } - + // 2^32 - 1 global A: Field = 4294967295; - + fn foo() -> Foo { Foo {} } - + fn main() { let _ = foo::().size(); } @@ -3189,25 +3209,6 @@ fn as_trait_path_syntax_no_impl() { assert!(matches!(&errors[0].0, TypeError(TypeCheckError::NoMatchingImplFound { .. }))); } -#[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 infer_globals_to_u32_from_type_use() { let src = r#" @@ -3393,6 +3394,36 @@ fn arithmetic_generics_rounding_fail() { let errors = get_program_errors(src); assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::TypeError(TypeCheckError::TypeMismatch { .. }) + )); +} + +#[test] +fn arithmetic_generics_rounding_fail_on_struct() { + let src = r#" + struct W {} + + fn foo(_x: W, _y: W) -> W { + W {} + } + + fn main() { + let w_2: W<2> = W {}; + let w_3: W<3> = W {}; + // Do not simplify N/M*M to just N + // This should be 3/2*2 = 2, not 3 + let _: W<3> = foo(w_3, w_2); + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::TypeError(TypeCheckError::TypeMismatch { .. }) + )); } #[test] @@ -3438,7 +3469,7 @@ fn unconditional_recursion_fail() { fn main() -> pub u64 { foo(1, main()) } - fn foo(a: u64, b: u64) -> u64 { + fn foo(a: u64, b: u64) -> u64 { a + b } "#, @@ -3623,3 +3654,41 @@ fn use_type_alias_to_generic_concrete_type_in_method_call() { "#; assert_no_errors(src); } + +#[test] +fn allows_struct_with_generic_infix_type_as_main_input_1() { + let src = r#" + struct Foo { + x: [u64; N * 2], + } + + fn main(_x: Foo<18>) {} + "#; + assert_no_errors(src); +} + +#[test] +fn allows_struct_with_generic_infix_type_as_main_input_2() { + let src = r#" + struct Foo { + x: [u64; N * 2], + } + + fn main(_x: Foo<2 * 9>) {} + "#; + assert_no_errors(src); +} + +#[test] +fn allows_struct_with_generic_infix_type_as_main_input_3() { + let src = r#" + struct Foo { + x: [u64; N * 2], + } + + global N = 9; + + fn main(_x: Foo) {} + "#; + assert_no_errors(src); +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests/arithmetic_generics.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests/arithmetic_generics.rs new file mode 100644 index 00000000000..3328fe439ae --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests/arithmetic_generics.rs @@ -0,0 +1,155 @@ +#![cfg(test)] + +use acvm::{AcirField, FieldElement}; + +use super::get_program_errors; +use crate::hir::type_check::TypeCheckError; +use crate::hir_def::types::{BinaryTypeOperator, Type}; +use crate::monomorphization::errors::MonomorphizationError; +use crate::tests::get_monomorphization_error; + +#[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 checked_casts_do_not_prevent_canonicalization() { + // Regression test for https://github.com/noir-lang/noir/issues/6495 + let source = r#" + pub trait Serialize { + fn serialize(self) -> [Field; N]; + } + + pub struct Counted { + pub inner: T, + } + + pub fn append(array1: [T; N]) -> [T; N + 1] { + [array1[0]; N + 1] + } + + impl Serialize for Counted + where + T: Serialize, + { + fn serialize(self) -> [Field; N] { + append(self.inner.serialize()) + } + } + "#; + let errors = get_program_errors(source); + println!("{:?}", errors); + assert_eq!(errors.len(), 0); +} + +#[test] +fn arithmetic_generics_checked_cast_zeros() { + let source = r#" + struct W {} + + fn foo(_x: W) -> W<(0 * N) / (N % N)> { + W {} + } + + fn bar(_x: W) -> u1 { + N + } + + fn main() -> pub u1 { + let w_0: W<0> = W {}; + let w: W<_> = foo(w_0); + bar(w) + } + "#; + + let errors = get_program_errors(source); + assert_eq!(errors.len(), 0); + + let monomorphization_error = get_monomorphization_error(source); + assert!(monomorphization_error.is_some()); + + // Expect a CheckedCast (0 % 0) failure + let monomorphization_error = monomorphization_error.unwrap(); + if let MonomorphizationError::UnknownArrayLength { ref length, ref err, location: _ } = + monomorphization_error + { + match length { + Type::CheckedCast { from, to } => { + assert!(matches!(*from.clone(), Type::InfixExpr { .. })); + assert!(matches!(*to.clone(), Type::InfixExpr { .. })); + } + _ => panic!("unexpected length: {:?}", length), + } + assert!(matches!( + err, + TypeCheckError::FailingBinaryOp { op: BinaryTypeOperator::Modulo, lhs: 0, rhs: 0, .. } + )); + } else { + panic!("unexpected error: {:?}", monomorphization_error); + } +} + +#[test] +fn arithmetic_generics_checked_cast_indirect_zeros() { + let source = r#" + struct W {} + + fn foo(_x: W) -> W<(N - N) % (N - N)> { + W {} + } + + fn bar(_x: W) -> Field { + N + } + + fn main() { + let w_0: W<0> = W {}; + let w = foo(w_0); + let _ = bar(w); + } + "#; + + let errors = get_program_errors(source); + assert_eq!(errors.len(), 0); + + let monomorphization_error = get_monomorphization_error(source); + assert!(monomorphization_error.is_some()); + + // Expect a CheckedCast (0 % 0) failure + let monomorphization_error = monomorphization_error.unwrap(); + if let MonomorphizationError::UnknownArrayLength { ref length, ref err, location: _ } = + monomorphization_error + { + match length { + Type::CheckedCast { from, to } => { + assert!(matches!(*from.clone(), Type::InfixExpr { .. })); + assert!(matches!(*to.clone(), Type::InfixExpr { .. })); + } + _ => panic!("unexpected length: {:?}", length), + } + match err { + TypeCheckError::ModuloOnFields { lhs, rhs, .. } => { + assert_eq!(lhs.clone(), FieldElement::zero()); + assert_eq!(rhs.clone(), FieldElement::zero()); + } + _ => panic!("expected ModuloOnFields, but found: {:?}", err), + } + } else { + panic!("unexpected error: {:?}", monomorphization_error); + } +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests/imports.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests/imports.rs index 1da7f5ce0ce..8598d8296e5 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests/imports.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests/imports.rs @@ -127,3 +127,30 @@ fn warns_on_re_export_of_item_with_less_visibility() { ) )); } + +#[test] +fn errors_if_using_alias_in_import() { + let src = r#" + mod foo { + pub type bar = i32; + } + + use foo::bar::baz; + + fn main() { + } + "#; + + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + let CompilationError::DefinitionError(DefCollectorErrorKind::PathResolutionError( + PathResolutionError::NotAModule { ident, kind }, + )) = &errors[0].0 + else { + panic!("Expected a 'not a module' error, got {:?}", errors[0].0); + }; + + assert_eq!(ident.to_string(), "bar"); + assert_eq!(*kind, "type alias"); +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests/traits.rs index 42900d094b8..0adf5c90bea 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests/traits.rs @@ -1,6 +1,6 @@ use crate::hir::def_collector::dc_crate::CompilationError; use crate::hir::resolution::errors::ResolverError; -use crate::tests::get_program_errors; +use crate::tests::{get_program_errors, get_program_with_maybe_parser_errors}; use super::assert_no_errors; @@ -390,3 +390,19 @@ fn trait_bounds_which_are_dependent_on_generic_types_are_resolved_correctly() { "#; assert_no_errors(src); } + +#[test] +fn does_not_crash_on_as_trait_path_with_empty_path() { + let src = r#" + struct Foo { + x: , + } + + fn main() {} + "#; + + let (_, _, errors) = get_program_with_maybe_parser_errors( + src, true, // allow parser errors + ); + assert!(!errors.is_empty()); +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests/unused_items.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests/unused_items.rs index 86f77fc397a..5f9fc887b27 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests/unused_items.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests/unused_items.rs @@ -294,3 +294,23 @@ fn no_warning_on_self_in_trait_impl() { "#; assert_no_errors(src); } + +#[test] +fn resolves_trait_where_clause_in_the_correct_module() { + // This is a regression test for https://github.com/noir-lang/noir/issues/6479 + let src = r#" + mod foo { + pub trait Foo {} + } + + use foo::Foo; + + pub trait Bar + where + T: Foo, + {} + + fn main() {} + "#; + assert_no_errors(src); +} diff --git a/noir/noir-repo/compiler/wasm/package.json b/noir/noir-repo/compiler/wasm/package.json index bbb3b1ede01..9b819ef64bb 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.37.0", + "version": "0.38.0", "license": "(MIT OR Apache-2.0)", "main": "dist/main.js", "types": "./dist/types/src/index.d.cts", diff --git a/noir/noir-repo/compiler/wasm/src/compile.rs b/noir/noir-repo/compiler/wasm/src/compile.rs index 2e178739bc5..e823f90add5 100644 --- a/noir/noir-repo/compiler/wasm/src/compile.rs +++ b/noir/noir-repo/compiler/wasm/src/compile.rs @@ -180,13 +180,13 @@ pub fn compile_program( .0; let optimized_program = nargo::ops::transform_program(compiled_program, expression_width); - // nargo::ops::check_program(&optimized_program).map_err(|errs| { - // CompileError::with_file_diagnostics( - // "Compiled program is not solvable", - // errs, - // &context.file_manager, - // ) - // })?; + nargo::ops::check_program(&optimized_program).map_err(|errs| { + CompileError::with_file_diagnostics( + "Compiled program is not solvable", + errs, + &context.file_manager, + ) + })?; let warnings = optimized_program.warnings.clone(); Ok(JsCompileProgramResult::new(optimized_program.into(), warnings)) diff --git a/noir/noir-repo/compiler/wasm/src/compile_new.rs b/noir/noir-repo/compiler/wasm/src/compile_new.rs index 3def12d9bfe..ac2f79147b3 100644 --- a/noir/noir-repo/compiler/wasm/src/compile_new.rs +++ b/noir/noir-repo/compiler/wasm/src/compile_new.rs @@ -118,13 +118,13 @@ impl CompilerContext { .0; let optimized_program = nargo::ops::transform_program(compiled_program, expression_width); - // nargo::ops::check_program(&optimized_program).map_err(|errs| { - // CompileError::with_file_diagnostics( - // "Compiled program is not solvable", - // errs, - // &self.context.file_manager, - // ) - // })?; + nargo::ops::check_program(&optimized_program).map_err(|errs| { + CompileError::with_file_diagnostics( + "Compiled program is not solvable", + errs, + &self.context.file_manager, + ) + })?; let warnings = optimized_program.warnings.clone(); Ok(JsCompileProgramResult::new(optimized_program.into(), warnings)) diff --git a/noir/noir-repo/cspell.json b/noir/noir-repo/cspell.json index 2577bf74548..d8315c35910 100644 --- a/noir/noir-repo/cspell.json +++ b/noir/noir-repo/cspell.json @@ -38,7 +38,10 @@ "callsites", "callstack", "callstacks", + "canonicalization", "canonicalize", + "canonicalized", + "canonicalizing", "castable", "catmcgee", "Celo", @@ -173,6 +176,7 @@ "prettytable", "printstd", "proptest", + "proptests", "pseudocode", "pubkey", "quantile", @@ -199,8 +203,8 @@ "stdlib", "structs", "subexpression", - "subtrait", "subshell", + "subtrait", "subtyping", "supertrait", "supertraits", diff --git a/noir/noir-repo/deny.toml b/noir/noir-repo/deny.toml index 3518628ee44..661c8095281 100644 --- a/noir/noir-repo/deny.toml +++ b/noir/noir-repo/deny.toml @@ -6,7 +6,8 @@ version = 2 yanked = "warn" ignore = [ - "RUSTSEC-2020-0168", # mach unmaintained + "RUSTSEC-2024-0388", # derivative unmaintained + "RUSTSEC-2024-0384", # instant unmaintained "RUSTSEC-2020-0016", # net2 unmaintained ] @@ -49,12 +50,9 @@ allow = [ "ISC", "0BSD", "Unicode-DFS-2016", + "Unicode-3.0", "Unlicense", "Zlib", - # https://github.com/briansmith/ring/issues/902 - "LicenseRef-ring", - # https://github.com/rustls/webpki/blob/main/LICENSE ISC Style - "LicenseRef-rustls-webpki", # bitmaps 2.1.0, im 15.1.0 "MPL-2.0", # Boost Software License @@ -76,16 +74,6 @@ exceptions = [ { allow = ["CDDL-1.0"], name = "inferno" }, ] -[[licenses.clarify]] -name = "ring" -expression = "LicenseRef-ring" -license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }] - -[[licenses.clarify]] -name = "rustls-webpki" -expression = "LicenseRef-rustls-webpki" -license-files = [{ path = "LICENSE", hash = 0x001c7e6c }] - # This section is considered when running `cargo deny check sources`. # More documentation about the 'sources' section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html diff --git a/noir/noir-repo/docs/docs/how_to/how-to-oracles.md b/noir/noir-repo/docs/docs/how_to/how-to-oracles.md index dc49b192384..4763b7788d6 100644 --- a/noir/noir-repo/docs/docs/how_to/how-to-oracles.md +++ b/noir/noir-repo/docs/docs/how_to/how-to-oracles.md @@ -18,8 +18,6 @@ This guide shows you how to use oracles in your Noir program. For the sake of cl - 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: @@ -99,6 +97,12 @@ fn main(input: [Field; 2]) { assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); } + +#[test] +fn test() { + let input = [4, 16]; + main(input); +} ``` :::info @@ -137,44 +141,38 @@ 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("resolve_function_call", async (params) => { - if params.function !== "getSqrt" { - throw Error("Unexpected foreign call") - }; - const values = params.inputs[0].Array.map((field) => { - return `${Math.sqrt(parseInt(field, 16))}`; - }); - return { values: [{ Array: values }] }; +server.addMethod("resolve_foreign_call", async (params) => { + if (params[0].function !== "getSqrt") { + throw Error("Unexpected foreign call") + }; + const values = params[0].inputs[0].map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [values] }; }); ``` 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, -} +export type ForeignCallSingle = string; -interface ArrayForeignCallParam { - Array: string[], -} - -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; +export type ForeignCallArray = string[]; -interface ForeignCallResult { - values: ForeignCallParam[], -} +export type ForeignCallResult = { + values: (ForeignCallSingle | ForeignCallArray)[]; +}; ``` -::: Multidimensional Arrays +:::info Multidimensional Arrays -If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in json as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. +If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in JSON as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the Noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. ::: ## Step 3 - Usage with Nargo -Using the [`nargo` CLI tool](../getting_started/noir_installation.md), you can use oracles in the `nargo test` and `nargo execute` commands by passing a value to `--oracle-resolver`. For example: +Using the [`nargo` CLI tool](../reference/nargo_commands.md), you can use oracles in the `nargo test` and `nargo execute` commands by passing a value to `--oracle-resolver`. For example: ```bash nargo test --oracle-resolver http://localhost:5555 @@ -233,17 +231,21 @@ 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 make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - input[0].map((i) => i.toString("hex")), - ]); - return { values: oracleReturn }; + const inputs = input[0].map((i) => i.toString("hex")) + // 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("resolve_foreign_call", [ + { + function: name, + inputs: [inputs] + }, + ]); + return [oracleReturn.values[0]]; }; // the rest of your NoirJS code const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); +const { witness } = await noir.execute(input, foreignCallHandler); ``` :::tip diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.32.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.32.0/how_to/how-to-oracles.md index 2f69902062c..94a89710e66 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.32.0/how_to/how-to-oracles.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.32.0/how_to/how-to-oracles.md @@ -18,8 +18,6 @@ This guide shows you how to use oracles in your Noir program. For the sake of cl - 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: @@ -137,38 +135,32 @@ 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("resolve_function_call", async (params) => { - if params.function !== "getSqrt" { - throw Error("Unexpected foreign call") - }; - const values = params.inputs[0].Array.map((field) => { - return `${Math.sqrt(parseInt(field, 16))}`; - }); - return { values: [{ Array: values }] }; +server.addMethod("resolve_foreign_call", async (params) => { + if (params[0].function !== "getSqrt") { + throw Error("Unexpected foreign call") + }; + const values = params[0].inputs[0].map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [values] }; }); ``` 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[], -} +export type ForeignCallSingle = string; -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; +export type ForeignCallArray = string[]; -interface ForeignCallResult { - values: ForeignCallParam[], -} +export type ForeignCallResult = { + values: (ForeignCallSingle | ForeignCallArray)[]; +}; ``` -::: Multidimensional Arrays +:::info Multidimensional Arrays -If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in json as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. +If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in JSON as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the Noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. ::: @@ -233,17 +225,21 @@ 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 make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - input[0].map((i) => i.toString("hex")), - ]); - return { values: oracleReturn }; + const inputs = input[0].map((i) => i.toString("hex")) + // 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("resolve_foreign_call", [ + { + function: name, + inputs: [inputs] + }, + ]); + return [oracleReturn.values[0]]; }; // the rest of your NoirJS code const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); +const { witness } = await noir.execute(input, foreignCallHandler); ``` :::tip diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.33.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.33.0/how_to/how-to-oracles.md index 2f69902062c..392dd8b452e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.33.0/how_to/how-to-oracles.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.33.0/how_to/how-to-oracles.md @@ -18,8 +18,6 @@ This guide shows you how to use oracles in your Noir program. For the sake of cl - 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: @@ -99,6 +97,12 @@ fn main(input: [Field; 2]) { assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); } + +#[test] +fn test() { + let input = [4, 16]; + main(input); +} ``` :::info @@ -137,38 +141,32 @@ 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("resolve_function_call", async (params) => { - if params.function !== "getSqrt" { - throw Error("Unexpected foreign call") - }; - const values = params.inputs[0].Array.map((field) => { - return `${Math.sqrt(parseInt(field, 16))}`; - }); - return { values: [{ Array: values }] }; +server.addMethod("resolve_foreign_call", async (params) => { + if (params[0].function !== "getSqrt") { + throw Error("Unexpected foreign call") + }; + const values = params[0].inputs[0].map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [values] }; }); ``` 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, -} +export type ForeignCallSingle = string; -interface ArrayForeignCallParam { - Array: string[], -} - -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; +export type ForeignCallArray = string[]; -interface ForeignCallResult { - values: ForeignCallParam[], -} +export type ForeignCallResult = { + values: (ForeignCallSingle | ForeignCallArray)[]; +}; ``` -::: Multidimensional Arrays +:::info Multidimensional Arrays -If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in json as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. +If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in JSON as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the Noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. ::: @@ -233,17 +231,21 @@ 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 make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - input[0].map((i) => i.toString("hex")), - ]); - return { values: oracleReturn }; + const inputs = input[0].map((i) => i.toString("hex")) + // 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("resolve_foreign_call", [ + { + function: name, + inputs: [inputs] + }, + ]); + return [oracleReturn.values[0]]; }; // the rest of your NoirJS code const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); +const { witness } = await noir.execute(input, foreignCallHandler); ``` :::tip @@ -270,4 +272,4 @@ app.use(cors()) 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. +- Provide custom foreign call handlers for NoirJS. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/how-to-oracles.md index 2f69902062c..392dd8b452e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/how-to-oracles.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.34.0/how_to/how-to-oracles.md @@ -18,8 +18,6 @@ This guide shows you how to use oracles in your Noir program. For the sake of cl - 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: @@ -99,6 +97,12 @@ fn main(input: [Field; 2]) { assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); } + +#[test] +fn test() { + let input = [4, 16]; + main(input); +} ``` :::info @@ -137,38 +141,32 @@ 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("resolve_function_call", async (params) => { - if params.function !== "getSqrt" { - throw Error("Unexpected foreign call") - }; - const values = params.inputs[0].Array.map((field) => { - return `${Math.sqrt(parseInt(field, 16))}`; - }); - return { values: [{ Array: values }] }; +server.addMethod("resolve_foreign_call", async (params) => { + if (params[0].function !== "getSqrt") { + throw Error("Unexpected foreign call") + }; + const values = params[0].inputs[0].map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [values] }; }); ``` 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, -} +export type ForeignCallSingle = string; -interface ArrayForeignCallParam { - Array: string[], -} - -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; +export type ForeignCallArray = string[]; -interface ForeignCallResult { - values: ForeignCallParam[], -} +export type ForeignCallResult = { + values: (ForeignCallSingle | ForeignCallArray)[]; +}; ``` -::: Multidimensional Arrays +:::info Multidimensional Arrays -If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in json as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. +If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in JSON as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the Noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. ::: @@ -233,17 +231,21 @@ 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 make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - input[0].map((i) => i.toString("hex")), - ]); - return { values: oracleReturn }; + const inputs = input[0].map((i) => i.toString("hex")) + // 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("resolve_foreign_call", [ + { + function: name, + inputs: [inputs] + }, + ]); + return [oracleReturn.values[0]]; }; // the rest of your NoirJS code const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); +const { witness } = await noir.execute(input, foreignCallHandler); ``` :::tip @@ -270,4 +272,4 @@ app.use(cors()) 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. +- Provide custom foreign call handlers for NoirJS. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.35.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.35.0/how_to/how-to-oracles.md index 2f69902062c..392dd8b452e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.35.0/how_to/how-to-oracles.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.35.0/how_to/how-to-oracles.md @@ -18,8 +18,6 @@ This guide shows you how to use oracles in your Noir program. For the sake of cl - 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: @@ -99,6 +97,12 @@ fn main(input: [Field; 2]) { assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); } + +#[test] +fn test() { + let input = [4, 16]; + main(input); +} ``` :::info @@ -137,38 +141,32 @@ 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("resolve_function_call", async (params) => { - if params.function !== "getSqrt" { - throw Error("Unexpected foreign call") - }; - const values = params.inputs[0].Array.map((field) => { - return `${Math.sqrt(parseInt(field, 16))}`; - }); - return { values: [{ Array: values }] }; +server.addMethod("resolve_foreign_call", async (params) => { + if (params[0].function !== "getSqrt") { + throw Error("Unexpected foreign call") + }; + const values = params[0].inputs[0].map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [values] }; }); ``` 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, -} +export type ForeignCallSingle = string; -interface ArrayForeignCallParam { - Array: string[], -} - -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; +export type ForeignCallArray = string[]; -interface ForeignCallResult { - values: ForeignCallParam[], -} +export type ForeignCallResult = { + values: (ForeignCallSingle | ForeignCallArray)[]; +}; ``` -::: Multidimensional Arrays +:::info Multidimensional Arrays -If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in json as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. +If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in JSON as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the Noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. ::: @@ -233,17 +231,21 @@ 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 make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - input[0].map((i) => i.toString("hex")), - ]); - return { values: oracleReturn }; + const inputs = input[0].map((i) => i.toString("hex")) + // 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("resolve_foreign_call", [ + { + function: name, + inputs: [inputs] + }, + ]); + return [oracleReturn.values[0]]; }; // the rest of your NoirJS code const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); +const { witness } = await noir.execute(input, foreignCallHandler); ``` :::tip @@ -270,4 +272,4 @@ app.use(cors()) 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. +- Provide custom foreign call handlers for NoirJS. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.36.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.36.0/how_to/how-to-oracles.md index dc49b192384..08ce6ee5476 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.36.0/how_to/how-to-oracles.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.36.0/how_to/how-to-oracles.md @@ -18,8 +18,6 @@ This guide shows you how to use oracles in your Noir program. For the sake of cl - 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: @@ -99,6 +97,12 @@ fn main(input: [Field; 2]) { assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); } + +#[test] +fn test() { + let input = [4, 16]; + main(input); +} ``` :::info @@ -137,44 +141,38 @@ 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("resolve_function_call", async (params) => { - if params.function !== "getSqrt" { - throw Error("Unexpected foreign call") - }; - const values = params.inputs[0].Array.map((field) => { - return `${Math.sqrt(parseInt(field, 16))}`; - }); - return { values: [{ Array: values }] }; +server.addMethod("resolve_foreign_call", async (params) => { + if (params[0].function !== "getSqrt") { + throw Error("Unexpected foreign call") + }; + const values = params[0].inputs[0].map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [values] }; }); ``` 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, -} +export type ForeignCallSingle = string; -interface ArrayForeignCallParam { - Array: string[], -} - -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; +export type ForeignCallArray = string[]; -interface ForeignCallResult { - values: ForeignCallParam[], -} +export type ForeignCallResult = { + values: (ForeignCallSingle | ForeignCallArray)[]; +}; ``` -::: Multidimensional Arrays +:::info Multidimensional Arrays -If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in json as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. +If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in JSON as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the Noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. ::: ## Step 3 - Usage with Nargo -Using the [`nargo` CLI tool](../getting_started/noir_installation.md), you can use oracles in the `nargo test` and `nargo execute` commands by passing a value to `--oracle-resolver`. For example: +Using the [`nargo` CLI tool](../reference/nargo_commands.md), you can use oracles in the `nargo test` and `nargo execute` commands by passing a value to `--oracle-resolver`. For example: ```bash nargo test --oracle-resolver http://localhost:5555 @@ -233,17 +231,21 @@ 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 make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - input[0].map((i) => i.toString("hex")), - ]); - return { values: oracleReturn }; + const inputs = input[0].map((i) => i.toString("hex")) + // 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("resolve_foreign_call", [ + { + function: name, + inputs: [inputs] + }, + ]); + return [oracleReturn.values[0]]; }; // the rest of your NoirJS code const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); +const { witness } = await noir.execute(input, foreignCallHandler); ``` :::tip @@ -270,4 +272,4 @@ app.use(cors()) 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. +- Provide custom foreign call handlers for NoirJS. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.37.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.37.0/how_to/how-to-oracles.md index dc49b192384..08ce6ee5476 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.37.0/how_to/how-to-oracles.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.37.0/how_to/how-to-oracles.md @@ -18,8 +18,6 @@ This guide shows you how to use oracles in your Noir program. For the sake of cl - 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: @@ -99,6 +97,12 @@ fn main(input: [Field; 2]) { assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); } + +#[test] +fn test() { + let input = [4, 16]; + main(input); +} ``` :::info @@ -137,44 +141,38 @@ 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("resolve_function_call", async (params) => { - if params.function !== "getSqrt" { - throw Error("Unexpected foreign call") - }; - const values = params.inputs[0].Array.map((field) => { - return `${Math.sqrt(parseInt(field, 16))}`; - }); - return { values: [{ Array: values }] }; +server.addMethod("resolve_foreign_call", async (params) => { + if (params[0].function !== "getSqrt") { + throw Error("Unexpected foreign call") + }; + const values = params[0].inputs[0].map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [values] }; }); ``` 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, -} +export type ForeignCallSingle = string; -interface ArrayForeignCallParam { - Array: string[], -} - -type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; +export type ForeignCallArray = string[]; -interface ForeignCallResult { - values: ForeignCallParam[], -} +export type ForeignCallResult = { + values: (ForeignCallSingle | ForeignCallArray)[]; +}; ``` -::: Multidimensional Arrays +:::info Multidimensional Arrays -If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in json as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. +If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in JSON as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the Noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. ::: ## Step 3 - Usage with Nargo -Using the [`nargo` CLI tool](../getting_started/noir_installation.md), you can use oracles in the `nargo test` and `nargo execute` commands by passing a value to `--oracle-resolver`. For example: +Using the [`nargo` CLI tool](../reference/nargo_commands.md), you can use oracles in the `nargo test` and `nargo execute` commands by passing a value to `--oracle-resolver`. For example: ```bash nargo test --oracle-resolver http://localhost:5555 @@ -233,17 +231,21 @@ 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 make the RPC request with the first parameter "numbers", which would be input[0] - const oracleReturn = await client.request(name, [ - input[0].map((i) => i.toString("hex")), - ]); - return { values: oracleReturn }; + const inputs = input[0].map((i) => i.toString("hex")) + // 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("resolve_foreign_call", [ + { + function: name, + inputs: [inputs] + }, + ]); + return [oracleReturn.values[0]]; }; // the rest of your NoirJS code const input = { input: [4, 16] }; -const { witness } = await noir.execute(numbers, foreignCallHandler); +const { witness } = await noir.execute(input, foreignCallHandler); ``` :::tip @@ -270,4 +272,4 @@ app.use(cors()) 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. +- Provide custom foreign call handlers for NoirJS. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/explainers/cspell.json b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/explainers/cspell.json new file mode 100644 index 00000000000..c60b0a597b1 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/explainers/cspell.json @@ -0,0 +1,5 @@ +{ + "words": [ + "Cryptdoku" + ] +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/explainers/explainer-oracle.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/explainers/explainer-oracle.md new file mode 100644 index 00000000000..821e1f95c04 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/explainers/explainer-oracle.md @@ -0,0 +1,57 @@ +--- +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 an 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 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.38.0/explainers/explainer-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/explainers/explainer-recursion.md new file mode 100644 index 00000000000..df8529ef4e0 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/explainers/explainer-recursion.md @@ -0,0 +1,176 @@ +--- +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.mdx), 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.38.0/explainers/explainer-writing-noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/explainers/explainer-writing-noir.md new file mode 100644 index 00000000000..3ce4245dc45 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/explainers/explainer-writing-noir.md @@ -0,0 +1,177 @@ +--- +title: Thinking in Circuits +description: Considerations when writing Noir programs +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.38.0/getting_started/noir_installation.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/getting_started/noir_installation.md new file mode 100644 index 00000000000..a5c7e649278 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/getting_started/noir_installation.md @@ -0,0 +1,106 @@ +--- +title: Standalone Noir Installation +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: 2 +--- + +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](#installing-noirup). + +## Setting up shell completions + +Once `nargo` is installed, you can [set up shell completions for it](setting_up_shell_completions). + +## 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.38.0/getting_started/project_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/getting_started/project_breakdown.md new file mode 100644 index 00000000000..e442e377040 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/getting_started/project_breakdown.md @@ -0,0 +1,159 @@ +--- +title: Project Breakdown +description: + Learn about the anatomy of a Nargo project, including the purpose of the Prover TOML + file, and how to prove and verify your program. +keywords: + [Nargo, Nargo project, Prover.toml, proof verification, private asset transfer] +sidebar_position: 1 +--- + +This section breaks down our hello world program from 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 + - 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. + +### 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) +- `expression_width` (optional) - Sets the default backend expression width. This field will override the default backend expression width specified by the Noir compiler (currently set to width 4). + +#### 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 the inputs to the Noir program (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 execute` is executed, nargo will execute the Noir program using the inputs specified in `Prover.toml`, aborting if it finds that these do not satisfy the constraints defined by `main`. In this example, `x` and `y` must satisfy the inequality constraint `assert(x != y)`. + +If an output name is specified such as `nargo execute foo`, the witness generated by this execution will be written to `./target/foo.gz`. This can then be used to generate a proof of the execution. + +#### 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 execution by using the `--prover-name` or `-p` flags. + +This command looks for proof inputs in the default **Prover.toml** and generates the witness and saves it at `./target/foo.gz`: + +```bash +nargo execute foo +``` + +This command looks for proof inputs in the custom **OtherProver.toml** and generates the witness and saves it at `./target/bar.gz`: + +```bash +nargo execute -p OtherProver bar +``` + +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.38.0/getting_started/quick_start.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/getting_started/quick_start.md new file mode 100644 index 00000000000..c693624eb82 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/getting_started/quick_start.md @@ -0,0 +1,126 @@ +--- +title: Quick Start +tags: [] +sidebar_position: 0 +--- + +## Installation + +### Noir + +The easiest way to develop with Noir is using Nargo the CLI tool. It provides you the ability to start new projects, compile, execute and test Noir programs from the terminal. + +You can use `noirup` the installation script to quickly install and update Nargo: + +```bash +curl -L noirup.dev | bash +noirup +``` + +Once installed, you can [set up shell completions for the `nargo` command](setting_up_shell_completions). + +### Proving backend + +After installing Noir, we install a proving backend to work with our Noir programs. + +Proving backends provide you the abilities to generate proofs, verify proofs, generate smart contracts and more for your Noir programs. + +Different proving backends provide different tools for working with Noir programs, here we will use the [Barretenberg proving backend](https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg) developed by Aztec Labs as an example. + +You can use the `bbup` installation script to quickly install and update BB, Barretenberg's CLI tool: + +You can find the full list of proving backends compatible with Noir in Awesome Noir. + +```bash +curl -L bbup.dev | bash +bbup +``` + +For the full list of proving backends compatible with Noir, visit [Awesome Noir](https://github.com/noir-lang/awesome-noir/?tab=readme-ov-file#proving-backends). + +## Nargo + +Nargo provides the ability to initiate and execute Noir projects. Let's initialize the traditional `hello_world`: + +```sh +nargo new hello_world +``` + +Two files will be created. + +- `src/main.nr` contains a simple boilerplate circuit +- `Nargo.toml` contains environmental options, such as name, author, dependencies, and others. + +Glancing at _main.nr_ , we can see that inputs in Noir are private by default, but can be labeled public using the keyword `pub`. This means that we will _assert_ that we know a value `x` which is different from `y` without revealing `x`: + +```rust +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +To learn more about private and public values, check the [Data Types](../noir/concepts/data_types/index.md) section. + +### Compiling and executing + +We can now use `nargo` to generate a _Prover.toml_ file, where our input values will be specified: + +```sh +cd hello_world +nargo check + +Let's feed some valid values into this file: + +```toml +x = "1" +y = "2" +``` + +We're now ready to compile and execute our Noir program. By default the `nargo execute` command will do both, and generate the `witness` that we need to feed to our proving backend: + +```sh +nargo execute +``` + +The witness corresponding to this execution will then be written to the file _./target/witness-name.gz_. + +The command also automatically compiles your Noir program if it was not already / was edited, which you may notice the compiled artifacts being written to the file _./target/hello_world.json_. + +With circuit compiled and witness generated, we're ready to prove. + +## Proving backend + +Different proving backends may provide different tools and commands to work with Noir programs. Here Barretenberg's `bb` CLI tool is used as an example: + +```sh +bb prove -b ./target/hello_world.json -w ./target/hello_world.gz -o ./target/proof +``` + +:::tip + +Naming can be confusing, specially as you pass them to the `bb` commands. If unsure, it won't hurt to delete the target folder and start anew to make sure you're using the most recent versions of the compiled circuit and witness. + +::: + +The proof is now generated in the `target` folder. To verify it we first need to compute the verification key from the compiled circuit, and use it to verify: + +```sh +bb write_vk -b ./target/hello_world.json -o ./target/vk +bb verify -k ./target/vk -p ./target/proof +``` + +:::info + +Notice that in order to verify a proof, the verifier knows nothing but the circuit, which is compiled and used to generate the verification key. This is obviously quite important: private inputs remain private. + +As for the public inputs, you may have noticed they haven't been specified. This behavior varies with each particular backend, but barretenberg typically attaches them to the proof. You can see them by parsing and splitting it. For example for if your public inputs are 32 bytes: + +```bash +head -c 32 ./target/proof | od -An -v -t x1 | tr -d $' \n' +``` + +::: + +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.38.0/getting_started/setting_up_shell_completions.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/getting_started/setting_up_shell_completions.md new file mode 100644 index 00000000000..0447321cbab --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/getting_started/setting_up_shell_completions.md @@ -0,0 +1,87 @@ +--- +title: Setting up shell completions +tags: [] +sidebar_position: 3 +--- + +The `nargo` binary provides a command to generate shell completions: + +```bash +nargo generate-completion-script [shell] +``` + +where `shell` must be one of `bash`, `elvish`, `fish`, `powershell`, and `zsh`. + +Below we explain how to install them in some popular shells. + +## Installing Zsh Completions + +If you have `oh-my-zsh` installed, you might already have a directory of automatically loading completion scripts — `.oh-my-zsh/completions`. +If not, first create it: + +```bash +mkdir -p ~/.oh-my-zsh/completions` +``` + +Then copy the completion script to that directory: + +```bash +nargo generate-completion-script zsh > ~/.oh-my-zsh/completions/_nargo +``` + +Without `oh-my-zsh`, you’ll need to add a path for completion scripts to your function path, and turn on completion script auto-loading. +First, add these lines to `~/.zshrc`: + +```bash +fpath=(~/.zsh/completions $fpath) +autoload -U compinit +compinit +``` + +Next, create a directory at `~/.zsh/completions`: + +```bash +mkdir -p ~/.zsh/completions +``` + +Then copy the completion script to that directory: + +```bash +nargo generate-completion-script zsh > ~/.zsh/completions/_nargo +``` + +## Installing Bash Completions + +If you have [bash-completion](https://github.com/scop/bash-completion) installed, you can just copy the completion script to the `/usr/local/etc/bash_completion.d` directory: + +```bash +nargo generate-completion-script bash > /usr/local/etc/bash_completion.d/nargo +``` + +Without `bash-completion`, you’ll need to source the completion script directly. +First create a directory such as `~/.bash_completions/`: + +```bash +mkdir ~/.bash_completions/ +``` + +Copy the completion script to that directory: + +```bash +nargo generate-completion-script bash > ~/.bash_completions/nargo.bash +``` + +Then add the following line to `~/.bash_profile` or `~/.bashrc`: + + +```bash +source ~/.bash_completions/nargo.bash +``` + +## Installing Fish Completions + +Copy the completion script to any path listed in the environment variable `$fish_completion_path`. For example, a typical location is `~/.config/fish/completions/nargo.fish`: + +```bash +nargo generate-completion-script fish > ~/.config/fish/completions/nargo.fish +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/_category_.json new file mode 100644 index 00000000000..23b560f610b --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/debugger/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/debugger/_category_.json new file mode 100644 index 00000000000..cc2cbb1c253 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugging", + "position": 5, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/debugger/debugging_with_the_repl.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/debugger/debugging_with_the_repl.md new file mode 100644 index 00000000000..09e5bae68ad --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/debugger/debugging_with_the_repl.md @@ -0,0 +1,164 @@ +--- +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.38.0/how_to/debugger/debugging_with_vs_code.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/debugger/debugging_with_vs_code.md new file mode 100644 index 00000000000..a5858c1a5eb --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/debugger/debugging_with_vs_code.md @@ -0,0 +1,68 @@ +--- +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.38.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/how-to-oracles.md new file mode 100644 index 00000000000..08ce6ee5476 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/how-to-oracles.md @@ -0,0 +1,275 @@ +--- +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.). + +## 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 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) { + 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); +} + +#[test] +fn test() { + let input = [4, 16]; + main(input); +} +``` + +:::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("resolve_foreign_call", async (params) => { + if (params[0].function !== "getSqrt") { + throw Error("Unexpected foreign call") + }; + const values = params[0].inputs[0].map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [values] }; +}); +``` + +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 +export type ForeignCallSingle = string; + +export type ForeignCallArray = string[]; + +export type ForeignCallResult = { + values: (ForeignCallSingle | ForeignCallArray)[]; +}; +``` + +:::info Multidimensional Arrays + +If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in JSON as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the Noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. + +::: + +## Step 3 - Usage with Nargo + +Using the [`nargo` CLI tool](../reference/nargo_commands.md), you can use oracles in the `nargo test` and `nargo execute` 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.execute(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`? 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) => { + const inputs = input[0].map((i) => i.toString("hex")) + // 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("resolve_foreign_call", [ + { + function: name, + inputs: [inputs] + }, + ]); + return [oracleReturn.values[0]]; +}; + +// the rest of your NoirJS code +const input = { input: [4, 16] }; +const { witness } = await noir.execute(input, 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. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/how-to-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/how-to-recursion.md new file mode 100644 index 00000000000..fac79a9cf49 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/how-to-recursion.md @@ -0,0 +1,172 @@ +--- +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 `bb.js`. +keywords: + [ + "NoirJS", + "EVM blockchain", + "smart contracts", + "recursion", + "solidity verifiers", + "Barretenberg backend", + "noir_js", + "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.mdx), 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. + +::: + +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 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 + +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) +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), + recursive: new Noir(circuits.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 { witness: recursiveWitness } = await noir_programs.recursive.execute(recursiveInputs) +const recursiveProof = await backends.recursive.generateProof(recursiveWitness); +``` + +::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/how-to-solidity-verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/how-to-solidity-verifier.md new file mode 100644 index 00000000000..2cc0f8e57ce --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/how-to-solidity-verifier.md @@ -0,0 +1,259 @@ +--- +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/quick_start.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 straightforward step. Just run: + +```sh +nargo compile +``` + +This will compile your source code into a Noir build artifact to be stored in the `./target` directory, you can then generate the smart contract using the commands: + +```sh +# Here we pass the path to the newly generated Noir artifact. +bb write_vk -b ./target/.json +bb contract +``` + +replacing `` with the name of your Noir project. A new `contract` folder would then be generated in your project directory, containing the Solidity +file `contract.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. + +You can find more information about `bb` and the default Noir proving backend on [this page](../getting_started/quick_start.md#proving-backend). + +:::info + +It is possible to generate verifier contracts of Noir programs for other smart contract platforms as long as the proving backend supplies an implementation. + +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 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: + +- 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 that 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/quick_start.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/quick_start.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. +NUM_PUBLIC_INPUTS=1 +PUBLIC_INPUT_BYTES=32*NUM_PUBLIC_INPUTS +HEX_PUBLIC_INPUTS=$(head -c $PUBLIC_INPUT_BYTES ./proof | od -An -v -t x1 | tr -d $' \n') +HEX_PROOF=$(tail -c +$(($PUBLIC_INPUT_BYTES + 1)) ./proof | od -An -v -t x1 | tr -d $' \n') + +echo "Public inputs:" +echo $HEX_PUBLIC_INPUTS + +echo "Proof:" +echo "0x$HEX_PROOF" +``` + +Remix expects that the public inputs will be split into an array of `bytes32` values so `HEX_PUBLIC_INPUTS` needs to be split up into 32 byte chunks which are prefixed with `0x` accordingly. + +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. + +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 + +Noir proof verification requires the ecMul, ecAdd and ecPairing precompiles. 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. You can find an incomplete list of which EVM chains support these precompiles [here](https://www.evmdiff.com/features?feature=precompiles). + +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 +- 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. + +## 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.38.0/how_to/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/merkle-proof.mdx new file mode 100644 index 00000000000..0a128adb2de --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/merkle-proof.mdx @@ -0,0 +1,48 @@ +--- +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 + +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.38.0/how_to/using-devcontainers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/using-devcontainers.mdx new file mode 100644 index 00000000000..727ec6ca667 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/how_to/using-devcontainers.mdx @@ -0,0 +1,110 @@ +--- +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.38.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/index.mdx new file mode 100644 index 00000000000..a6bd306f91d --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/index.mdx @@ -0,0 +1,67 @@ +--- +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 an open-source Domain-Specific Language for safe and seamless construction of privacy-preserving Zero-Knowledge programs, requiring no previous knowledge on the underlying mathematics or cryptography. + +ZK programs are programs that can generate short proofs of statements without revealing all inputs to the statements. You can read more about Zero-Knowledge Proofs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). + +## What's new about Noir? + +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.38.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/migration_notes.md new file mode 100644 index 00000000000..6bd740024e5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/migration_notes.md @@ -0,0 +1,105 @@ +--- +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.38.0/noir/concepts/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/_category_.json new file mode 100644 index 00000000000..7da08f8a8c5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/_category_.json @@ -0,0 +1,6 @@ +{ + "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.38.0/noir/concepts/assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/assert.md new file mode 100644 index 00000000000..2132de42072 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/assert.md @@ -0,0 +1,78 @@ +--- +title: Assert Function +description: + 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 +--- + +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); +``` + +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.38.0/noir/concepts/comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/comments.md new file mode 100644 index 00000000000..b51a85f5c94 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/comments.md @@ -0,0 +1,33 @@ +--- +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.38.0/noir/concepts/comptime.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/comptime.md new file mode 100644 index 00000000000..2ceb030c7e1 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/comptime.md @@ -0,0 +1,445 @@ +--- +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: 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; + } + } +``` +> Source code: noir_stdlib/src/meta/mod.nr#L120-L140 + + +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#L142-L164 + + +### 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#L166-L177 + + +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#L179-L189 + + +--- + +## 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. You can see more in the standard library [Metaprogramming section](../standard_library/meta). + +- `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. + +### `#[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 + +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. +pub type DeriveFunction = fn(StructDefinition) -> Quoted; + +// We'll keep a global HANDLERS map to keep track of the derive handler for each trait +comptime mut global HANDLERS: UHashMap> = + UHashMap::default(); + +// 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#L31-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#L191-L249 + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/control_flow.md new file mode 100644 index 00000000000..b365bb22728 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/control_flow.md @@ -0,0 +1,79 @@ +--- +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 +} +``` + +Alternatively, `start..=end` can be used for a range that is inclusive on both ends. + +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.38.0/noir/concepts/data_bus.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_bus.mdx new file mode 100644 index 00000000000..e55e58622ce --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_bus.mdx @@ -0,0 +1,23 @@ +--- +title: Data Bus +sidebar_position: 13 +--- +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()` +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.38.0/noir/concepts/data_types/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/arrays.md new file mode 100644 index 00000000000..289145a8c4d --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/arrays.md @@ -0,0 +1,276 @@ +--- +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. 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] +``` + +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 the starting element. + +Requires `self` to be non-empty. + +```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); +} +``` + +### 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.38.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/booleans.md new file mode 100644 index 00000000000..2507af710e7 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/booleans.md @@ -0,0 +1,28 @@ +--- +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; +} +``` + +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.38.0/noir/concepts/data_types/fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/fields.md new file mode 100644 index 00000000000..b9b56f7ecc3 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/fields.md @@ -0,0 +1,246 @@ +--- +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#L276-L282 + + + +### 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#L267-L273 + + + +### 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] { +``` +> Source code: noir_stdlib/src/field/mod.nr#L61-L63 + + +example: + +```rust title="to_le_bytes_example" showLineNumbers +fn test_to_le_bytes() { + let field = 2; + let bytes: [u8; 8] = field.to_le_bytes(); + assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]); + assert_eq(Field::from_le_bytes::<8>(bytes), field); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L295-L302 + + +### 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] { +``` +> Source code: noir_stdlib/src/field/mod.nr#L94-L96 + + +example: + +```rust title="to_be_bytes_example" showLineNumbers +fn test_to_be_bytes() { + let field = 2; + let bytes: [u8; 8] = field.to_be_bytes(); + assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]); + assert_eq(Field::from_be_bytes::<8>(bytes), field); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L285-L292 + + + +### 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] { + // Brillig does not need an immediate radix + if !crate::runtime::is_unconstrained() { + crate::assert_constant(radix); + } + self.__to_le_radix(radix) + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L118-L126 + + + +example: + +```rust title="to_le_radix_example" showLineNumbers +fn test_to_le_radix() { + let field = 2; + let bytes: [u8; 8] = field.to_le_radix(256); + assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]); + assert_eq(Field::from_le_bytes::<8>(bytes), field); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L315-L322 + + + +### 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] { + // Brillig does not need an immediate radix + if !crate::runtime::is_unconstrained() { + crate::assert_constant(radix); + } + self.__to_be_radix(radix) + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L128-L136 + + +example: + +```rust title="to_be_radix_example" showLineNumbers +fn test_to_be_radix() { + let field = 2; + let bytes: [u8; 8] = field.to_be_radix(256); + assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]); + assert_eq(Field::from_be_bytes::<8>(bytes), field); + } +``` +> Source code: noir_stdlib/src/field/mod.nr#L305-L312 + + + +### 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) { +``` +> Source code: noir_stdlib/src/field/mod.nr#L10-L12 + + +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.38.0/noir/concepts/data_types/function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/function_types.md new file mode 100644 index 00000000000..f6121af17e2 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/function_types.md @@ -0,0 +1,26 @@ +--- +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.38.0/noir/concepts/data_types/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/index.md new file mode 100644 index 00000000000..0f2db2b2d75 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/index.md @@ -0,0 +1,126 @@ +--- +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 +``` + +By default, like functions, type aliases are private to the module they exist in. You can use `pub` +to make the type alias public or `pub(crate)` to make it public to just its crate: + +```rust +// This type alias is now public +pub type Id = u8; +``` + +## Wildcard Type +Noir can usually infer the type of the variable from the context, so specifying the type of a variable is only required when it cannot be inferred. However, specifying a complex type can be tedious, especially when it has multiple generic arguments. Often some of the generic types can be inferred from the context, and Noir only needs a hint to properly infer the other types. We can partially specify a variable's type by using `_` as a marker, indicating where we still want the compiler to infer the type. + +```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.38.0/noir/concepts/data_types/integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/integers.md new file mode 100644 index 00000000000..a1d59bf3166 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/integers.md @@ -0,0 +1,156 @@ +--- +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 execute +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 + +fn main(x: u8, y: u8) -> pub u8 { + std::wrapping_add(x, y) +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/references.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/references.md new file mode 100644 index 00000000000..a5293d11cfb --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/references.md @@ -0,0 +1,23 @@ +--- +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.38.0/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/slices.mdx new file mode 100644 index 00000000000..cfee564a302 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/slices.mdx @@ -0,0 +1,358 @@ +--- +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 +fn main() -> pub u32 { + let mut slice: [Field] = &[0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +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, +`&[..]` 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]); +} +``` + +### 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.38.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/strings.md new file mode 100644 index 00000000000..1fdee42425e --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/strings.md @@ -0,0 +1,79 @@ +--- +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 + +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.38.0/noir/concepts/data_types/structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/structs.md new file mode 100644 index 00000000000..29951ae843a --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/structs.md @@ -0,0 +1,96 @@ +--- +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. + +### Visibility + +By default, like functions, structs are private to the module they 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, +} +``` + +The same applies to struct fields: by default they are private to the module they exist in, +but they can be made `pub` or `pub(crate)`: + +```rust +// This struct is now public +pub struct Animal { + hands: Field, // private to its module + pub(crate) legs: Field, // accessible from the entire crate + pub eyes: u8, // accessible from anywhere +} +``` \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/tuples.md new file mode 100644 index 00000000000..2ec5c9c4113 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/data_types/tuples.md @@ -0,0 +1,48 @@ +--- +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.38.0/noir/concepts/functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/functions.md new file mode 100644 index 00000000000..f656cdfd97a --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/functions.md @@ -0,0 +1,226 @@ +--- +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.38.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/generics.md new file mode 100644 index 00000000000..c180a0ce7e6 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/generics.md @@ -0,0 +1,251 @@ +--- +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 +} +``` + +## 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 +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. + +## 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 +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.38.0/noir/concepts/globals.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/globals.md new file mode 100644 index 00000000000..6b8314399a2 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/globals.md @@ -0,0 +1,82 @@ +--- +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: u32 = 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. + +### Visibility + +By default, like functions, globals are private to the module they exist in. You can use `pub` +to make the global public or `pub(crate)` to make it public to just its crate: + +```rust +// This global is now public +pub global N = 5; +``` \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/lambdas.md new file mode 100644 index 00000000000..be3c7e0b5ca --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/lambdas.md @@ -0,0 +1,81 @@ +--- +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.38.0/noir/concepts/mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/mutability.md new file mode 100644 index 00000000000..fdeef6a87c5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/mutability.md @@ -0,0 +1,121 @@ +--- +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.38.0/noir/concepts/ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/ops.md new file mode 100644 index 00000000000..c35c36c38a9 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/ops.md @@ -0,0 +1,98 @@ +--- +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.38.0/noir/concepts/oracles.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/oracles.mdx new file mode 100644 index 00000000000..77a2ac1550a --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/oracles.mdx @@ -0,0 +1,29 @@ +--- +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 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +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.38.0/noir/concepts/shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/shadowing.md new file mode 100644 index 00000000000..5ce6130d201 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/shadowing.md @@ -0,0 +1,44 @@ +--- +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.38.0/noir/concepts/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/traits.md new file mode 100644 index 00000000000..9da00a77587 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/traits.md @@ -0,0 +1,501 @@ +--- +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 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; 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 { + 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 + } +} +``` + +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 +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); +} +``` + +### 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 +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: some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: 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. + +### Trait Inheritance + +Sometimes, you might need one trait to use another trait’s functionality (like "inheritance" in some other languages). In this case, you can specify this relationship by listing any child traits after the parent trait's name and a colon. Now, whenever the parent trait is implemented it will require the child traits to be implemented as well. A parent trait is also called a "super trait." + +```rust +trait Person { + fn name(self) -> String; +} + +// Person is a supertrait of Student. +// Implementing Student requires you to also impl Person. +trait Student: Person { + fn university(self) -> String; +} + +trait Programmer { + fn fav_language(self) -> String; +} + +// CompSciStudent (computer science student) is a subtrait of both Programmer +// and Student. Implementing CompSciStudent requires you to impl both supertraits. +trait CompSciStudent: Programmer + Student { + fn git_username(self) -> String; +} +``` + +### Visibility + +By default, like functions, traits are private to the module they 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/versioned_docs/version-v0.38.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/unconstrained.md new file mode 100644 index 00000000000..b5221b8d2dd --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/concepts/unconstrained.md @@ -0,0 +1,104 @@ +--- +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 = unsafe { + 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). + +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 + +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.38.0/noir/modules_packages_crates/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/modules_packages_crates/_category_.json new file mode 100644 index 00000000000..1debcfe7675 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/modules_packages_crates/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Modules, Packages and Crates", + "position": 2, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..95ee9f52ab2 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/modules_packages_crates/crates_and_packages.md @@ -0,0 +1,43 @@ +--- +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.38.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..24e02de08fe --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/modules_packages_crates/dependencies.md @@ -0,0 +1,124 @@ +--- +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 ecrecover; +use lib_a; +``` + +You can also import only the specific parts of dependency that you want to use, like so: + +```rust +use std::hash::sha256; +use 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 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 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.38.0/noir/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/modules_packages_crates/modules.md new file mode 100644 index 00000000000..14aa1f0579a --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/modules_packages_crates/modules.md @@ -0,0 +1,221 @@ +--- +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 + +``` + +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. + +``` +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 +``` + +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`. + +### Visibility + +By default, like functions, modules are private to the module (or crate) they exist in. You can use `pub` +to make the module public or `pub(crate)` to make it public to just its crate: + +```rust +// This module is now public and can be seen by other crates. +pub mod foo; +``` \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..513497f12bf --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/modules_packages_crates/workspaces.md @@ -0,0 +1,42 @@ +--- +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.38.0/noir/standard_library/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/_category_.json new file mode 100644 index 00000000000..af04c0933fd --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Standard Library", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/bigint.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/bigint.md new file mode 100644 index 00000000000..05c3011634f --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/bigint.md @@ -0,0 +1,127 @@ +--- +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. + +:::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: + +- 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 +pub struct BigInt { + pointer: u32, + modulus: u32, +} +``` +> Source code: noir_stdlib/src/bigint.nr#L28-L33 + + +## 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#L74-L82 + + +## 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.38.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/black_box_fns.md new file mode 100644 index 00000000000..d6079ab182c --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/black_box_fns.md @@ -0,0 +1,32 @@ +--- +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.mdx) + +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.38.0/noir/standard_library/bn254.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/bn254.md new file mode 100644 index 00000000000..3294f005dbb --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/bn254.md @@ -0,0 +1,46 @@ +--- +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.38.0/noir/standard_library/containers/boundedvec.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/containers/boundedvec.md new file mode 100644 index 00000000000..509b214bf3a --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/containers/boundedvec.md @@ -0,0 +1,419 @@ +--- +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 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 `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(); + 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(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(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 + + +### set + +```rust +pub fn set(&mut self: Self, index: u64, value: T) { +``` + +Writes an element to 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); + assert(first != 42); + v.set(0, 42); + let new_first = v.get(0); + assert(new_first == 42); +} +``` + +### set_unchecked + +```rust +pub fn set_unchecked(&mut self: Self, index: u64, value: T) -> T { +``` + +Writes an element to 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="set_unchecked_example" showLineNumbers +fn set_unchecked_example() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([1, 2]); + + // Here we're safely writing within the valid range of `vec` + // `vec` now has the value [42, 2] + vec.set_unchecked(0, 42); + + // We can then safely read this value back out of `vec`. + // Notice that we use the checked version of `get` which would prevent reading unsafe values. + assert_eq(vec.get(0), 42); + + // We've now written past the end of `vec`. + // As this index is still within the maximum potential length of `v`, + // it won't cause a constraint failure. + vec.set_unchecked(2, 42); + println(vec); + + // This will write past the end of the maximum potential length of `vec`, + // it will then trigger a constraint failure. + vec.set_unchecked(5, 42); + println(vec); +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L67-L91 + + + +### 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#L95-L103 + + +### 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#L108-L120 + + +### 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#L125-L140 + + +### 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#L145-L151 + + +### 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#L156-L163 + + +### 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#L168-L175 + + +### 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#L180-L189 + + +### 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]) +``` + +### map + +```rust +pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec +``` + +Creates a new vector of equal size by calling a closure on each element in this vector. + +Example: + +```rust title="bounded-vec-map-example" showLineNumbers +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#L495-L498 + + +### 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#L256-L262 + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/containers/hashmap.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/containers/hashmap.md new file mode 100644 index 00000000000..395cc312705 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/containers/hashmap.md @@ -0,0 +1,587 @@ +--- +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`. + +Example: + +```rust +// Create a mapping from Fields to u32s with a maximum length of 12 +// using a poseidon2 hasher +use 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, +{ + /// 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#L681-L696 + + +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#L207-L210 + + +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#L201-L203 + + +### 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#L103-L108 + + +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#L211-L216 + + +### 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#L465-L472 + + +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#L296-L304 + + +### 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#L507-L514 + + +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#L217-L221 + + +### 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#L563-L570 + + +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#L224-L231 + + +### is_empty + +```rust title="is_empty" showLineNumbers +pub fn is_empty(self) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L167-L169 + + +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#L232-L240 + + +### len + +```rust title="len" showLineNumbers +pub fn len(self) -> u32 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L424-L426 + + +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#L241-L256 + + +### capacity + +```rust title="capacity" showLineNumbers +pub fn capacity(_self: Self) -> u32 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L446-L448 + + +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-L262 + + +### clear + +```rust title="clear" showLineNumbers +pub fn clear(&mut self) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L123-L125 + + +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#L143-L150 + + +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#L268-L275 + + +### entries + +```rust title="entries" showLineNumbers +pub fn entries(self) -> BoundedVec<(K, V), N> { +``` +> Source code: noir_stdlib/src/collections/map.nr#L191-L193 + + +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#L307-L318 + + +### keys + +```rust title="keys" showLineNumbers +pub fn keys(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L227-L229 + + +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#L319-L329 + + +### values + +```rust title="values" showLineNumbers +pub fn values(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L262-L264 + + +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#L330-L339 + + +### 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#L297-L304 + + +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#L343-L346 + + +### 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#L335-L342 + + +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#L347-L350 + + +### 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#L367-L369 + + +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#L351-L354 + + +### retain + +```rust title="retain" showLineNumbers +pub fn retain(&mut self, f: fn(K, V) -> bool) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L388-L390 + + +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#L279-L281 + + +## Trait Implementations + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + 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#L681-L696 + + +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#L207-L210 + + +### eq + +```rust title="eq" showLineNumbers +impl Eq for HashMap +where + K: Eq + Hash, + V: Eq, + B: BuildHasher, + 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#L629-L654 + + +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#L282-L293 + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/containers/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/containers/index.md new file mode 100644 index 00000000000..ea84c6d5c21 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/containers/index.md @@ -0,0 +1,5 @@ +--- +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.38.0/noir/standard_library/containers/vec.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/containers/vec.mdx new file mode 100644 index 00000000000..475011922f8 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/containers/vec.mdx @@ -0,0 +1,170 @@ +--- +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); +``` + +### set + +```rust +pub fn set(&mut self: Self, index: u64, value: T) { +``` + +Writes an element to the vector at the given index, starting from zero. + +Panics if the index points beyond the vector's end. + +Example: + +```rust +let vector: Vec = Vec::from_slice(&[10, 20, 30]); +assert(vector.get(1) == 20); +vector.set(1, 42); +assert(vector.get(1) == 42); +``` + +### 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.38.0/noir/standard_library/cryptographic_primitives/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 00000000000..5d694210bbf --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/ciphers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/ciphers.mdx new file mode 100644 index 00000000000..d6a5e1a79eb --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/ciphers.mdx @@ -0,0 +1,32 @@ +--- +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'; + +## 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.38.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/ec_primitives.md new file mode 100644 index 00000000000..f262d8160d6 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -0,0 +1,102 @@ +--- +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/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 +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/master/noir_stdlib/src/ec/mod.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 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.38.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..8d96027b42c --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -0,0 +1,98 @@ +--- +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'; + +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.38.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/eddsa.mdx new file mode 100644 index 00000000000..b283de693c8 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/eddsa.mdx @@ -0,0 +1,37 @@ +--- +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'; + +## 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` function by passing a type implementing the Hasher trait with the turbofish operator. +For instance, if you want to use Poseidon2 instead, you can do the following: +```rust +use std::hash::poseidon2::Poseidon2Hasher; + +eddsa_verify::(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg); +``` + + + +## 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.38.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx new file mode 100644 index 00000000000..482a36932b9 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx @@ -0,0 +1,95 @@ +--- +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'; + +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: [EmbeddedCurvePoint; N], + scalars: [EmbeddedCurveScalar; N], +) -> EmbeddedCurvePoint +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L103-L108 + + +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: EmbeddedCurveScalar) -> EmbeddedCurvePoint +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L120-L122 + + +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 +pub fn embedded_curve_add( + point1: EmbeddedCurvePoint, + point2: EmbeddedCurvePoint, +) -> EmbeddedCurvePoint { +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L136-L141 + + +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.38.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/hashes.mdx new file mode 100644 index 00000000000..541a1971561 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -0,0 +1,227 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s and pedersen +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, hash] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox'; + +## 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]) -> HASH +``` +> Source code: noir_stdlib/src/hash/sha256.nr#L47-L49 + + +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#L15-L17 + + +```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/mod.nr#L18-L20 + + +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/mod.nr#L24-L26 + + +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/mod.nr#L49-L51 + + +example: + +```rust title="pedersen-hash" showLineNumbers +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-L6 + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. + +```rust title="pedersen_commitment" showLineNumbers +pub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint { +``` +> Source code: noir_stdlib/src/hash/mod.nr#L29-L31 + + +example: + +```rust title="pedersen-commitment" showLineNumbers +fn main(x: Field, y: Field, expected_commitment: std::embedded_curve_ops::EmbeddedCurvePoint) { + 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-L7 + + + + +## 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/mod.nr#L116-L118 + + +example: + +```rust title="keccak256" showLineNumbers +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-L20 + + + + +## 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 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 + + +## 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); +``` + +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 + + +## 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.38.0/noir/standard_library/cryptographic_primitives/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/index.md new file mode 100644 index 00000000000..650f30165d5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/index.md @@ -0,0 +1,14 @@ +--- +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.38.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/schnorr.mdx new file mode 100644 index 00000000000..030452645c5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/cryptographic_primitives/schnorr.mdx @@ -0,0 +1,64 @@ +--- +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'; + +## 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#L4-L11 + + +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#L15-L22 + + + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/fmtstr.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/fmtstr.md new file mode 100644 index 00000000000..19809d60261 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.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 +pub 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.38.0/noir/standard_library/is_unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/is_unconstrained.md new file mode 100644 index 00000000000..51bb1bda8f1 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/is_unconstrained.md @@ -0,0 +1,69 @@ +--- +title: Is Unconstrained Function +description: + The is_unconstrained function returns wether the context at that point of the program is unconstrained or not. +keywords: + [ + unconstrained + ] +--- + +It's very common for functions in circuits to take unconstrained hints of an expensive computation and then verify it. This is done by running the hint in an unconstrained context and then verifying the result in a constrained context. + +When a function is marked as unconstrained, any subsequent functions that it calls will also be run in an unconstrained context. However, if we are implementing a library function, other users might call it within an unconstrained context or a constrained one. Generally, in an unconstrained context we prefer just computing the result instead of taking a hint of it and verifying it, since that'd mean doing the same computation twice: + +```rust + +fn my_expensive_computation(){ + ... +} + +unconstrained fn my_expensive_computation_hint(){ + my_expensive_computation() +} + +pub fn external_interface(){ + my_expensive_computation_hint(); + // verify my_expensive_computation: If external_interface is called from unconstrained, this is redundant + ... +} + +``` + +In order to improve the performance in an unconstrained context you can use the function at `std::runtime::is_unconstrained() -> bool`: + + +```rust +use dep::std::runtime::is_unconstrained; + +fn my_expensive_computation(){ + ... +} + +unconstrained fn my_expensive_computation_hint(){ + my_expensive_computation() +} + +pub fn external_interface(){ + if is_unconstrained() { + my_expensive_computation(); + } else { + my_expensive_computation_hint(); + // verify my_expensive_computation + ... + } +} + +``` + +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.38.0/noir/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/logging.md new file mode 100644 index 00000000000..db75ef9f86f --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/logging.md @@ -0,0 +1,78 @@ +--- +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.38.0/noir/standard_library/mem.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/mem.md new file mode 100644 index 00000000000..95d36ac2a72 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/mem.md @@ -0,0 +1,52 @@ +--- +title: Memory Module +description: + This module contains functions which manipulate memory in a low-level way +keywords: + [ + mem, memory, zeroed, transmute, checked_transmute + ] +--- + +# `std::mem::zeroed` + +```rust +fn zeroed() -> T +``` + +Returns 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. + +This function currently supports the following types: + +- Field +- Bool +- Uint +- Array +- Slice +- String +- Tuple +- Functions + +Using it on other types could result in unexpected behavior. + +# `std::mem::checked_transmute` + +```rust +fn checked_transmute(value: T) -> U +``` + +Transmutes a value of one type into the same value but with a new type `U`. + +This function is safe to use since both types are asserted to be equal later during compilation after the concrete values for generic types become known. +This function is useful for cases where the compiler may fails a type check that is expected to pass where +a user knows the two types to be equal. For example, when using arithmetic generics there are cases the compiler +does not see as equal, such as `[Field; N*(A + B)]` and `[Field; N*A + N*B]`, which users may know to be equal. +In these cases, `checked_transmute` can be used to cast the value to the desired type while also preserving safety +by checking this equality once `N`, `A`, `B` are fully resolved. + +Note that since this safety check is performed after type checking rather than during, no error is issued if the function +containing `checked_transmute` is never called. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/merkle_trees.md new file mode 100644 index 00000000000..6a9ebf72ada --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/merkle_trees.md @@ -0,0 +1,58 @@ +--- +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.38.0/noir/standard_library/meta/ctstring.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/ctstring.md new file mode 100644 index 00000000000..b76f873ca03 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/ctstring.md @@ -0,0 +1,100 @@ +--- +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 + +```rust title="as-ctstring" showLineNumbers +pub trait AsCtString { + comptime fn as_ctstring(self) -> CtString; +} +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L43-L47 + + +Converts an object into a compile-time string. + +Implementations: + +```rust +impl AsCtString for str { ... } +impl AsCtString for fmtstr { ... } +``` + +## Methods + +### new + +```rust title="new" showLineNumbers +pub comptime fn new() -> Self { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L4-L6 + + +Creates an empty `CtString`. + +### append_str + +```rust title="append_str" showLineNumbers +pub comptime fn append_str(self, s: str) -> Self { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L11-L13 + + +Returns a new CtString with the given str appended onto the end. + +### append_fmtstr + +```rust title="append_fmtstr" showLineNumbers +pub comptime fn append_fmtstr(self, s: fmtstr) -> Self { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L17-L19 + + +Returns a new CtString with the given fmtstr appended onto the end. + +### as_quoted_str + +```rust title="as_quoted_str" showLineNumbers +pub comptime fn as_quoted_str(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L26-L28 + + +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: + +```rust title="as_quoted_str_example" showLineNumbers +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()); +``` +> Source code: noir_stdlib/src/meta/ctstring.nr#L92-L97 + + +## Trait Implementations + +```rust +impl Eq for CtString +impl Hash for CtString +impl Append for CtString +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/expr.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/expr.md new file mode 100644 index 00000000000..b6d395c6700 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/expr.md @@ -0,0 +1,380 @@ +--- +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 +pub comptime fn as_array(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L10-L12 + + +If this expression is an array, this returns a slice of each element in the array. + +### as_assert + +```rust title="as_assert" showLineNumbers +pub comptime fn as_assert(self) -> Option<(Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L16-L18 + + +If this expression is an assert, this returns the assert expression and the optional message. + +### as_assert_eq + +```rust title="as_assert_eq" showLineNumbers +pub comptime fn as_assert_eq(self) -> Option<(Expr, Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L23-L25 + + +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 +pub comptime fn as_assign(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L30-L32 + + +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 +pub comptime fn as_binary_op(self) -> Option<(Expr, BinaryOp, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L37-L39 + + +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 +pub comptime fn as_block(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L44-L46 + + +If this expression is a block `{ stmt1; stmt2; ...; stmtN }`, return +a slice containing each statement. + +### as_bool + +```rust title="as_bool" showLineNumbers +pub comptime fn as_bool(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L50-L52 + + +If this expression is a boolean literal, return that literal. + +### as_cast + +```rust title="as_cast" showLineNumbers +#[builtin(expr_as_cast)] + pub comptime fn as_cast(self) -> Option<(Expr, UnresolvedType)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L56-L59 + + +If this expression is a cast expression (`expr as type`), returns the casted +expression and the type to cast to. + +### as_comptime + +```rust title="as_comptime" showLineNumbers +pub comptime fn as_comptime(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L64-L66 + + +If this expression is a `comptime { stmt1; stmt2; ...; stmtN }` block, +return each statement in the block. + +### as_constructor + +```rust title="as_constructor" showLineNumbers +pub comptime fn as_constructor(self) -> Option<(UnresolvedType, [(Quoted, Expr)])> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L71-L73 + + +If this expression is a constructor `Type { field1: expr1, ..., fieldN: exprN }`, +return the type and the fields. + +### as_for + +```rust title="as_for" showLineNumbers +pub comptime fn as_for(self) -> Option<(Quoted, Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L78-L80 + + +If this expression is a for statement over a single expression, return the identifier, +the expression and the for loop body. + +### as_for_range + +```rust title="as_for" showLineNumbers +pub comptime fn as_for(self) -> Option<(Quoted, Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L78-L80 + + +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 + +```rust title="as_function_call" showLineNumbers +pub comptime fn as_function_call(self) -> Option<(Expr, [Expr])> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L92-L94 + + +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 +pub comptime fn as_if(self) -> Option<(Expr, Expr, Option)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L100-L102 + + +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 +pub comptime fn as_index(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L107-L109 + + +If this expression is an index into an array `array[index]`, return the +array and the index. + +### as_integer + +```rust title="as_integer" showLineNumbers +pub comptime fn as_integer(self) -> Option<(Field, bool)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L114-L116 + + +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 + +```rust title="as_lambda" showLineNumbers +pub comptime fn as_lambda( + self, + ) -> Option<([(Expr, Option)], Option, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L120-L124 + + +If this expression is a lambda, returns the parameters, return type and body. + +### as_let + +```rust title="as_let" showLineNumbers +pub comptime fn as_let(self) -> Option<(Expr, Option, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L129-L131 + + +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 +pub comptime fn as_member_access(self) -> Option<(Expr, Quoted)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L136-L138 + + +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 +pub comptime fn as_method_call(self) -> Option<(Expr, Quoted, [UnresolvedType], [Expr])> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L143-L145 + + +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 +pub comptime fn as_repeated_element_array(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L150-L152 + + +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 +pub comptime fn as_repeated_element_slice(self) -> Option<(Expr, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L157-L159 + + +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 +pub comptime fn as_slice(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L164-L166 + + +If this expression is a slice literal `&[elem1, ..., elemN]`, +return each element of the slice. + +### as_tuple + +```rust title="as_tuple" showLineNumbers +pub comptime fn as_tuple(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L171-L173 + + +If this expression is a tuple `(field1, ..., fieldN)`, +return each element of the tuple. + +### as_unary_op + +```rust title="as_unary_op" showLineNumbers +pub comptime fn as_unary_op(self) -> Option<(UnaryOp, Expr)> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L178-L180 + + +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 +pub comptime fn as_unsafe(self) -> Option<[Expr]> {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L185-L187 + + +If this expression is an `unsafe { stmt1; ...; stmtN }` block, +return each statement inside in a slice. + +### has_semicolon + +```rust title="has_semicolon" showLineNumbers +pub comptime fn has_semicolon(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L206-L208 + + +`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 +pub comptime fn is_break(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L212-L214 + + +`true` if this expression is `break`. + +### is_continue + +```rust title="is_continue" showLineNumbers +pub comptime fn is_continue(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L218-L220 + + +`true` if this expression is `continue`. + +### modify + +```rust title="modify" showLineNumbers +pub comptime fn modify(self, f: fn[Env](Expr) -> Option) -> Expr { +``` +> Source code: noir_stdlib/src/meta/expr.nr#L229-L231 + + +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 +pub comptime fn quoted(self) -> Quoted { +``` +> Source code: noir_stdlib/src/meta/expr.nr#L266-L268 + + +Returns this expression as a `Quoted` value. It's the same as `quote { $self }`. + +### resolve + +```rust title="resolve" showLineNumbers +pub comptime fn resolve(self, in_function: Option) -> TypedExpr {} +``` +> Source code: noir_stdlib/src/meta/expr.nr#L282-L284 + + +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.38.0/noir/standard_library/meta/function_def.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/function_def.md new file mode 100644 index 00000000000..b7f2ebdb889 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.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 +pub 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 +pub 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 +pub 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 +pub 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 +pub 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 +pub 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 +pub 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 +pub 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 +pub 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 +pub 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 +pub 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 +pub 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 +pub comptime fn set_unconstrained(self, value: bool) {} +``` +> Source code: noir_stdlib/src/meta/function_def.nr#L66-L68 + + +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.38.0/noir/standard_library/meta/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/index.md new file mode 100644 index 00000000000..14544c07442 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/index.md @@ -0,0 +1,224 @@ +--- +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#L27-L29 + + +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#L19-L21 + + +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#L48-L51 + + +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-L30 + + +### 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#L137-L151 + + +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#L216-L231 + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/module.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/module.md new file mode 100644 index 00000000000..f47231972b7 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.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 +pub 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 +pub 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 +pub 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 +pub 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 +pub 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 +pub 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.38.0/noir/standard_library/meta/op.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/op.md new file mode 100644 index 00000000000..03ea49ad8ec --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.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#L24-L26 + + +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#L30-L32 + + +`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#L36-L38 + + +`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#L42-L44 + + +`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#L48-L50 + + +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#L86-L88 + + +`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#L92-L94 + + +`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#L98-L100 + + +`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#L104-L106 + + +`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#L176-L178 + + +`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#L110-L112 + + +`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#L116-L118 + + +`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#L122-L124 + + +`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#L128-L130 + + +`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#L134-L136 + + +`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#L140-L142 + + +`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#L146-L148 + + +`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#L152-L154 + + +`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#L164-L166 + + +`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#L164-L166 + + +`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#L182-L184 + + +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.38.0/noir/standard_library/meta/quoted.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/quoted.md new file mode 100644 index 00000000000..d7acf23bc07 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/quoted.md @@ -0,0 +1,141 @@ +--- +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 +pub 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#L360-L371 + + +### as_module + +```rust title="as_module" showLineNumbers +pub 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 { + pub 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#L115-L127 + + +### as_trait_constraint + +```rust title="as_trait_constraint" showLineNumbers +pub 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 +pub 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#L160-L173 + + +### as_type + +```rust title="as_type" showLineNumbers +pub 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 +pub 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#L160-L173 + + +### tokens + +```rust title="tokens" showLineNumbers +pub 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.38.0/noir/standard_library/meta/struct_def.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/struct_def.md new file mode 100644 index 00000000000..fd609942f4e --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.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 +pub 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 +pub 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#L35-L44 + + +### as_type + +```rust title="as_type" showLineNumbers +pub 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 +pub 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 +pub 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 +pub 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 +pub 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 +pub 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 +pub 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.38.0/noir/standard_library/meta/trait_constraint.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.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.38.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.38.0/noir/standard_library/meta/trait_def.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/trait_def.md new file mode 100644 index 00000000000..e661d3af7f1 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.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 +pub 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.38.0/noir/standard_library/meta/trait_impl.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/trait_impl.md new file mode 100644 index 00000000000..a527617c1e6 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.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 +pub 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 +pub 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.38.0/noir/standard_library/meta/typ.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/typ.md new file mode 100644 index 00000000000..90222c222f5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/typ.md @@ -0,0 +1,264 @@ +--- +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#L57-L59 + + +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#L14-L29 + +```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#L129-L149 + + +## Methods + +### as_array + +```rust title="as_array" showLineNumbers +pub comptime fn as_array(self) -> Option<(Type, Type)> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L76-L78 + + +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 +pub comptime fn as_constant(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L83-L85 + + +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 +pub comptime fn as_integer(self) -> Option<(bool, u8)> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L90-L92 + + +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_mutable_reference + +```rust title="as_mutable_reference" showLineNumbers +comptime fn as_mutable_reference(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L96-L98 + + +If this is a mutable reference type `&mut T`, returns the mutable type `T`. + +### as_slice + +```rust title="as_slice" showLineNumbers +pub comptime fn as_slice(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L102-L104 + + +If this is a slice type, return the element type of the slice. + +### as_str + +```rust title="as_str" showLineNumbers +pub comptime fn as_str(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L108-L110 + + +If this is a `str` type, returns the length `N` as a type. + +### as_struct + +```rust title="as_struct" showLineNumbers +pub comptime fn as_struct(self) -> Option<(StructDefinition, [Type])> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L114-L116 + + +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 +pub comptime fn as_tuple(self) -> Option<[Type]> {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L120-L122 + + +If this is a tuple type, returns each element type of the tuple. + +### get_trait_impl + +```rust title="get_trait_impl" showLineNumbers +pub comptime fn get_trait_impl(self, constraint: TraitConstraint) -> Option {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L143-L145 + + +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 +pub comptime fn implements(self, constraint: TraitConstraint) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L166-L168 + + +`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 +pub comptime fn is_bool(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L172-L174 + + +`true` if this type is `bool`. + +### is_field + +```rust title="is_field" showLineNumbers +pub comptime fn is_field(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L178-L180 + + +`true` if this type is `Field`. + +### is_unit + +```rust title="is_unit" showLineNumbers +comptime fn is_unit(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/typ.nr#L184-L186 + + +`true` if this type is the unit `()` type. + +## 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.38.0/noir/standard_library/meta/typed_expr.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/typed_expr.md new file mode 100644 index 00000000000..0db7dbfef61 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.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 +pub 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 +pub 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.38.0/noir/standard_library/meta/unresolved_type.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/unresolved_type.md new file mode 100644 index 00000000000..2826ec5ec0f --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/meta/unresolved_type.md @@ -0,0 +1,57 @@ +--- +title: UnresolvedType +--- + +`std::meta::unresolved_type` contains methods on the built-in `UnresolvedType` type for the syntax of types. + +## Methods + +### as_mutable_reference + +```rust title="as_mutable_reference" showLineNumbers +comptime fn as_mutable_reference(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L8-L10 + + +If this is a mutable reference type `&mut T`, returns the mutable type `T`. + +### as_slice + +```rust title="as_slice" showLineNumbers +comptime fn as_slice(self) -> Option {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L14-L16 + + +If this is a slice `&[T]`, returns the element type `T`. + +### is_bool + +```rust title="is_bool" showLineNumbers +comptime fn is_bool(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L20-L22 + + +Returns `true` if this type is `bool`. + +### is_field + +```rust title="is_field" showLineNumbers +pub comptime fn is_field(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L26-L28 + + +Returns true if this type refers to the Field type. + +### is_unit + +```rust title="is_unit" showLineNumbers +comptime fn is_unit(self) -> bool {} +``` +> Source code: noir_stdlib/src/meta/unresolved_type.nr#L32-L34 + + +Returns true if this type is the unit `()` type. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/options.md new file mode 100644 index 00000000000..a1bd4e1de5f --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/options.md @@ -0,0 +1,101 @@ +--- +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.38.0/noir/standard_library/recursion.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/recursion.mdx new file mode 100644 index 00000000000..60414a2fa51 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/recursion.mdx @@ -0,0 +1,85 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, verify_proof] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox'; + +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) {} +``` + + + +## Example usage + +```rust + +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, + proof, + public_inputs, + key_hash + ); + + std::verify_proof( + verification_key, + proof_b, + public_inputs, + 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.38.0/noir/standard_library/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/traits.md new file mode 100644 index 00000000000..ee20f9cd949 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/noir/standard_library/traits.md @@ -0,0 +1,628 @@ +--- +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 +pub trait Default { + fn default() -> Self; +} +``` +> Source code: noir_stdlib/src/default.nr#L4-L8 + + +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 +pub 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#L28-L119 + + +#### 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 +pub 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-L26 + + +`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 +pub trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L4-L8 + + +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 +pub trait Ord { + fn cmp(self, other: Self) -> Ordering; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L210-L214 + + +`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 +pub trait Add { + fn add(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L1-L5 + +```rust title="sub-trait" showLineNumbers +pub trait Sub { + fn sub(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L60-L64 + +```rust title="mul-trait" showLineNumbers +pub trait Mul { + fn mul(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L119-L123 + +```rust title="div-trait" showLineNumbers +pub trait Div { + fn div(self, other: Self) -> Self; +} +``` +> 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 +`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 +pub trait Rem { + fn rem(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L237-L241 + + +`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 +pub trait Neg { + fn neg(self) -> Self; +} +``` +> 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 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#L296-L323 + + +### `std::ops::Not` + +```rust title="not-trait" showLineNumbers +pub 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-L60 + + +### `std::ops::{ BitOr, BitAnd, BitXor }` + +```rust title="bitor-trait" showLineNumbers +pub trait BitOr { + fn bitor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L62-L66 + +```rust title="bitand-trait" showLineNumbers +pub trait BitAnd { + fn bitand(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L121-L125 + +```rust title="bitxor-trait" showLineNumbers +pub trait BitXor { + fn bitxor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L180-L184 + + +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 +pub trait Shl { + fn shl(self, other: u8) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L239-L243 + +```rust title="shr-trait" showLineNumbers +pub trait Shr { + fn shr(self, other: u8) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L292-L296 + + +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 } } +``` + +--- + +## `std::append` + +### `std::append::Append` + +`Append` can abstract over types that can be appended to - usually container types: + +```rust title="append-trait" showLineNumbers +pub 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.38.0/reference/NoirJS/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/.nojekyll @@ -0,0 +1 @@ +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.38.0/reference/NoirJS/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/classes/Noir.md new file mode 100644 index 00000000000..ead255bc504 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/classes/Noir.md @@ -0,0 +1,52 @@ +# Noir + +## Constructors + +### new Noir(circuit) + +```ts +new Noir(circuit): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | `CompiledCircuit` | + +#### Returns + +[`Noir`](Noir.md) + +## Methods + +### 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) +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/functions/and.md new file mode 100644 index 00000000000..c783283e396 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/functions/and.md @@ -0,0 +1,22 @@ +# 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.38.0/reference/NoirJS/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/functions/blake2s256.md new file mode 100644 index 00000000000..7882d0da8d5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/functions/blake2s256.md @@ -0,0 +1,21 @@ +# 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.38.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 00000000000..5e3cd53e9d3 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md @@ -0,0 +1,28 @@ +# 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.38.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 00000000000..0b20ff68957 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md @@ -0,0 +1,28 @@ +# 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.38.0/reference/NoirJS/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/functions/xor.md new file mode 100644 index 00000000000..8d762b895d3 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/functions/xor.md @@ -0,0 +1,22 @@ +# 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.38.0/reference/NoirJS/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/index.md new file mode 100644 index 00000000000..4de7a696991 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/index.md @@ -0,0 +1,47 @@ +# 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. | +| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | + +## References + +### CompiledCircuit + +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.38.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md new file mode 100644 index 00000000000..e8c2f4aef3d --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md @@ -0,0 +1,15 @@ +# 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.38.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 00000000000..812b8b16481 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md @@ -0,0 +1,24 @@ +# 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.38.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 00000000000..dd95809186a --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md @@ -0,0 +1,9 @@ +# 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.38.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 00000000000..b71fb78a946 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md @@ -0,0 +1,9 @@ +# 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.38.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 00000000000..258c46f9d0c --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md @@ -0,0 +1,9 @@ +# 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.38.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs new file mode 100644 index 00000000000..4796b5abaa8 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_js/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/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/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/.nojekyll @@ -0,0 +1 @@ +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.38.0/reference/NoirJS/noir_wasm/functions/compile.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/functions/compile.md new file mode 100644 index 00000000000..6faf763b37f --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/functions/compile.md @@ -0,0 +1,51 @@ +# 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.38.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/functions/compile_contract.md new file mode 100644 index 00000000000..7d0b39a43ef --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/functions/compile_contract.md @@ -0,0 +1,51 @@ +# 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.38.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/functions/createFileManager.md new file mode 100644 index 00000000000..7e65c1d69c7 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/functions/createFileManager.md @@ -0,0 +1,21 @@ +# 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.38.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md new file mode 100644 index 00000000000..fcea9275341 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md @@ -0,0 +1,21 @@ +# 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.38.0/reference/NoirJS/noir_wasm/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/index.md new file mode 100644 index 00000000000..b6e0f9d1bc0 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/index.md @@ -0,0 +1,49 @@ +# 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.38.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs new file mode 100644 index 00000000000..e0870710349 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @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.38.0/reference/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/_category_.json new file mode 100644 index 00000000000..5b6a20a609a --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/debugger/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/debugger/_category_.json new file mode 100644 index 00000000000..27869205ad3 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugger", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/debugger/debugger_known_limitations.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/debugger/debugger_known_limitations.md new file mode 100644 index 00000000000..936d416ac4b --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/debugger/debugger_known_limitations.md @@ -0,0 +1,59 @@ +--- +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.38.0/reference/debugger/debugger_repl.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/debugger/debugger_repl.md new file mode 100644 index 00000000000..46e2011304e --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/debugger/debugger_repl.md @@ -0,0 +1,360 @@ +--- +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.38.0/reference/debugger/debugger_vscode.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/debugger/debugger_vscode.md new file mode 100644 index 00000000000..c027332b3b0 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/debugger/debugger_vscode.md @@ -0,0 +1,82 @@ +--- +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.38.0/reference/nargo_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/nargo_commands.md new file mode 100644 index 00000000000..8842fad6647 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/nargo_commands.md @@ -0,0 +1,474 @@ +--- +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 debug`↴](#nargo-debug) +* [`nargo test`↴](#nargo-test) +* [`nargo info`↴](#nargo-info) +* [`nargo lsp`↴](#nargo-lsp) +* [`nargo generate-completion-script`↴](#nargo-generate-completion-script) + +## `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 +* `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 +* `generate-completion-script` — Generates a shell completion script for your favorite shell + +###### **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 + + Possible values: `true`, `false` + +* `--overwrite` — Force overwrite of existing files + + Possible values: `true`, `false` + +* `--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` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--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 + + Possible values: `true`, `false` + + + + +## `nargo fmt` + +Format the Noir files in a workspace + +**Usage:** `nargo fmt [OPTIONS]` + +###### **Options:** + +* `--check` — Run noirfmt in check mode + + Possible values: `true`, `false` + + + + +## `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 + + Possible values: `true`, `false` + +* `--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` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--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 + + Possible values: `true`, `false` + + + + +## `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 + + Possible values: `true`, `false` + +* `--bin` — Use a binary template [default] + + Possible values: `true`, `false` + +* `--contract` — Use a contract template + + Possible values: `true`, `false` + + + + +## `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 + + Possible values: `true`, `false` + +* `--bin` — Use a binary template [default] + + Possible values: `true`, `false` + +* `--contract` — Use a contract template + + Possible values: `true`, `false` + + + + +## `nargo execute` + +Executes a circuit to calculate its return value + +**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` + +###### **Arguments:** + +* `` — Write the execution witness to named file + +Defaults to the name of the package being executed. + +###### **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 + + Possible values: `true`, `false` + +* `--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` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--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 + + Possible values: `true`, `false` + +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo debug` + +Executes a circuit in debug mode + +**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` +* `--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: `false` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--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 + + Possible values: `true`, `false` + +* `--acir-mode` — Force ACIR output (disabling instrumentation) + + Possible values: `true`, `false` + +* `--skip-instrumentation ` — Disable vars debug instrumentation (enabled by default) + + Possible values: `true`, `false` + + + + +## `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 + + Possible values: `true`, `false` + +* `--exact` — Only run tests that match exactly + + Possible values: `true`, `false` + +* `--package ` — The name of the package to test +* `--workspace` — Test all packages in the workspace + + Possible values: `true`, `false` + +* `--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` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--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 + + Possible values: `true`, `false` + +* `--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 + + Possible values: `true`, `false` + +* `--profile-execution` + + Possible values: `true`, `false` + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `--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` + + Possible values: `true`, `false` + +* `--force` — Force a full recompilation + + Possible values: `true`, `false` + +* `--print-acir` — Display the ACIR for compiled circuit + + Possible values: `true`, `false` + +* `--deny-warnings` — Treat all warnings as errors + + Possible values: `true`, `false` + +* `--silence-warnings` — Suppress warnings + + Possible values: `true`, `false` + +* `--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 + + Possible values: `true`, `false` + + + + +## `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` + + + +## `nargo generate-completion-script` + +Generates a shell completion script for your favorite shell + +**Usage:** `nargo generate-completion-script ` + +###### **Arguments:** + +* `` — The shell to generate completions for. One of: bash, elvish, fish, powershell, zsh + + + +
+ + + This document was generated automatically by + clap-markdown. + + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/noir_codegen.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/noir_codegen.md new file mode 100644 index 00000000000..e4c362f9610 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/reference/noir_codegen.md @@ -0,0 +1,116 @@ +--- +title: Noir Codegen for TypeScript +description: Learn how to use Noir codegen to generate TypeScript bindings +keywords: [Nargo, Noir, compile, TypeScript] +sidebar_position: 3 +--- + +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](../getting_started/noir_installation.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"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"}},"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.38.0/tooling/debugger.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/tooling/debugger.md new file mode 100644 index 00000000000..200b5fc423a --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/tooling/debugger.md @@ -0,0 +1,26 @@ +--- +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/noir_installation.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.38.0/tooling/language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/tooling/language_server.md new file mode 100644 index 00000000000..81e0356ef8a --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/tooling/language_server.md @@ -0,0 +1,43 @@ +--- +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.38.0/tooling/testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/tooling/testing.md new file mode 100644 index 00000000000..866677da567 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/tooling/testing.md @@ -0,0 +1,79 @@ +--- +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); +} +``` + +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.38.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/tutorials/noirjs_app.md new file mode 100644 index 00000000000..6e69ea0bbed --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.38.0/tutorials/noirjs_app.md @@ -0,0 +1,366 @@ +--- +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.31.x matches `noir_js@0.31.x`, etc. + +In this guide, we will be pinned to 0.31.0. + +::: + +Before we start, we want to make sure we have Node, Nargo and the Barretenberg proving system (`bb`) 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/quick_start.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 +``` + +Follow the instructions on [this page](https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg/cpp/src/barretenberg/bb#installation) to install `bb`. +Version 0.41.0 is compatible with `nargo` version 0.31.0, which you can install with `bbup -v 0.41.0` once `bbup` is installed. + +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: + +```bash +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: + +```bash +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/quick_start.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'; +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 { + build: { + target: 'esnext', + rollupOptions: { + external: ['@aztec/bb.js'] + } + }, + optimizeDeps: { + esbuildOptions: { + target: 'esnext' + } + }, + plugins: [ + copy({ + targets: [{ src: 'node_modules/**/*.wasm', dest: 'node_modules/.vite/dist' }], + copySync: true, + hook: 'buildStart', + }), + command === 'serve' ? wasmContentTypePlugin : [], + ], + }; + } + + return {}; +}); +``` + +#### 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.31.0 @noir-lang/noir_js@0.31.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 +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 😢 + +:::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); +// } +``` + +:::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 { witness } = await noir.execute(input); +const proof = await backend.generateProof(witness); +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 isValid = await backend.verifyProof(proof); + +// or to cache and use the verification key: +// 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. + +## 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). diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.38.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.38.0-sidebars.json new file mode 100644 index 00000000000..b9ad026f69f --- /dev/null +++ b/noir/noir-repo/docs/versioned_sidebars/version-v0.38.0-sidebars.json @@ -0,0 +1,93 @@ +{ + "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/examples/codegen_verifier/codegen_verifier.sh b/noir/noir-repo/examples/codegen_verifier/codegen_verifier.sh index fabd6235a67..f224f74168f 100755 --- a/noir/noir-repo/examples/codegen_verifier/codegen_verifier.sh +++ b/noir/noir-repo/examples/codegen_verifier/codegen_verifier.sh @@ -16,11 +16,17 @@ nargo execute witness PROOF_PATH=./target/proof $BACKEND prove -b ./target/hello_world.json -w ./target/witness.gz -o $PROOF_PATH -NUM_PUBLIC_INPUTS=1 +# Sanity check that proof is valid. +$BACKEND verify -k ./target/vk -p ./target/proof + +NUM_PUBLIC_INPUTS=2 PUBLIC_INPUT_BYTES=$((32 * $NUM_PUBLIC_INPUTS)) HEX_PUBLIC_INPUTS=$(head -c $PUBLIC_INPUT_BYTES $PROOF_PATH | od -An -v -t x1 | tr -d $' \n') HEX_PROOF=$(tail -c +$(($PUBLIC_INPUT_BYTES + 1)) $PROOF_PATH | od -An -v -t x1 | tr -d $' \n') +# Split public inputs into strings where each string represents a `bytes32`. +SPLIT_HEX_PUBLIC_INPUTS=$(sed -e 's/.\{64\}/0x&,/g' <<< $HEX_PUBLIC_INPUTS) + # Spin up an anvil node to deploy the contract to anvil & @@ -31,8 +37,7 @@ DEPLOY_INFO=$(forge create UltraVerifier \ VERIFIER_ADDRESS=$(echo $DEPLOY_INFO | jq -r '.deployedTo') # Call the verifier contract with our proof. -# Note that we haven't needed to split up `HEX_PUBLIC_INPUTS` as there's only a single public input -cast call $VERIFIER_ADDRESS "verify(bytes, bytes32[])(bool)" "0x$HEX_PROOF" "[0x$HEX_PUBLIC_INPUTS]" +cast call $VERIFIER_ADDRESS "verify(bytes, bytes32[])(bool)" "0x$HEX_PROOF" "[$SPLIT_HEX_PUBLIC_INPUTS]" # Stop anvil node again -kill %- \ No newline at end of file +kill %- diff --git a/noir/noir-repo/examples/codegen_verifier/src/main.nr b/noir/noir-repo/examples/codegen_verifier/src/main.nr index baef0c3786a..93531797744 100644 --- a/noir/noir-repo/examples/codegen_verifier/src/main.nr +++ b/noir/noir-repo/examples/codegen_verifier/src/main.nr @@ -1,3 +1,3 @@ -fn main(x: Field, y: pub Field) { +fn main(x: pub Field, y: pub Field) { assert(x != y); -} \ No newline at end of file +} 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 9e70c403f77..f33890f197e 100644 --- a/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr +++ b/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr @@ -517,7 +517,7 @@ mod bounded_vec_tests { let expected = BoundedVec::from_array([5, 1]); assert_eq(result, expected); - assert_eq(result.storage()[2], 0); + assert_eq(result.get_unchecked(2), 0); } } @@ -551,9 +551,9 @@ mod bounded_vec_tests { assert_eq(bounded_vec.max_len(), 10); assert_eq(bounded_vec.len(), 3); - assert_eq(bounded_vec.storage()[0], 1); - assert_eq(bounded_vec.storage()[1], 2); - assert_eq(bounded_vec.storage()[2], 3); + assert_eq(bounded_vec.get(0), 1); + assert_eq(bounded_vec.get(1), 2); + assert_eq(bounded_vec.get(2), 3); } #[test(should_fail_with = "from array out of bounds")] @@ -572,8 +572,8 @@ mod bounded_vec_tests { assert_eq(bounded_vec.max_len(), 10); assert_eq(bounded_vec.len(), 2); - assert_eq(bounded_vec.storage()[0], 1); - assert_eq(bounded_vec.storage()[1], 2); + assert_eq(bounded_vec.get(0), 1); + assert_eq(bounded_vec.get(1), 2); } } diff --git a/noir/noir-repo/noir_stdlib/src/ec/tecurve.nr b/noir/noir-repo/noir_stdlib/src/ec/tecurve.nr index 8512413c831..08f017c4f91 100644 --- a/noir/noir-repo/noir_stdlib/src/ec/tecurve.nr +++ b/noir/noir-repo/noir_stdlib/src/ec/tecurve.nr @@ -27,7 +27,7 @@ pub mod affine { impl Point { // Point constructor - #[deprecated = "It's recommmended to use the external noir-edwards library (https://github.com/noir-lang/noir-edwards)"] + //#[deprecated = "It's recommmended to use the external noir-edwards library (https://github.com/noir-lang/noir-edwards)"] pub fn new(x: Field, y: Field) -> Self { Self { x, y } } diff --git a/noir/noir-repo/test_programs/compile_success_empty/attribute_args/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/attribute_args/src/main.nr index 492afd9e2f1..5fc193150db 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/attribute_args/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/attribute_args/src/main.nr @@ -1,6 +1,6 @@ #[attr_with_args(1, 2)] -#[varargs(1, 2)] -#[varargs(1, 2, 3, 4)] +#[attr_with_varargs(1, 2)] +#[attr_with_varargs(1, 2, 3, 4)] pub struct Foo {} comptime fn attr_with_args(s: StructDefinition, a: Field, b: Field) { @@ -12,8 +12,8 @@ comptime fn attr_with_args(s: StructDefinition, a: Field, b: Field) { } #[varargs] -comptime fn varargs(s: StructDefinition, t: [Field]) { - let _ = s; +comptime fn attr_with_varargs(s: StructDefinition, t: [Field]) { + let _: StructDefinition = s; for _ in t {} assert(t.len() < 5); } 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 index a3aae2911bb..ff74c82f2ee 100644 --- 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 @@ -38,5 +38,5 @@ fn main( a_as_bounded_vec.push(value); } } - a_as_bounded_vec.storage + a_as_bounded_vec.storage() } diff --git a/noir/noir-repo/test_programs/execution_success/bit_shifts_comptime/src/main.nr b/noir/noir-repo/test_programs/execution_success/bit_shifts_comptime/src/main.nr index 6d9736b6abb..a11dae1c716 100644 --- a/noir/noir-repo/test_programs/execution_success/bit_shifts_comptime/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/bit_shifts_comptime/src/main.nr @@ -15,6 +15,10 @@ fn main(x: u64) { assert(x << 63 == 0); assert_eq((1 as u64) << 32, 0x0100000000); + + //regression for 6201 + let a: i16 = -769; + assert_eq(a >> 3, -97); } fn regression_2250() { diff --git a/noir/noir-repo/test_programs/execution_success/bit_shifts_runtime/Prover.toml b/noir/noir-repo/test_programs/execution_success/bit_shifts_runtime/Prover.toml index 67bf6a6a234..7b56d36c9d5 100644 --- a/noir/noir-repo/test_programs/execution_success/bit_shifts_runtime/Prover.toml +++ b/noir/noir-repo/test_programs/execution_success/bit_shifts_runtime/Prover.toml @@ -1,2 +1,3 @@ x = 64 y = 1 +z = "-769" diff --git a/noir/noir-repo/test_programs/execution_success/bit_shifts_runtime/src/main.nr b/noir/noir-repo/test_programs/execution_success/bit_shifts_runtime/src/main.nr index 059bbe84dac..370bb699048 100644 --- a/noir/noir-repo/test_programs/execution_success/bit_shifts_runtime/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/bit_shifts_runtime/src/main.nr @@ -1,4 +1,4 @@ -fn main(x: u64, y: u8) { +fn main(x: u64, y: u8, z: i16) { // runtime shifts on compile-time known values assert(64 << y == 128); assert(64 >> y == 32); @@ -17,4 +17,6 @@ fn main(x: u64, y: u8) { assert(a << y == -2); assert(x >> (x as u8) == 0); + + assert_eq(z >> 3, -97); } diff --git a/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr b/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr index 48e1e4af9fb..d4c3664f0c9 100644 --- a/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr @@ -2,7 +2,6 @@ use std::compat; use std::ec::consts::te::baby_jubjub; use std::ec::tecurve::affine::Point as TEPoint; use std::eddsa::{eddsa_poseidon_verify, eddsa_to_pub, eddsa_verify}; -use std::hash; use std::hash::poseidon2::Poseidon2Hasher; fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) { diff --git a/noir/noir-repo/test_programs/execution_success/references/src/main.nr b/noir/noir-repo/test_programs/execution_success/references/src/main.nr index 4ddbf8aa1e3..65d70dc4a5f 100644 --- a/noir/noir-repo/test_programs/execution_success/references/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/references/src/main.nr @@ -1,7 +1,6 @@ fn main(mut x: Field) { add1(&mut x); assert(x == 3); - let mut s = S { y: x }; s.add2(); assert(s.y == 5); @@ -21,18 +20,16 @@ fn main(mut x: Field) { let mut c = C { foo: 0, bar: &mut C2 { array: &mut [1, 2] } }; *c.bar.array = [3, 4]; assert(*c.bar.array == [3, 4]); - regression_1887(); regression_2054(); regression_2030(); regression_2255(); - + regression_6443(); assert(x == 3); regression_2218_if_inner_if(x, 10); regression_2218_if_inner_else(20, x); regression_2218_else(x, 3); regression_2218_loop(x, 10); - regression_2560(s_ref); } @@ -106,6 +103,7 @@ fn regression_2030() { let _ = *array[0]; *array[0] = 1; } + // The `mut x: &mut ...` caught a bug handling lvalues where a double-dereference would occur internally // in one step rather than being tracked by two separate steps. This lead to assigning the 1 value to the // incorrect outer `mut` reference rather than the correct `&mut` reference. @@ -119,6 +117,18 @@ fn regression_2255_helper(mut x: &mut Field) { *x = 1; } +// Similar to `regression_2255` but without the double-dereferencing. +// The test checks that `mem2reg` does not eliminate storing to a reference passed as a parameter. +fn regression_6443() { + let x = &mut 0; + regression_6443_helper(x); + assert(*x == 1); +} + +fn regression_6443_helper(x: &mut Field) { + *x = 1; +} + fn regression_2218(x: Field, y: Field) -> Field { let q = &mut &mut 0; let q1 = *q; diff --git a/noir/noir-repo/test_programs/execution_success/regression_6451/Nargo.toml b/noir/noir-repo/test_programs/execution_success/regression_6451/Nargo.toml new file mode 100644 index 00000000000..e109747c7f6 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_6451/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "regression_6451" +type = "bin" +authors = [""] +[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/regression_6451/Prover.toml b/noir/noir-repo/test_programs/execution_success/regression_6451/Prover.toml new file mode 100644 index 00000000000..74213d097ec --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_6451/Prover.toml @@ -0,0 +1 @@ +x = 0 \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/regression_6451/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_6451/src/main.nr new file mode 100644 index 00000000000..fbee6956dfa --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_6451/src/main.nr @@ -0,0 +1,23 @@ +fn main(x: Field) { + // Regression test for #6451 + let y = unsafe { empty(x) }; + let mut value = 0; + let term1 = x * x - x * y; + std::as_witness(term1); + value += term1; + let term2 = x * x - y * x; + value += term2; + value.assert_max_bit_size::<1>(); + + // Regression test for Aztec Packages issue #6451 + let y = unsafe { empty(x + 1) }; + let z = y + x + 1; + let z1 = z + y; + assert(z + z1 != 3); + let w = y + 2 * x + 3; + assert(w + z1 != z); +} + +unconstrained fn empty(_: Field) -> Field { + 0 +} diff --git a/noir/noir-repo/tooling/debugger/src/context.rs b/noir/noir-repo/tooling/debugger/src/context.rs index 3f64fc1acdb..bec30976552 100644 --- a/noir/noir-repo/tooling/debugger/src/context.rs +++ b/noir/noir-repo/tooling/debugger/src/context.rs @@ -954,7 +954,7 @@ mod tests { use crate::foreign_calls::DefaultDebugForeignCallExecutor; use acvm::{ acir::{ - brillig::IntegerBitSize, + brillig::{HeapVector, IntegerBitSize}, circuit::{ brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}, opcodes::{AcirFunctionId, BlockId, BlockType}, @@ -970,31 +970,25 @@ mod tests { #[test] fn test_resolve_foreign_calls_stepping_into_brillig() { - let fe_0 = FieldElement::zero(); let fe_1 = FieldElement::one(); let w_x = Witness(1); let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress::direct(0), + destination: MemoryAddress::direct(1), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(1u64), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(1), + destination: MemoryAddress::direct(2), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), - }, - BrilligOpcode::Const { - destination: MemoryAddress::direct(1), - value: fe_0, - bit_size: BitSize::Integer(IntegerBitSize::U32), + size_address: MemoryAddress::direct(1), + offset_address: MemoryAddress::direct(2), }, BrilligOpcode::ForeignCall { function: "clear_mock".into(), @@ -1003,7 +997,12 @@ mod tests { inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], input_value_types: vec![HeapValueType::field()], }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, + BrilligOpcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(2), + size: MemoryAddress::direct(2), + }, + }, ], }; let opcodes = vec![Opcode::BrilligCall { @@ -1082,18 +1081,6 @@ mod tests { }) ); - // Const - let result = context.step_into_opcode(); - assert!(matches!(result, DebugCommandResult::Ok)); - assert_eq!( - context.get_current_debug_location(), - Some(DebugLocation { - circuit_id: 0, - opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 4 }, - brillig_function_id: Some(BrilligFunctionId(0)), - }) - ); - // try to execute the Brillig opcode (and resolve the foreign call) let result = context.step_into_opcode(); assert!(matches!(result, DebugCommandResult::Ok)); @@ -1101,7 +1088,7 @@ mod tests { context.get_current_debug_location(), Some(DebugLocation { circuit_id: 0, - opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 4 }, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 3 }, brillig_function_id: Some(BrilligFunctionId(0)), }) ); @@ -1113,7 +1100,7 @@ mod tests { context.get_current_debug_location(), Some(DebugLocation { circuit_id: 0, - opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 5 }, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 4 }, brillig_function_id: Some(BrilligFunctionId(0)), }) ); @@ -1132,6 +1119,9 @@ mod tests { let w_y = Witness(2); let w_z = Witness(3); + let zero_usize = MemoryAddress::direct(2); + let one_usize = MemoryAddress::direct(3); + // This Brillig block is equivalent to: z = x + y let brillig_bytecode = BrilligBytecode { bytecode: vec![ @@ -1141,14 +1131,19 @@ mod tests { value: FieldElement::from(2u64), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(1), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, + BrilligOpcode::Const { + destination: one_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(1u64), + }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress::direct(0), size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + offset_address: zero_usize, }, BrilligOpcode::BinaryFieldOp { destination: MemoryAddress::direct(0), @@ -1156,7 +1151,9 @@ mod tests { lhs: MemoryAddress::direct(0), rhs: MemoryAddress::direct(1), }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 1 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: one_usize }, + }, ], }; let opcodes = vec![ @@ -1238,18 +1235,10 @@ mod tests { #[test] fn test_address_debug_location_mapping() { - let brillig_one = BrilligBytecode { - bytecode: vec![ - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - ], - }; + let brillig_one = + BrilligBytecode { bytecode: vec![BrilligOpcode::Return, BrilligOpcode::Return] }; let brillig_two = BrilligBytecode { - bytecode: vec![ - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - ], + bytecode: vec![BrilligOpcode::Return, BrilligOpcode::Return, BrilligOpcode::Return], }; let circuit_one = Circuit { diff --git a/noir/noir-repo/tooling/lsp/src/attribute_reference_finder.rs b/noir/noir-repo/tooling/lsp/src/attribute_reference_finder.rs index 660ee8ffdfb..e3f31b65b46 100644 --- a/noir/noir-repo/tooling/lsp/src/attribute_reference_finder.rs +++ b/noir/noir-repo/tooling/lsp/src/attribute_reference_finder.rs @@ -13,24 +13,22 @@ use noirc_frontend::{ graph::CrateId, hir::{ def_map::{CrateDefMap, LocalModuleId, ModuleId}, - resolution::{ - import::PathResolutionItem, - path_resolver::{PathResolver, StandardPathResolver}, - }, + resolution::import::resolve_import, }, - node_interner::{NodeInterner, ReferenceId}, - parser::{ParsedSubModule, Parser}, - token::CustomAttribute, + node_interner::ReferenceId, + parser::ParsedSubModule, + token::MetaAttribute, usage_tracker::UsageTracker, ParsedModule, }; +use crate::modules::module_def_id_to_reference_id; + pub(crate) struct AttributeReferenceFinder<'a> { byte_index: usize, /// The module ID in scope. This might change as we traverse the AST /// if we are analyzing something inside an inline module declaration. module_id: ModuleId, - interner: &'a NodeInterner, def_maps: &'a BTreeMap, reference_id: Option, } @@ -41,7 +39,6 @@ impl<'a> AttributeReferenceFinder<'a> { file: FileId, byte_index: usize, krate: CrateId, - interner: &'a NodeInterner, def_maps: &'a BTreeMap, ) -> Self { // Find the module the current file belongs to @@ -54,7 +51,7 @@ impl<'a> AttributeReferenceFinder<'a> { def_map.root() }; let module_id = ModuleId { krate, local_id }; - Self { byte_index, module_id, interner, def_maps, reference_id: None } + Self { byte_index, module_id, def_maps, reference_id: None } } pub(crate) fn find(&mut self, parsed_module: &ParsedModule) -> Option { @@ -88,42 +85,31 @@ impl<'a> Visitor for AttributeReferenceFinder<'a> { false } - fn visit_custom_attribute(&mut self, attribute: &CustomAttribute, _target: AttributeTarget) { - if !self.includes_span(attribute.contents_span) { - return; + fn visit_meta_attribute( + &mut self, + attribute: &MetaAttribute, + _target: AttributeTarget, + ) -> bool { + if !self.includes_span(attribute.span) { + return false; } - let name = match attribute.contents.split_once('(') { - Some((left, _right)) => left.to_string(), - None => attribute.contents.to_string(), - }; - let mut parser = Parser::for_str(&name); - let Some(path) = parser.parse_path_no_turbofish() else { - return; - }; - - let resolver = StandardPathResolver::new(self.module_id, None); - let mut usage_tracker = UsageTracker::default(); - let Ok(result) = - resolver.resolve(self.interner, self.def_maps, path, &mut usage_tracker, &mut None) - else { - return; + let path = attribute.name.clone(); + // The path here must resolve to a function and it's a simple path (can't have turbofish) + // so it can (and must) be solved as an import. + let Ok(Some((module_def_id, _, _))) = resolve_import( + path, + self.module_id, + self.def_maps, + &mut UsageTracker::default(), + None, // references tracker + ) + .map(|result| result.namespace.values) else { + return true; }; - self.reference_id = Some(path_resolution_item_to_reference_id(result.item)); - } -} + self.reference_id = Some(module_def_id_to_reference_id(module_def_id)); -fn path_resolution_item_to_reference_id(item: PathResolutionItem) -> ReferenceId { - match item { - PathResolutionItem::Module(module_id) => ReferenceId::Module(module_id), - PathResolutionItem::Struct(struct_id) => ReferenceId::Struct(struct_id), - PathResolutionItem::TypeAlias(type_alias_id) => ReferenceId::Alias(type_alias_id), - PathResolutionItem::Trait(trait_id) => ReferenceId::Trait(trait_id), - PathResolutionItem::Global(global_id) => ReferenceId::Global(global_id), - PathResolutionItem::ModuleFunction(func_id) - | PathResolutionItem::StructFunction(_, _, func_id) - | PathResolutionItem::TypeAliasFunction(_, _, func_id) - | PathResolutionItem::TraitFunction(_, _, func_id) => ReferenceId::Function(func_id), + true } } diff --git a/noir/noir-repo/tooling/lsp/src/requests/completion.rs b/noir/noir-repo/tooling/lsp/src/requests/completion.rs index 2dd42c740cd..d71f0414adc 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/completion.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/completion.rs @@ -26,20 +26,21 @@ use noirc_frontend::{ graph::{CrateId, Dependency}, hir::{ def_map::{CrateDefMap, LocalModuleId, ModuleDefId, ModuleId}, - resolution::visibility::{method_call_is_visible, struct_member_is_visible}, + resolution::visibility::{ + item_in_module_is_visible, method_call_is_visible, struct_member_is_visible, + }, }, hir_def::traits::Trait, node_interner::{NodeInterner, ReferenceId, StructId}, parser::{Item, ItemKind, ParsedSubModule}, - token::{CustomAttribute, Token, Tokens}, + token::{MetaAttribute, Token, Tokens}, Kind, ParsedModule, StructType, Type, TypeBinding, }; use sort_text::underscore_sort_text; use crate::{ requests::to_lsp_location, trait_impl_method_stub_generator::TraitImplMethodStubGenerator, - use_segment_positions::UseSegmentPositions, utils, visibility::item_in_module_is_visible, - LspState, + use_segment_positions::UseSegmentPositions, utils, LspState, }; use super::process_request; @@ -583,6 +584,14 @@ impl<'a> NodeFinder<'a> { self_prefix, ); } + Type::CheckedCast { to, .. } => { + return self.complete_type_fields_and_methods( + to, + prefix, + function_completion_kind, + self_prefix, + ); + } Type::Tuple(types) => { self.complete_tuple_fields(types, self_prefix); } @@ -799,10 +808,10 @@ impl<'a> NodeFinder<'a> { let per_ns = module_data.find_name(ident); if let Some((module_def_id, visibility, _)) = per_ns.types { if item_in_module_is_visible( - module_id, + self.def_maps, self.module_id, + module_id, visibility, - self.def_maps, ) { let completion_items = self.module_def_id_completion_items( module_def_id, @@ -820,10 +829,10 @@ impl<'a> NodeFinder<'a> { if let Some((module_def_id, visibility, _)) = per_ns.values { if item_in_module_is_visible( - module_id, + self.def_maps, self.module_id, + module_id, visibility, - self.def_maps, ) { let completion_items = self.module_def_id_completion_items( module_def_id, @@ -892,24 +901,6 @@ impl<'a> NodeFinder<'a> { None } - fn suggest_attributes(&mut self, prefix: &str, target: AttributeTarget) { - self.suggest_builtin_attributes(prefix, target); - - let function_completion_kind = FunctionCompletionKind::NameAndParameters; - let requested_items = RequestedItems::OnlyAttributeFunctions(target); - - self.complete_in_module( - self.module_id, - prefix, - PathKind::Plain, - true, - function_completion_kind, - requested_items, - ); - - self.complete_auto_imports(prefix, requested_items, function_completion_kind); - } - fn suggest_no_arguments_attributes(&mut self, prefix: &str, attributes: &[&str]) { for name in attributes { if name_matches(name, prefix) { @@ -1666,12 +1657,14 @@ impl<'a> Visitor for NodeFinder<'a> { false } - fn visit_custom_attribute(&mut self, attribute: &CustomAttribute, target: AttributeTarget) { - if self.byte_index != attribute.contents_span.end() as usize { - return; + fn visit_meta_attribute(&mut self, attribute: &MetaAttribute, target: AttributeTarget) -> bool { + if self.byte_index == attribute.name.span.end() as usize { + self.suggest_builtin_attributes(&attribute.name.to_string(), target); } - self.suggest_attributes(&attribute.contents, target); + self.find_in_path(&attribute.name, RequestedItems::OnlyAttributeFunctions(target)); + + true } fn visit_quote(&mut self, tokens: &Tokens) { 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 c2c561ced32..b4c7d8b6e01 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/completion/builtins.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/completion/builtins.rs @@ -107,6 +107,15 @@ impl<'a> NodeFinder<'a> { let one_argument_attributes = &["abi", "field", "foreign", "oracle"]; self.suggest_one_argument_attributes(prefix, one_argument_attributes); + if name_matches("deprecated", prefix) { + self.completion_items.push(snippet_completion_item( + "deprecated(\"...\")", + CompletionItemKind::METHOD, + "deprecated(\"${1:message}\")", + None, + )); + } + if name_matches("test", prefix) || name_matches("should_fail", prefix) { self.completion_items.push(snippet_completion_item( "test(should_fail)", 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 745dacfc152..8cfb2a4b5ee 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs @@ -2350,13 +2350,13 @@ fn main() { #[test] async fn test_suggests_built_in_function_attribute() { let src = r#" - #[dep>|<] + #[no_pred>|<] fn foo() {} "#; assert_completion_excluding_auto_import( src, - vec![simple_completion_item("deprecated", CompletionItemKind::METHOD, None)], + vec![simple_completion_item("no_predicates", CompletionItemKind::METHOD, None)], ) .await; } diff --git a/noir/noir-repo/tooling/lsp/src/requests/goto_definition.rs b/noir/noir-repo/tooling/lsp/src/requests/goto_definition.rs index 9380209da5c..a2443ea165d 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/goto_definition.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/goto_definition.rs @@ -46,7 +46,6 @@ fn on_goto_definition_inner( file_id, byte_index, args.crate_id, - args.interner, args.def_maps, ); finder.find(&parsed_module) diff --git a/noir/noir-repo/tooling/lsp/src/requests/hover.rs b/noir/noir-repo/tooling/lsp/src/requests/hover.rs index eb066b53b78..bb1ea661719 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/hover.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/hover.rs @@ -47,7 +47,6 @@ pub(crate) fn on_hover_request( file_id, byte_index, args.crate_id, - args.interner, args.def_maps, ); finder.find(&parsed_module) @@ -680,6 +679,7 @@ impl<'a> TypeLinksGatherer<'a> { self.gather_type_links(lhs); self.gather_type_links(rhs); } + Type::CheckedCast { to, .. } => self.gather_type_links(to), Type::FieldElement | Type::Integer(..) | Type::Bool 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 f7b3e6a748d..c6415acb545 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/inlay_hint.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/inlay_hint.rs @@ -471,6 +471,7 @@ fn push_type_parts(typ: &Type, parts: &mut Vec, files: &File push_type_variable_parts(binding, parts, files); } } + Type::CheckedCast { to, .. } => push_type_parts(to, parts, files), Type::FieldElement | Type::Integer(..) 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 index b433ee2ec88..2ae0d526f3e 100644 --- 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 @@ -368,6 +368,7 @@ impl<'a> TraitImplMethodStubGenerator<'a> { self.string.push(' '); self.append_type(right); } + Type::CheckedCast { to, .. } => self.append_type(to), Type::Constant(..) | Type::Integer(_, _) | Type::Bool diff --git a/noir/noir-repo/tooling/lsp/src/visibility.rs b/noir/noir-repo/tooling/lsp/src/visibility.rs index 6a21525f069..6724a0ba505 100644 --- a/noir/noir-repo/tooling/lsp/src/visibility.rs +++ b/noir/noir-repo/tooling/lsp/src/visibility.rs @@ -5,36 +5,13 @@ use noirc_frontend::{ graph::CrateId, hir::{ def_map::{CrateDefMap, ModuleDefId, ModuleId}, - resolution::visibility::can_reference_module_id, + resolution::visibility::item_in_module_is_visible, }, node_interner::NodeInterner, }; use crate::modules::get_parent_module; -/// Returns true if an item with the given visibility in the target module -/// is visible from the current module. For example: -/// -/// mod foo { -/// ^^^ <-- target module -/// pub(crate) fn bar() {} -/// ^^^^^^^^^^ <- visibility -/// } -pub(super) fn item_in_module_is_visible( - target_module_id: ModuleId, - current_module_id: ModuleId, - visibility: ItemVisibility, - def_maps: &BTreeMap, -) -> bool { - can_reference_module_id( - def_maps, - current_module_id.krate, - current_module_id.local_id, - target_module_id, - visibility, - ) -} - /// Returns true if the given ModuleDefId is visible from the current module, given its visibility. /// This will in turn check if the ModuleDefId parent modules are visible from the current module. /// If `defining_module` is Some, it will be considered as the parent of the item to check @@ -57,7 +34,7 @@ pub(super) fn module_def_id_is_visible( // Then check if it's visible, and upwards while let Some(module_id) = target_module_id { - if !item_in_module_is_visible(module_id, current_module_id, visibility, def_maps) { + if !item_in_module_is_visible(def_maps, current_module_id, module_id, visibility) { return false; } diff --git a/noir/noir-repo/tooling/nargo_cli/Cargo.toml b/noir/noir-repo/tooling/nargo_cli/Cargo.toml index 4e45749ddaf..317706bb237 100644 --- a/noir/noir-repo/tooling/nargo_cli/Cargo.toml +++ b/noir/noir-repo/tooling/nargo_cli/Cargo.toml @@ -88,6 +88,7 @@ sha3.workspace = true iai = "0.1.1" test-binary = "3.0.2" test-case.workspace = true +lazy_static.workspace = true light-poseidon = "0.2.0" diff --git a/noir/noir-repo/tooling/nargo_cli/build.rs b/noir/noir-repo/tooling/nargo_cli/build.rs index 94f74a06149..438eef687b8 100644 --- a/noir/noir-repo/tooling/nargo_cli/build.rs +++ b/noir/noir-repo/tooling/nargo_cli/build.rs @@ -130,7 +130,7 @@ fn generate_execution_success_tests(test_file: &mut File, test_data_dir: &Path) &test_dir, r#" nargo.arg("execute").arg("--force"); - + nargo.assert().success();"#, ); @@ -141,7 +141,7 @@ fn generate_execution_success_tests(test_file: &mut File, test_data_dir: &Path) &test_dir, r#" nargo.arg("execute").arg("--force").arg("--force-brillig"); - + nargo.assert().success();"#, ); } @@ -169,7 +169,7 @@ fn generate_execution_failure_tests(test_file: &mut File, test_data_dir: &Path) &test_dir, r#" nargo.arg("execute").arg("--force"); - + nargo.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not());"#, ); } @@ -196,7 +196,7 @@ fn generate_noir_test_success_tests(test_file: &mut File, test_data_dir: &Path) &test_dir, r#" nargo.arg("test"); - + nargo.assert().success();"#, ); } @@ -222,7 +222,7 @@ fn generate_noir_test_failure_tests(test_file: &mut File, test_data_dir: &Path) &test_dir, r#" nargo.arg("test"); - + nargo.assert().failure();"#, ); } @@ -273,7 +273,7 @@ fn generate_compile_success_empty_tests(test_file: &mut File, test_data_dir: &Pa &format!( r#" nargo.arg("info").arg("--json").arg("--force"); - + {assert_zero_opcodes}"#, ), ); @@ -353,7 +353,7 @@ fn generate_compile_failure_tests(test_file: &mut File, test_data_dir: &Path) { &test_name, &test_dir, r#"nargo.arg("compile").arg("--force"); - + nargo.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not());"#, ); } diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs index df3a4370cb0..304988ed516 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -192,7 +192,7 @@ fn compile_programs( let target_width = get_target_width(package.expression_width, compile_options.expression_width); let program = nargo::ops::transform_program(program, target_width); - // nargo::ops::check_program(&program)?; + nargo::ops::check_program(&program)?; save_program_to_file(&program.into(), &package.name, workspace.target_directory_path()); Ok(((), warnings)) diff --git a/noir/noir-repo/tooling/nargo_fmt/src/chunks.rs b/noir/noir-repo/tooling/nargo_fmt/src/chunks.rs index 0e55dfad3b7..fcef261284d 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/chunks.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/chunks.rs @@ -915,11 +915,18 @@ impl<'a> Formatter<'a> { self.write_indentation(); } Chunk::LeadingComment(text_chunk) => { - let ends_with_newline = text_chunk.string.ends_with('\n'); + let ends_with_multiple_newlines = text_chunk.string.ends_with("\n\n"); + let ends_with_newline = + ends_with_multiple_newlines || text_chunk.string.ends_with('\n'); self.write_chunk_lines(text_chunk.string.trim()); // Respect whether the leading comment had a newline before what comes next or not - if ends_with_newline { + if ends_with_multiple_newlines { + // Remove any indentation that could exist (we'll add it later) + self.buffer.trim_spaces(); + self.write_multiple_lines_without_skipping_whitespace_and_comments(); + self.write_indentation(); + } else if ends_with_newline { self.write_line_without_skipping_whitespace_and_comments(); self.write_indentation(); } else { diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter.rs index 4ae5443a2cc..9a9386e1911 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter.rs @@ -188,8 +188,7 @@ impl<'a> Formatter<'a> { pub(crate) fn write_token(&mut self, token: Token) { self.skip_comments_and_whitespace(); if self.token == token { - self.write_current_token(); - self.bump(); + self.write_current_token_and_bump(); } else { panic!("Expected token {:?}, got: {:?}", token, self.token); } @@ -200,6 +199,12 @@ impl<'a> Formatter<'a> { self.write(&self.token.to_string()); } + /// Writes the current token and advances to the next one + pub(crate) fn write_current_token_and_bump(&mut self) { + self.write(&self.token.to_string()); + self.bump(); + } + /// Writes the current token trimming its end but doesn't advance to the next one. /// Mainly used when writing comment lines, because we never want trailing spaces /// inside comments. diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/attribute.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/attribute.rs index c13ba2a8c4c..19d5730a546 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/attribute.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/attribute.rs @@ -1,30 +1,342 @@ -use noirc_frontend::token::Token; +use noirc_frontend::token::{ + Attribute, Attributes, FunctionAttribute, MetaAttribute, SecondaryAttribute, TestScope, Token, +}; + +use crate::chunks::ChunkGroup; use super::Formatter; impl<'a> Formatter<'a> { - pub(super) fn format_attributes(&mut self) { - loop { - self.skip_comments_and_whitespace(); + pub(super) fn format_attributes(&mut self, attributes: Attributes) { + let mut all_attributes = Vec::new(); + for attribute in attributes.secondary { + all_attributes.push(Attribute::Secondary(attribute)); + } + if let Some((function_attribute, index)) = attributes.function { + all_attributes.insert(index, Attribute::Function(function_attribute)); + } + for attribute in all_attributes { + self.format_attribute(attribute); + } + } - if let Token::Attribute(_) = self.token { - self.write_indentation(); - self.write_current_token(); - self.bump(); - self.write_line(); - } else { - break; + pub(super) fn format_secondary_attributes(&mut self, attributes: Vec) { + for attribute in attributes { + self.format_secondary_attribute(attribute); + } + } + + fn format_attribute(&mut self, attribute: Attribute) { + match attribute { + Attribute::Function(function_attribute) => { + self.format_function_attribute(function_attribute); + } + Attribute::Secondary(secondary_attribute) => { + self.format_secondary_attribute(secondary_attribute); } } } - pub(super) fn format_inner_attribute(&mut self) { + fn format_function_attribute(&mut self, attribute: FunctionAttribute) { self.skip_comments_and_whitespace(); - let Token::InnerAttribute(..) = self.token else { - panic!("Expected inner attribute, got {:?}", self.token); - }; self.write_indentation(); - self.write_current_token(); - self.bump(); + + if !matches!(self.token, Token::AttributeStart { .. }) { + panic!("Expected attribute start, got: {:?}", self.token); + } + + match attribute { + FunctionAttribute::Foreign(_) + | FunctionAttribute::Builtin(_) + | FunctionAttribute::Oracle(_) => self.format_one_arg_attribute(), + FunctionAttribute::Test(test_scope) => self.format_test_attribute(test_scope), + FunctionAttribute::Fold + | FunctionAttribute::NoPredicates + | FunctionAttribute::InlineAlways => self.format_no_args_attribute(), + } + + self.write_line(); + } + + pub(super) fn format_secondary_attribute(&mut self, attribute: SecondaryAttribute) { + self.skip_comments_and_whitespace(); + self.write_indentation(); + + if !matches!(self.token, Token::AttributeStart { .. }) { + panic!("Expected attribute start, got: {:?}", self.token); + } + + match attribute { + SecondaryAttribute::Deprecated(message) => { + self.format_deprecated_attribute(message); + } + SecondaryAttribute::ContractLibraryMethod + | SecondaryAttribute::Export + | SecondaryAttribute::Varargs + | SecondaryAttribute::UseCallersScope => { + self.format_no_args_attribute(); + } + SecondaryAttribute::Field(_) + | SecondaryAttribute::Abi(_) + | SecondaryAttribute::Allow(_) => { + self.format_one_arg_attribute(); + } + SecondaryAttribute::Tag(custom_attribute) => { + self.write_and_skip_span_without_formatting(custom_attribute.span); + } + SecondaryAttribute::Meta(meta_attribute) => { + self.format_meta_attribute(meta_attribute); + } + } + + self.write_line(); + } + + fn format_deprecated_attribute(&mut self, message: Option) { + self.write_current_token_and_bump(); // #[ + self.skip_comments_and_whitespace(); + if message.is_some() { + self.write_current_token_and_bump(); // deprecated + self.write_left_paren(); // ( + self.skip_comments_and_whitespace(); // message + self.write_current_token_and_bump(); // ) + self.write_right_paren(); + } else { + self.write_current_token_and_bump(); + } + self.write_right_bracket(); // ] + } + + fn format_test_attribute(&mut self, test_scope: TestScope) { + self.write_current_token_and_bump(); // #[ + self.skip_comments_and_whitespace(); + self.write_current_token_and_bump(); // test + + match test_scope { + TestScope::None => (), + TestScope::ShouldFailWith { reason: None } => { + self.write_left_paren(); // ( + self.skip_comments_and_whitespace(); + self.write_current_token_and_bump(); // should_fail + self.write_right_paren(); // ) + } + TestScope::ShouldFailWith { reason: Some(..) } => { + self.write_left_paren(); // ( + self.skip_comments_and_whitespace(); + self.write_current_token_and_bump(); // should_fail_with + self.write_space(); + self.write_token(Token::Assign); + self.write_space(); + self.skip_comments_and_whitespace(); + self.write_current_token_and_bump(); // "reason" + self.write_right_paren(); // ) + } + } + + self.write_right_bracket(); // ] + } + + fn format_meta_attribute(&mut self, meta_attribute: MetaAttribute) { + self.write_current_token_and_bump(); // #[ + self.skip_comments_and_whitespace(); + self.format_path(meta_attribute.name); + self.skip_comments_and_whitespace(); + if self.is_at(Token::LeftParen) { + let comments_count_before_arguments = self.written_comments_count; + let has_arguments = !meta_attribute.arguments.is_empty(); + + let mut chunk_formatter = self.chunk_formatter(); + let mut group = ChunkGroup::new(); + group.text(chunk_formatter.chunk(|formatter| { + formatter.write_left_paren(); + })); + chunk_formatter.format_expressions_separated_by_comma( + meta_attribute.arguments, + false, // force trailing comma + &mut group, + ); + group.text(chunk_formatter.chunk(|formatter| { + formatter.write_right_paren(); + })); + if has_arguments || self.written_comments_count > comments_count_before_arguments { + self.format_chunk_group(group); + } + } + self.write_right_bracket(); + } + + fn format_no_args_attribute(&mut self) { + self.write_current_token_and_bump(); // #[ + self.skip_comments_and_whitespace(); + self.write_current_token_and_bump(); // name + self.write_right_bracket(); // ] + } + + fn format_one_arg_attribute(&mut self) { + self.write_current_token_and_bump(); // #[ + self.skip_comments_and_whitespace(); + self.write_current_token_and_bump(); // name + self.write_left_paren(); // ( + loop { + self.skip_comments_and_whitespace(); + if self.is_at(Token::RightParen) { + self.write_right_paren(); + break; + } else { + self.write_current_token_and_bump(); + } + } + self.write_right_bracket(); // ] + } +} + +#[cfg(test)] +mod tests { + use crate::assert_format; + + fn assert_format_attribute(src: &str, expected: &str) { + let src = format!(" {src} fn foo() {{}}"); + let expected = format!("{expected}\nfn foo() {{}}\n"); + assert_format(&src, &expected); + } + + #[test] + fn format_inner_tag_attribute() { + let src = " #!['foo] "; + let expected = "#!['foo]\n"; + assert_format(src, expected); + } + + #[test] + fn format_deprecated_attribute() { + let src = " #[ deprecated ] "; + let expected = "#[deprecated]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_deprecated_attribute_with_message() { + let src = " #[ deprecated ( \"use something else\" ) ] "; + let expected = "#[deprecated(\"use something else\")]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_contract_library_method() { + let src = " #[ contract_library_method ] "; + let expected = "#[contract_library_method]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_export() { + let src = " #[ export ] "; + let expected = "#[export]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_varargs() { + let src = " #[ varargs ] "; + let expected = "#[varargs]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_use_callers_scope() { + let src = " #[ use_callers_scope ] "; + let expected = "#[use_callers_scope]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_field_attribute() { + let src = " #[ field ( bn256 ) ] "; + let expected = "#[field(bn256)]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_abi_attribute() { + let src = " #[ abi ( foo ) ] "; + let expected = "#[abi(foo)]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_allow_attribute() { + let src = " #[ allow ( unused_vars ) ] "; + let expected = "#[allow(unused_vars)]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_meta_attribute_without_arguments() { + let src = " #[ custom ] "; + let expected = "#[custom]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_meta_attribute_without_arguments_removes_parentheses() { + let src = " #[ custom ( ) ] "; + let expected = "#[custom]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_meta_attribute_without_arguments_but_comment() { + let src = " #[ custom ( /* nothing */ ) ] "; + let expected = "#[custom( /* nothing */ )]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_meta_attribute_with_arguments() { + let src = " #[ custom ( 1 , 2, [ 3, 4 ], ) ] "; + let expected = "#[custom(1, 2, [3, 4])]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_foreign_attribute() { + let src = " #[ foreign ( foo ) ] "; + let expected = "#[foreign(foo)]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_recursive_attribute() { + let src = " #[ recursive ] "; + let expected = "#[recursive]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_test_attribute() { + let src = " #[ test ] "; + let expected = "#[test]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_test_should_fail_attribute() { + let src = " #[ test ( should_fail )] "; + let expected = "#[test(should_fail)]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_test_should_fail_with_reason_attribute() { + let src = " #[ test ( should_fail_with=\"reason\" )] "; + let expected = "#[test(should_fail_with = \"reason\")]"; + assert_format_attribute(src, expected); + } + + #[test] + fn format_multiple_function_attributes() { + let src = " #[foo] #[test] #[bar] "; + let expected = "#[foo]\n#[test]\n#[bar]"; + assert_format_attribute(src, expected); } } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/buffer.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/buffer.rs index e4740311bf6..3e4bebef608 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/buffer.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/buffer.rs @@ -38,9 +38,10 @@ impl Buffer { } /// Trim spaces from the end of the buffer. - pub(super) fn trim_spaces(&mut self) { + pub(crate) fn trim_spaces(&mut self) { while self.buffer.ends_with(' ') { self.buffer.truncate(self.buffer.len() - 1); + self.current_line_width -= 1; } } @@ -48,6 +49,7 @@ impl Buffer { pub(super) fn trim_comma(&mut self) -> bool { if self.buffer.ends_with(',') { self.buffer.truncate(self.buffer.len() - 1); + self.current_line_width -= 1; true } else { false diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/comments_and_whitespace.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/comments_and_whitespace.rs index 547d33348b8..e20eb4291d1 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/comments_and_whitespace.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/comments_and_whitespace.rs @@ -162,8 +162,7 @@ impl<'a> Formatter<'a> { // will never write two consecutive spaces. self.write_space_without_skipping_whitespace_and_comments(); } - self.write_current_token(); - self.bump(); + self.write_current_token_and_bump(); passed_whitespace = false; last_was_block_comment = true; self.written_comments_count += 1; diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/expression.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/expression.rs index bff1799a298..0ac4c98bb95 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/expression.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/expression.rs @@ -1133,11 +1133,15 @@ impl<'a, 'b> ChunkFormatter<'a, 'b> { if count > 0 { // If newlines follow, we first add a line, then add the comment chunk group.lines(count > 1); - group.leading_comment(self.skip_comments_and_whitespace_chunk()); + group.leading_comment(self.chunk(|formatter| { + formatter.skip_comments_and_whitespace_writing_multiple_lines_if_found(); + })); ignore_next = self.ignore_next; } else { // Otherwise, add the comment first as it's a trailing comment - group.trailing_comment(self.skip_comments_and_whitespace_chunk()); + group.trailing_comment(self.chunk(|formatter| { + formatter.skip_comments_and_whitespace_writing_multiple_lines_if_found(); + })); ignore_next = self.ignore_next; group.line(); } @@ -1146,6 +1150,20 @@ impl<'a, 'b> ChunkFormatter<'a, 'b> { self.format_statement(statement, group, ignore_next); } + // See how many newlines follow the last statement + let count = self.following_newlines_count(); + + group.text(self.chunk(|formatter| { + formatter.skip_whitespace(); + })); + + // After skipping whitespace we check if there's a comment. If so, we respect + // how many lines were before that comment. + if count > 0 && matches!(self.token, Token::LineComment(..) | Token::BlockComment(..)) { + group.lines(count > 1); + } + + // Finally format the comment, if any group.text(self.chunk(|formatter| { formatter.skip_comments_and_whitespace(); })); diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/function.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/function.rs index 1dc9ead42e0..fd6977df613 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/function.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/function.rs @@ -3,13 +3,14 @@ use noirc_frontend::{ BlockExpression, FunctionReturnType, Ident, ItemVisibility, NoirFunction, Param, UnresolvedGenerics, UnresolvedTraitConstraint, Visibility, }, - token::{Keyword, Token}, + token::{Attributes, Keyword, Token}, }; use super::Formatter; use crate::chunks::{ChunkGroup, TextChunk}; pub(super) struct FunctionToFormat { + pub(super) attributes: Attributes, pub(super) visibility: ItemVisibility, pub(super) name: Ident, pub(super) generics: UnresolvedGenerics, @@ -23,6 +24,7 @@ pub(super) struct FunctionToFormat { impl<'a> Formatter<'a> { pub(super) fn format_function(&mut self, func: NoirFunction) { self.format_function_impl(FunctionToFormat { + attributes: func.def.attributes, visibility: func.def.visibility, name: func.def.name, generics: func.def.generics, @@ -37,7 +39,7 @@ impl<'a> Formatter<'a> { pub(super) fn format_function_impl(&mut self, func: FunctionToFormat) { let has_where_clause = !func.where_clause.is_empty(); - self.format_attributes(); + self.format_attributes(func.attributes); self.write_indentation(); self.format_function_modifiers(func.visibility); self.write_keyword(Keyword::Fn); @@ -278,16 +280,12 @@ impl<'a> Formatter<'a> { } pub(super) fn format_function_body(&mut self, body: BlockExpression) { - if body.is_empty() { - self.format_empty_block_contents(); - } else { - let mut group = ChunkGroup::new(); - self.chunk_formatter().format_non_empty_block_expression_contents( - body, true, // force multiple lines - &mut group, - ); - self.format_chunk_group(group); - } + let mut group = ChunkGroup::new(); + self.chunk_formatter().format_block_expression_contents( + body, true, // force multiple newlines + &mut group, + ); + self.format_chunk_group(group); } } @@ -535,4 +533,46 @@ fn baz() { let z = 3 ; "; assert_format(src, expected); } + + #[test] + fn comment_in_body_respects_newlines() { + let src = "fn foo() { + let x = 1; + + // comment + + let y = 2; +} +"; + let expected = src; + assert_format(src, expected); + } + + #[test] + fn final_comment_in_body_respects_newlines() { + let src = "fn foo() { + let x = 1; + + let y = 2; + + // comment +} +"; + let expected = src; + assert_format(src, expected); + } + + #[test] + fn initial_comment_in_body_respects_newlines() { + let src = "fn foo() { + // comment + + let x = 1; + + let y = 2; +} +"; + let expected = src; + assert_format(src, expected); + } } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/item.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/item.rs index 77f1cd10cbc..521e476fe71 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/item.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/item.rs @@ -73,7 +73,7 @@ impl<'a> Formatter<'a> { ItemKind::Submodules(parsed_sub_module) => { self.format_submodule(parsed_sub_module); } - ItemKind::InnerAttribute(..) => self.format_inner_attribute(), + ItemKind::InnerAttribute(attribute) => self.format_secondary_attribute(attribute), } } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/module.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/module.rs index 3df9b7e0c90..e07d22c7586 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/module.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/module.rs @@ -6,9 +6,7 @@ use super::Formatter; impl<'a> Formatter<'a> { pub(super) fn format_module_declaration(&mut self, module_declaration: ModuleDeclaration) { - if !module_declaration.outer_attributes.is_empty() { - self.format_attributes(); - } + self.format_secondary_attributes(module_declaration.outer_attributes); self.write_indentation(); self.format_item_visibility(module_declaration.visibility); self.write_keyword(Keyword::Mod); @@ -18,9 +16,7 @@ impl<'a> Formatter<'a> { } pub(super) fn format_submodule(&mut self, submodule: ParsedSubModule) { - if !submodule.outer_attributes.is_empty() { - self.format_attributes(); - } + self.format_secondary_attributes(submodule.outer_attributes); self.write_indentation(); self.format_item_visibility(submodule.visibility); if submodule.is_contract { diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/statement.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/statement.rs index 28107294909..50c286ff161 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/statement.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/statement.rs @@ -16,7 +16,15 @@ impl<'a, 'b> ChunkFormatter<'a, 'b> { group: &mut ChunkGroup, mut ignore_next: bool, ) { - group.leading_comment(self.skip_comments_and_whitespace_chunk()); + // First skip any whitespace to avoid writing multiple lines + group.text(self.chunk(|formatter| { + formatter.skip_whitespace(); + })); + + // Now write any leading comment respecting multiple newlines after them + group.leading_comment(self.chunk(|formatter| { + formatter.skip_comments_and_whitespace_writing_multiple_lines_if_found(); + })); ignore_next |= self.ignore_next; @@ -102,9 +110,7 @@ impl<'a, 'b> ChunkFormatter<'a, 'b> { let mut group = ChunkGroup::new(); group.text(self.chunk(|formatter| { - if !attributes.is_empty() { - formatter.format_attributes(); - } + formatter.format_secondary_attributes(attributes); formatter.write_keyword(keyword); formatter.write_space(); formatter.format_pattern(pattern); @@ -692,4 +698,16 @@ mod tests { "; assert_format_with_max_width(src, expected, " a_long_variable = foo(1, 2);".len() - 1); } + + #[test] + fn long_let_preceded_by_two_newlines() { + let src = "fn foo() { + let y = 0; + + let x = 123456; +} +"; + let expected = src; + assert_format_with_max_width(src, expected, " let x = 123456;".len()); + } } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/structs.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/structs.rs index 54bfc88264d..c26ab552f30 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/structs.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/structs.rs @@ -8,9 +8,7 @@ use crate::chunks::ChunkGroup; impl<'a> Formatter<'a> { pub(super) fn format_struct(&mut self, noir_struct: NoirStruct) { - if !noir_struct.attributes.is_empty() { - self.format_attributes(); - } + self.format_secondary_attributes(noir_struct.attributes); self.write_indentation(); self.format_item_visibility(noir_struct.visibility); self.write_keyword(Keyword::Struct); diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/traits.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/traits.rs index 1379596b483..9a6b84c6537 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/traits.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/traits.rs @@ -1,15 +1,13 @@ use noirc_frontend::{ ast::{NoirTrait, Param, Pattern, TraitItem, Visibility}, - token::{Keyword, Token}, + token::{Attributes, Keyword, Token}, }; use super::{function::FunctionToFormat, Formatter}; impl<'a> Formatter<'a> { pub(super) fn format_trait(&mut self, noir_trait: NoirTrait) { - if !noir_trait.attributes.is_empty() { - self.format_attributes(); - } + self.format_secondary_attributes(noir_trait.attributes); self.write_indentation(); self.format_item_visibility(noir_trait.visibility); self.write_keyword(Keyword::Trait); @@ -91,6 +89,7 @@ impl<'a> Formatter<'a> { .collect(); let func = FunctionToFormat { + attributes: Attributes::empty(), visibility, name, generics, diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/type_expression.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/type_expression.rs index 87ba1430f10..95b0c045156 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/type_expression.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/type_expression.rs @@ -14,14 +14,12 @@ impl<'a> Formatter<'a> { match type_expr { UnresolvedTypeExpression::Variable(path) => self.format_path(path), UnresolvedTypeExpression::Constant(..) => { - self.write_current_token(); - self.bump(); + self.write_current_token_and_bump(); } UnresolvedTypeExpression::BinaryOperation(lhs, _operator, rhs, _span) => { self.format_type_expression(*lhs); self.write_space(); - self.write_current_token(); - self.bump(); + self.write_current_token_and_bump(); self.write_space(); self.format_type_expression(*rhs); } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/types.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/types.rs index d2b5c4ab793..e52704ddaa7 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/types.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/types.rs @@ -18,8 +18,7 @@ impl<'a> Formatter<'a> { self.write_keyword(Keyword::Bool); } UnresolvedTypeData::Integer(..) | UnresolvedTypeData::FieldElement => { - self.write_current_token(); - self.bump(); + self.write_current_token_and_bump(); } UnresolvedTypeData::Array(type_expr, typ) => { self.write_left_bracket(); @@ -145,8 +144,7 @@ impl<'a> Formatter<'a> { } } UnresolvedTypeData::Quoted(..) => { - self.write_current_token(); - self.bump(); + self.write_current_token_and_bump(); } UnresolvedTypeData::AsTraitPath(as_trait_path) => { self.format_as_trait_path(*as_trait_path); diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/visibility.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/visibility.rs index d1068aa4d05..27441b977bb 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/visibility.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/visibility.rs @@ -37,8 +37,7 @@ impl<'a> Formatter<'a> { self.write_keyword(Keyword::CallData); self.write_left_paren(); self.skip_comments_and_whitespace(); - self.write_current_token(); - self.bump(); + self.write_current_token_and_bump(); self.skip_comments_and_whitespace(); self.write_right_paren(); self.write_space(); diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/parens.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/parens.nr index 5ff0acf7330..2eaf3838ed6 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/expected/parens.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/parens.nr @@ -25,6 +25,7 @@ fn main(x: u64, y: pub u64) { ( /*a*/ + ( // test 1 diff --git a/noir/noir-repo/tooling/noir_codegen/package.json b/noir/noir-repo/tooling/noir_codegen/package.json index 24bc6368572..7ec8ba3df64 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.37.0", + "version": "0.38.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/noir/noir-repo/tooling/noir_js/package.json b/noir/noir-repo/tooling/noir_js/package.json index 1d3da4e7a54..a3e5777c3d3 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.37.0", + "version": "0.38.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/noir/noir-repo/tooling/noir_js_types/package.json b/noir/noir-repo/tooling/noir_js_types/package.json index 5192a6cd02d..0eeb900253a 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.37.0", + "version": "0.38.0", "license": "(MIT OR Apache-2.0)", "homepage": "https://noir-lang.org/", "repository": { diff --git a/noir/noir-repo/tooling/noirc_abi_wasm/package.json b/noir/noir-repo/tooling/noirc_abi_wasm/package.json index 7e4500ec29b..ff121326d1a 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.37.0", + "version": "0.38.0", "license": "(MIT OR Apache-2.0)", "homepage": "https://noir-lang.org/", "repository": { diff --git a/spartan/aztec-network/files/config/deploy-l1-contracts.sh b/spartan/aztec-network/files/config/deploy-l1-contracts.sh index 114820ff4a1..66cc107f251 100644 --- a/spartan/aztec-network/files/config/deploy-l1-contracts.sh +++ b/spartan/aztec-network/files/config/deploy-l1-contracts.sh @@ -1,15 +1,20 @@ #!/bin/sh set -exu +CHAIN_ID=$1 + alias aztec='node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js' +# Use default account, it is funded on our dev machine +export PRIVATE_KEY="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + # Run the deploy-l1-contracts command and capture the output output="" # if INIT_VALIDATORS is true, then we need to pass the validators flag to the deploy-l1-contracts command if [ "$INIT_VALIDATORS" = "true" ]; then - output=$(aztec deploy-l1-contracts --validators $1) + output=$(aztec deploy-l1-contracts --validators $2 --l1-chain-id $CHAIN_ID) else - output=$(aztec deploy-l1-contracts) + output=$(aztec deploy-l1-contracts --l1-chain-id $CHAIN_ID) fi echo "$output" diff --git a/spartan/aztec-network/files/config/genesis.json b/spartan/aztec-network/files/config/genesis.json new file mode 100644 index 00000000000..e899e7f8255 --- /dev/null +++ b/spartan/aztec-network/files/config/genesis.json @@ -0,0 +1,179 @@ +{ + "config": { + "chainId": 1337, + "homesteadBlock":0, + "eip150Block":0, + "eip155Block":0, + "eip158Block":0, + "byzantiumBlock":0, + "constantinopleBlock":0, + "petersburgBlock":0, + "istanbulBlock":0, + "muirGlacierBlock":0, + "berlinBlock":0, + "londonBlock":0, + "arrowGlacierBlock":0, + "grayGlacierBlock":0, + "mergeNetsplitBlock":0, + "bedrockBlock":0, + "regolithTime":0, + "shanghaiTime":0, + "cancunTime":0, + "terminalTotalDifficulty":0, + "terminalTotalDifficultyPassed":true + }, + "nonce": "0x42", + "timestamp": "0x0", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x1388", + "difficulty": "0x400000000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": { + "balance": "0x56bc75e2d63100000" + }, + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8": { + "balance": "0x56bc75e2d63100000" + }, + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": { + "balance": "0x56bc75e2d63100000" + }, + "0x90F79bf6EB2c4f870365E785982E1f101E93b906": { + "balance": "0x56bc75e2d63100000" + }, + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65": { + "balance": "0x56bc75e2d63100000" + }, + "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc": { + "balance": "0x56bc75e2d63100000" + }, + "0x976EA74026E726554dB657fA54763abd0C3a0aa9": { + "balance": "0x56bc75e2d63100000" + }, + "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955": { + "balance": "0x56bc75e2d63100000" + }, + "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f": { + "balance": "0x56bc75e2d63100000" + }, + "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720": { + "balance": "0x56bc75e2d63100000" + }, + "0xBcd4042DE499D14e55001CcbB24a551F3b954096": { + "balance": "0x56bc75e2d63100000" + }, + "0x71bE63f3384f5fb98995898A86B02Fb2426c5788": { + "balance": "0x56bc75e2d63100000" + }, + "0xFABB0ac9d68B0B445fB7357272Ff202C5651694a": { + "balance": "0x56bc75e2d63100000" + }, + "0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec": { + "balance": "0x56bc75e2d63100000" + }, + "0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097": { + "balance": "0x56bc75e2d63100000" + }, + "0xcd3B766CCDd6AE721141F452C550Ca635964ce71": { + "balance": "0x56bc75e2d63100000" + }, + "0x2546BcD3c84621e976D8185a91A922aE77ECEc30": { + "balance": "0x56bc75e2d63100000" + }, + "0xbDA5747bFD65F08deb54cb465eB87D40e51B197E": { + "balance": "0x56bc75e2d63100000" + }, + "0xdD2FD4581271e230360230F9337D5c0430Bf44C0": { + "balance": "0x56bc75e2d63100000" + }, + "0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199": { + "balance": "0x56bc75e2d63100000" + }, + "0x09DB0a93B389bEF724429898f539AEB7ac2Dd55f": { + "balance": "0x56bc75e2d63100000" + }, + "0x02484cb50AAC86Eae85610D6f4Bf026f30f6627D": { + "balance": "0x56bc75e2d63100000" + }, + "0x08135Da0A343E492FA2d4282F2AE34c6c5CC1BbE": { + "balance": "0x56bc75e2d63100000" + }, + "0x5E661B79FE2D3F6cE70F5AAC07d8Cd9abb2743F1": { + "balance": "0x56bc75e2d63100000" + }, + "0x61097BA76cD906d2ba4FD106E757f7Eb455fc295": { + "balance": "0x56bc75e2d63100000" + }, + "0xDf37F81dAAD2b0327A0A50003740e1C935C70913": { + "balance": "0x56bc75e2d63100000" + }, + "0x553BC17A05702530097c3677091C5BB47a3a7931": { + "balance": "0x56bc75e2d63100000" + }, + "0x87BdCE72c06C21cd96219BD8521bDF1F42C78b5e": { + "balance": "0x56bc75e2d63100000" + }, + "0x40Fc963A729c542424cD800349a7E4Ecc4896624": { + "balance": "0x56bc75e2d63100000" + }, + "0x9DCCe783B6464611f38631e6C851bf441907c710": { + "balance": "0x56bc75e2d63100000" + }, + "0x1BcB8e569EedAb4668e55145Cfeaf190902d3CF2": { + "balance": "0x56bc75e2d63100000" + }, + "0x8263Fce86B1b78F95Ab4dae11907d8AF88f841e7": { + "balance": "0x56bc75e2d63100000" + }, + "0xcF2d5b3cBb4D7bF04e3F7bFa8e27081B52191f91": { + "balance": "0x56bc75e2d63100000" + }, + "0x86c53Eb85D0B7548fea5C4B4F82b4205C8f6Ac18": { + "balance": "0x56bc75e2d63100000" + }, + "0x1aac82773CB722166D7dA0d5b0FA35B0307dD99D": { + "balance": "0x56bc75e2d63100000" + }, + "0x2f4f06d218E426344CFE1A83D53dAd806994D325": { + "balance": "0x56bc75e2d63100000" + }, + "0x1003ff39d25F2Ab16dBCc18EcE05a9B6154f65F4": { + "balance": "0x56bc75e2d63100000" + }, + "0x9eAF5590f2c84912A08de97FA28d0529361Deb9E": { + "balance": "0x56bc75e2d63100000" + }, + "0x11e8F3eA3C6FcF12EcfF2722d75CEFC539c51a1C": { + "balance": "0x56bc75e2d63100000" + }, + "0x7D86687F980A56b832e9378952B738b614A99dc6": { + "balance": "0x56bc75e2d63100000" + }, + "0x9eF6c02FB2ECc446146E05F1fF687a788a8BF76d": { + "balance": "0x56bc75e2d63100000" + }, + "0x08A2DE6F3528319123b25935C92888B16db8913E": { + "balance": "0x56bc75e2d63100000" + }, + "0xe141C82D99D85098e03E1a1cC1CdE676556fDdE0": { + "balance": "0x56bc75e2d63100000" + }, + "0x4b23D303D9e3719D6CDf8d172Ea030F80509ea15": { + "balance": "0x56bc75e2d63100000" + }, + "0xC004e69C5C04A223463Ff32042dd36DabF63A25a": { + "balance": "0x56bc75e2d63100000" + }, + "0x5eb15C0992734B5e77c888D713b4FC67b3D679A2": { + "balance": "0x56bc75e2d63100000" + }, + "0x7Ebb637fd68c523613bE51aad27C35C4DB199B9c": { + "balance": "0x56bc75e2d63100000" + }, + "0x3c3E2E178C69D4baD964568415a0f0c84fd6320A": { + "balance": "0x56bc75e2d63100000" + } + }, + "number": "0x0" + } \ No newline at end of file diff --git a/spartan/aztec-network/templates/anvil.yaml b/spartan/aztec-network/templates/anvil.yaml deleted file mode 100644 index 2661769b6e1..00000000000 --- a/spartan/aztec-network/templates/anvil.yaml +++ /dev/null @@ -1,146 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "aztec-network.fullname" . }}-ethereum - labels: - {{- include "aztec-network.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.ethereum.replicas }} - selector: - matchLabels: - {{- include "aztec-network.selectorLabels" . | nindent 6 }} - app: ethereum - template: - metadata: - labels: - {{- include "aztec-network.selectorLabels" . | nindent 8 }} - app: ethereum - spec: - containers: - - name: ethereum - image: "{{ .Values.images.foundry.image }}" - imagePullPolicy: {{ .Values.images.foundry.pullPolicy }} - command: ["/bin/sh", "/scripts/run-anvil.sh"] - ports: - - containerPort: {{ .Values.ethereum.service.port }} - name: anvil - readinessProbe: - exec: - command: - - sh - - -c - - | - wget -qO- --post-data='{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}' \ - --header='Content-Type: application/json' \ - 127.0.0.1:{{ .Values.ethereum.service.port }} \ - | grep -q '"result":"anvil' - initialDelaySeconds: {{ .Values.ethereum.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.ethereum.readinessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.ethereum.readinessProbe.timeoutSeconds }} - successThreshold: {{ .Values.ethereum.readinessProbe.successThreshold }} - failureThreshold: {{ .Values.ethereum.readinessProbe.failureThreshold }} - volumeMounts: - - name: shared-volume - mountPath: /state_exports - - name: scripts - mountPath: /scripts - resources: - {{- toYaml .Values.ethereum.resources | nindent 12 }} - volumes: - - name: shared-volume - persistentVolumeClaim: - claimName: {{ include "aztec-network.fullname" . }}-ethereum-pvc - - name: scripts - configMap: - name: {{ include "aztec-network.fullname" . }}-ethereum-scripts - defaultMode: 0755 ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: {{ include "aztec-network.fullname" . }}-ethereum-pvc - labels: - {{- include "aztec-network.labels" . | nindent 4 }} -spec: - accessModes: ["ReadWriteOnce"] - resources: - requests: - storage: {{ .Values.ethereum.storage }} ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "aztec-network.fullname" . }}-ethereum-scripts -data: - run-anvil.sh: | - #!/bin/sh - - STATE_FILE="/state_exports/state.json" - - if [ -f "$STATE_FILE" ]; then - echo "State file found. Loading existing state." - anvil \ - --host 0.0.0.0 \ - --load-state /state_exports/ \ - --dump-state /state_exports/ \ - {{ include "helpers.flag" (list "block-time" .Values.ethereum.blockTime) }} \ - {{ include "helpers.flag" (list "chain-id" .Values.ethereum.chainId) }} \ - {{ include "helpers.flag" (list "gas-limit" .Values.ethereum.gasLimit) }} \ - {{ include "helpers.flag" (list "fork-url" .Values.ethereum.forkUrl) }} \ - {{ include "helpers.flag" (list "fork-block-number" .Values.ethereum.forkBlockNumber) }} \ - {{ include "helpers.flag" (list "accounts" .Values.validator.replicas) }} \ - -p {{ .Values.ethereum.service.port }} - else - echo "No state file found. Starting with a fresh state and enabling state dumping." - anvil \ - --host 0.0.0.0 \ - --dump-state /state_exports/ \ - {{ include "helpers.flag" (list "block-time" .Values.ethereum.blockTime) }} \ - {{ include "helpers.flag" (list "chain-id" .Values.ethereum.chainId) }} \ - {{ include "helpers.flag" (list "gas-limit" .Values.ethereum.gasLimit) }} \ - {{ include "helpers.flag" (list "fork-url" .Values.ethereum.forkUrl) }} \ - {{ include "helpers.flag" (list "fork-block-number" .Values.ethereum.forkBlockNumber) }} \ - {{ include "helpers.flag" (list "accounts" .Values.validator.replicas) }} \ - -p {{ .Values.ethereum.service.port }} - fi ---- -apiVersion: v1 -kind: Service -metadata: - name: {{ include "aztec-network.fullname" . }}-ethereum - labels: - {{- include "aztec-network.labels" . | nindent 4 }} -spec: - type: {{ .Values.ethereum.service.type }} - selector: - {{- include "aztec-network.selectorLabels" . | nindent 4 }} - app: ethereum - ports: - - protocol: TCP - port: {{ .Values.ethereum.service.port }} - targetPort: {{ .Values.ethereum.service.targetPort }} - {{- if and (eq .Values.ethereum.service.type "NodePort") .Values.ethereum.service.nodePort }} - nodePort: {{ .Values.ethereum.service.nodePort }} - {{- end }} ---- -{{if .Values.network.public }} -apiVersion: v1 -kind: Service -metadata: - name: {{ include "aztec-network.fullname" . }}-ethereum-lb - labels: - {{- include "aztec-network.labels" . | nindent 4 }} -spec: - type: LoadBalancer - selector: - {{- include "aztec-network.selectorLabels" . | nindent 4 }} - app: ethereum - ports: - - protocol: TCP - port: {{ .Values.ethereum.service.port }} - targetPort: {{ .Values.ethereum.service.targetPort }} - {{- if and (eq .Values.ethereum.service.type "NodePort") .Values.ethereum.service.nodePort }} - nodePort: {{ .Values.ethereum.service.nodePort }} - {{- end }} ---- -{{ end }} \ No newline at end of file diff --git a/spartan/aztec-network/templates/boot-node.yaml b/spartan/aztec-network/templates/boot-node.yaml index d497f96860a..5bf506ff585 100644 --- a/spartan/aztec-network/templates/boot-node.yaml +++ b/spartan/aztec-network/templates/boot-node.yaml @@ -26,7 +26,7 @@ spec: - | until curl -s -X POST -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}' \ - {{ include "aztec-network.ethereumHost" . }} | grep -q anvil; do + {{ include "aztec-network.ethereumHost" . }} | grep -q reth; do echo "Waiting for Ethereum node..." sleep 5 done @@ -45,7 +45,7 @@ spec: [ "/bin/sh", "-c", - "cp /scripts/deploy-contracts.sh /tmp/deploy-contracts.sh && chmod +x /tmp/deploy-contracts.sh && /tmp/deploy-contracts.sh \"{{ join "," .Values.validator.validatorAddresses }}\"" + "cp /scripts/deploy-contracts.sh /tmp/deploy-contracts.sh && chmod +x /tmp/deploy-contracts.sh && /tmp/deploy-contracts.sh {{ .Values.ethereum.chainId }} \"{{ join "," .Values.validator.validatorAddresses }}\"" ] volumeMounts: - name: scripts-output @@ -57,6 +57,14 @@ spec: value: {{ include "aztec-network.ethereumHost" . | quote }} - name: INIT_VALIDATORS value: {{ not .Values.validator.external | quote }} + - name: ETHEREUM_SLOT_DURATION + value: "{{ .Values.ethereum.blockTime }}" + - name: AZTEC_SLOT_DURATION + value: "{{ .Values.aztec.slotDuration }}" + - name: AZTEC_EPOCH_DURATION + value: "{{ .Values.aztec.epochDuration }}" + - name: AZTEC_EPOCH_PROOF_CLAIM_WINDOW_IN_L2_SLOTS + value: "{{ .Values.aztec.epochProofClaimWindow }}" {{- end }} containers: - name: boot-node @@ -112,6 +120,8 @@ spec: value: "{{ .Values.bootNode.coinbaseAddress }}" - name: VALIDATOR_DISABLED value: "{{ .Values.bootNode.validator.disabled }}" + - name: L1_CHAIN_ID + value: "{{ .Values.ethereum.chainId }}" - name: SEQ_MAX_SECONDS_BETWEEN_BLOCKS value: "{{ .Values.bootNode.sequencer.maxSecondsBetweenBlocks }}" - name: SEQ_MIN_TX_PER_BLOCK @@ -142,6 +152,16 @@ spec: value: {{ include "aztec-network.otelCollectorTracesEndpoint" . | quote }} - name: OTEL_EXPORTER_OTLP_LOGS_ENDPOINT value: {{ include "aztec-network.otelCollectorLogsEndpoint" . | quote }} + - name: PROVER_REAL_PROOFS + value: "{{ .Values.bootNode.realProofs }}" + - name: ETHEREUM_SLOT_DURATION + value: "{{ .Values.ethereum.blockTime }}" + - name: AZTEC_SLOT_DURATION + value: "{{ .Values.aztec.slotDuration }}" + - name: AZTEC_EPOCH_DURATION + value: "{{ .Values.aztec.epochDuration }}" + - name: AZTEC_EPOCH_PROOF_CLAIM_WINDOW_IN_L2_SLOTS + value: "{{ .Values.aztec.epochProofClaimWindow }}" ports: - containerPort: {{ .Values.bootNode.service.nodePort }} - containerPort: {{ .Values.bootNode.service.p2pTcpPort }} diff --git a/spartan/aztec-network/templates/prover-agent.yaml b/spartan/aztec-network/templates/prover-agent.yaml index 39ea5d1729c..f929daa4b79 100644 --- a/spartan/aztec-network/templates/prover-agent.yaml +++ b/spartan/aztec-network/templates/prover-agent.yaml @@ -17,6 +17,11 @@ spec: {{- include "aztec-network.selectorLabels" . | nindent 8 }} app: prover-agent spec: + {{- if .Values.proverAgent.nodeSelector }} + nodeSelector: + {{- toYaml .Values.proverAgent.nodeSelector | nindent 8 }} + {{- end }} + initContainers: - name: wait-for-prover-node image: {{ .Values.images.curl.image }} @@ -38,7 +43,7 @@ spec: {{- end }} env: - name: PROVER_JOB_SOURCE_URL - value: http://{{ include "aztec-network.fullname" . }}-prover-node.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.proverNode.service.nodePort }} + value: "http://{{ include "aztec-network.fullname" . }}-prover-node.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.proverNode.service.nodePort }}" containers: - name: prover-agent image: "{{ .Values.images.aztec.image }}" @@ -57,7 +62,7 @@ spec: - name: PROVER_REAL_PROOFS value: "{{ .Values.proverAgent.realProofs }}" - name: PROVER_JOB_SOURCE_URL - value: http://{{ include "aztec-network.fullname" . }}-prover-node.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.proverNode.service.nodePort }} + value: "http://{{ include "aztec-network.fullname" . }}-prover-node.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.proverNode.service.nodePort }}" - name: PROVER_AGENT_ENABLED value: "true" - name: PROVER_AGENT_CONCURRENCY @@ -72,4 +77,6 @@ spec: value: {{ include "aztec-network.otelCollectorTracesEndpoint" . | quote }} - name: OTEL_EXPORTER_OTLP_LOGS_ENDPOINT value: {{ include "aztec-network.otelCollectorLogsEndpoint" . | quote }} + resources: + {{- toYaml .Values.proverAgent.resources | nindent 12 }} {{- end }} diff --git a/spartan/aztec-network/templates/prover-node.yaml b/spartan/aztec-network/templates/prover-node.yaml index a3d5cf3f187..bd2f305710b 100644 --- a/spartan/aztec-network/templates/prover-node.yaml +++ b/spartan/aztec-network/templates/prover-node.yaml @@ -26,7 +26,7 @@ spec: - | until curl -s -X POST -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}' \ - {{ include "aztec-network.ethereumHost" . }} | grep -q anvil; do + {{ include "aztec-network.ethereumHost" . }} | grep -q reth; do echo "Waiting for Ethereum node..." sleep 5 done @@ -102,6 +102,8 @@ spec: value: {{ include "aztec-network.otelCollectorTracesEndpoint" . | quote }} - name: OTEL_EXPORTER_OTLP_LOGS_ENDPOINT value: {{ include "aztec-network.otelCollectorLogsEndpoint" . | quote }} + - name: L1_CHAIN_ID + value: "{{ .Values.ethereum.chainId }}" - name: P2P_ENABLED value: "{{ .Values.proverNode.p2pEnabled }}" - name: P2P_TCP_ANNOUNCE_ADDR @@ -120,6 +122,14 @@ spec: value: "0.0.0.0:{{ .Values.proverNode.service.p2pTcpPort }}" - name: P2P_UDP_LISTEN_ADDR value: "0.0.0.0:{{ .Values.proverNode.service.p2pUdpPort }}" + - name: ETHEREUM_SLOT_DURATION + value: "{{ .Values.ethereum.blockTime }}" + - name: AZTEC_SLOT_DURATION + value: "{{ .Values.aztec.slotDuration }}" + - name: AZTEC_EPOCH_DURATION + value: "{{ .Values.aztec.epochDuration }}" + - name: AZTEC_EPOCH_PROOF_CLAIM_WINDOW_IN_L2_SLOTS + value: "{{ .Values.aztec.epochProofClaimWindow }}" ports: - containerPort: {{ .Values.proverNode.service.nodePort }} - containerPort: {{ .Values.proverNode.service.p2pTcpPort }} diff --git a/spartan/aztec-network/templates/reth.yaml b/spartan/aztec-network/templates/reth.yaml new file mode 100644 index 00000000000..5c2dea00d93 --- /dev/null +++ b/spartan/aztec-network/templates/reth.yaml @@ -0,0 +1,128 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "aztec-network.fullname" . }}-ethereum + labels: + {{- include "aztec-network.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.ethereum.replicas }} + selector: + matchLabels: + {{- include "aztec-network.selectorLabels" . | nindent 6 }} + app: ethereum + template: + metadata: + labels: + {{- include "aztec-network.selectorLabels" . | nindent 8 }} + app: ethereum + spec: + containers: + - name: ethereum + image: "{{ .Values.images.reth.image }}" + imagePullPolicy: {{ .Values.images.reth.pullPolicy }} + command: ["/bin/sh", "-c"] + args: + - >- + reth node {{ include "helpers.flag" (list "http.addr" "0.0.0.0") }} + {{- include "helpers.flag" (list "http.port" .Values.ethereum.service.port) }} + {{- include "helpers.flag" (list "builder.gaslimit" .Values.ethereum.gasLimit) }} + {{- include "helpers.flag" (list "txpool.gas-limit" .Values.ethereum.gasLimit) }} + {{- include "helpers.flag" (list "dev.block-time" .Values.ethereum.blockTime) }} + --chain /genesis/genesis.json + --datadir /data + --dev + ports: + - containerPort: {{ .Values.ethereum.service.port }} + name: reth + volumeMounts: + - name: shared-volume + mountPath: /data + - name: genesis + mountPath: /genesis + # readinessProbe: + # exec: + # command: + # - sh + # - -c + # - | + # wget -qO- --post-data='{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}' \ + # --header='Content-Type: application/json' \ + # 127.0.0.1:{{ .Values.ethereum.service.port }} \ + # | grep -q 'reth' + # initialDelaySeconds: {{ .Values.ethereum.readinessProbe.initialDelaySeconds }} + # periodSeconds: {{ .Values.ethereum.readinessProbe.periodSeconds }} + # timeoutSeconds: {{ .Values.ethereum.readinessProbe.timeoutSeconds }} + # successThreshold: {{ .Values.ethereum.readinessProbe.successThreshold }} + # failureThreshold: {{ .Values.ethereum.readinessProbe.failureThreshold }} + resources: + {{- toYaml .Values.ethereum.resources | nindent 12 }} + volumes: + - name: shared-volume + persistentVolumeClaim: + claimName: {{ include "aztec-network.fullname" . }}-ethereum-pvc + - name: genesis + configMap: + name: {{ include "aztec-network.fullname" . }}-reth-genesis +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "aztec-network.fullname" . }}-ethereum + labels: + {{- include "aztec-network.labels" . | nindent 4 }} +spec: + type: {{ .Values.ethereum.service.type }} + selector: + {{- include "aztec-network.selectorLabels" . | nindent 4 }} + app: ethereum + ports: + - protocol: TCP + port: {{ .Values.ethereum.service.port }} + targetPort: {{ .Values.ethereum.service.targetPort }} + {{- if and (eq .Values.ethereum.service.type "NodePort") .Values.ethereum.service.nodePort }} + nodePort: {{ .Values.ethereum.service.nodePort }} + {{- end }} +--- +{{if .Values.network.public }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "aztec-network.fullname" . }}-ethereum-lb + labels: + {{- include "aztec-network.labels" . | nindent 4 }} +spec: + type: LoadBalancer + selector: + {{- include "aztec-network.selectorLabels" . | nindent 4 }} + app: ethereum + ports: + - protocol: TCP + port: {{ .Values.ethereum.service.port }} + targetPort: {{ .Values.ethereum.service.targetPort }} + {{- if and (eq .Values.ethereum.service.type "NodePort") .Values.ethereum.service.nodePort }} + nodePort: {{ .Values.ethereum.service.nodePort }} + {{- end }} +{{ end }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "aztec-network.fullname" . }}-reth-genesis + labels: + {{- include "aztec-network.labels" . | nindent 4 }} +data: + genesis.json: | + {{ .Files.Get "files/config/genesis.json" | nindent 4 }} +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "aztec-network.fullname" . }}-ethereum-pvc + labels: + {{- include "aztec-network.labels" . | nindent 4 }} +spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: {{ .Values.ethereum.storage }} +--- \ No newline at end of file diff --git a/spartan/aztec-network/templates/setup-l2-contracts.yaml b/spartan/aztec-network/templates/setup-l2-contracts.yaml index 60045b20352..5f6a42d1806 100644 --- a/spartan/aztec-network/templates/setup-l2-contracts.yaml +++ b/spartan/aztec-network/templates/setup-l2-contracts.yaml @@ -28,7 +28,7 @@ spec: done echo "PXE service is ready!" set -e - node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js setup-protocol-contracts --skipProofWait + node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js setup-protocol-contracts --skipProofWait --l1-chain-id {{ .Values.ethereum.chainId }} echo "L2 contracts initialized" env: - name: PXE_URL diff --git a/spartan/aztec-network/templates/transaction-bot.yaml b/spartan/aztec-network/templates/transaction-bot.yaml index 75a1d09f32c..598262d3710 100644 --- a/spartan/aztec-network/templates/transaction-bot.yaml +++ b/spartan/aztec-network/templates/transaction-bot.yaml @@ -20,11 +20,18 @@ spec: initContainers: - name: wait-for-aztec-node image: "{{ .Values.images.curl.image }}" + env: + - name: AZTEC_NODE_URL + {{- if .Values.bot.nodeUrl }} + value: "{{ .Values.bot.nodeUrl }}" + {{- else }} + value: {{ include "aztec-network.bootNodeUrl" . | quote }} + {{- end }} command: - /bin/sh - -c - | - until curl -s {{ include "aztec-network.bootNodeUrl" . }}/status; do echo waiting for aztec-node; sleep 2; done + until curl -s $(AZTEC_NODE_URL)/status; do echo waiting for aztec-node; sleep 2; done containers: - name: transaction-bot image: "{{ .Values.images.aztec.image }}" @@ -37,7 +44,11 @@ spec: - name: ETHEREUM_HOST value: {{ include "aztec-network.ethereumHost" . | quote }} - name: AZTEC_NODE_URL + {{- if .Values.bot.nodeUrl }} + value: "{{ .Values.bot.nodeUrl }}" + {{- else }} value: {{ include "aztec-network.bootNodeUrl" . | quote }} + {{- end }} - name: LOG_JSON value: "1" - name: LOG_LEVEL @@ -61,9 +72,9 @@ spec: - name: PROVER_REAL_PROOFS value: "{{ .Values.bot.proverRealProofs }}" - name: BOT_MAX_CONSECUTIVE_ERRORS - value: "3" + value: "{{ .Values.bot.maxErrors }}" - name: BOT_STOP_WHEN_UNHEALTHY - value: "true" + value: "{{ .Values.bot.stopIfUnhealthy }}" ports: - name: http containerPort: {{ .Values.bot.service.port }} @@ -105,4 +116,4 @@ spec: {{- if and (eq .Values.bot.service.type "NodePort") .Values.bot.service.nodePort }} nodePort: {{ .Values.bot.service.nodePort }} {{- end }} -{{- end }} \ No newline at end of file +{{- end }} diff --git a/spartan/aztec-network/templates/validator.yaml b/spartan/aztec-network/templates/validator.yaml index a10a61de997..ac6223b5dff 100644 --- a/spartan/aztec-network/templates/validator.yaml +++ b/spartan/aztec-network/templates/validator.yaml @@ -27,7 +27,7 @@ spec: - | until curl -s -X POST -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}' \ - {{ include "aztec-network.ethereumHost" . }} | grep -q anvil; do + {{ include "aztec-network.ethereumHost" . }} | grep -q reth; do echo "Waiting for Ethereum node..." sleep 5 done @@ -121,6 +121,8 @@ spec: value: "{{ .Values.validator.sequencer.maxTxsPerBlock }}" - name: SEQ_ENFORCE_TIME_TABLE value: "{{ .Values.validator.sequencer.enforceTimeTable }}" + - name: L1_CHAIN_ID + value: "{{ .Values.ethereum.chainId }}" - name: P2P_TCP_ANNOUNCE_ADDR {{- if .Values.validator.externalTcpHost }} value: "{{ .Values.validator.externalTcpHost }}:{{ .Values.validator.service.p2pTcpPort }}" @@ -145,6 +147,14 @@ spec: value: {{ include "aztec-network.otelCollectorTracesEndpoint" . | quote }} - name: OTEL_EXPORTER_OTLP_LOGS_ENDPOINT value: {{ include "aztec-network.otelCollectorLogsEndpoint" . | quote }} + - name: ETHEREUM_SLOT_DURATION + value: "{{ .Values.ethereum.blockTime }}" + - name: AZTEC_SLOT_DURATION + value: "{{ .Values.aztec.slotDuration }}" + - name: AZTEC_EPOCH_DURATION + value: "{{ .Values.aztec.epochDuration }}" + - name: AZTEC_EPOCH_PROOF_CLAIM_WINDOW_IN_L2_SLOTS + value: "{{ .Values.aztec.epochProofClaimWindow }}" ports: - containerPort: {{ .Values.validator.service.nodePort }} - containerPort: {{ .Values.validator.service.p2pTcpPort }} @@ -253,4 +263,4 @@ spec: protocol: UDP --- {{- end }} -{{ end }} \ No newline at end of file +{{ end }} diff --git a/spartan/aztec-network/values.yaml b/spartan/aztec-network/values.yaml index fba43ca9548..4c1ff560df4 100644 --- a/spartan/aztec-network/values.yaml +++ b/spartan/aztec-network/values.yaml @@ -19,6 +19,14 @@ images: foundry: image: ghcr.io/foundry-rs/foundry@sha256:ce4b236f6760fdeb08e82267c9fa17647d29a374760bfe7ee01998fb8c0aaad7 pullPolicy: IfNotPresent + reth: + image: ghcr.io/paradigmxyz/reth:v1.0.8 + pullPolicy: IfNotPresent + +aztec: + slotDuration: 24 # in seconds, aka L2 slot duration. Must be a multiple of {{ ethereum.blockTime }} + epochDuration: 16 # how many L2 slots in an epoch + epochProofClaimWindow: 13 # in L2 slots bootNode: externalTcpHost: "" @@ -34,6 +42,7 @@ bootNode: sequencer: maxSecondsBetweenBlocks: 0 minTxsPerBlock: 1 + realProofs: false validator: disabled: true p2p: @@ -113,6 +122,7 @@ proverNode: pxe: externalHost: "" logLevel: "debug" + proverEnable: false debug: "aztec:*,-aztec:avm_simulator*,-aztec:libp2p_service*,-aztec:circuits:artifact_hash,-json-rpc*,-aztec:l2_block_stream,-aztec:world-state:database" replicas: 1 service: @@ -144,6 +154,8 @@ bot: botNoStart: false pxeProverEnabled: false proverRealProofs: false + maxErrors: 3 + stopIfUnhealthy: true service: type: ClusterIP port: 8080 @@ -163,13 +175,11 @@ bot: ethereum: externalHost: "" replicas: 1 - chainId: 31337 - blockTime: 12 + chainId: 1337 + blockTime: 12sec # 1 billion gas limit # helps ensure we can deploy public contracts gasLimit: "1000000000" - forkUrl: "" - forkBlockNumber: "" args: "" service: type: ClusterIP @@ -186,7 +196,7 @@ ethereum: requests: memory: "2Gi" cpu: "200m" - storage: "8Gi" + storage: "80Gi" proverAgent: enabled: true diff --git a/spartan/aztec-network/values/1-validator-with-proving.yaml b/spartan/aztec-network/values/1-validator-with-proving.yaml index ac7ca644a1f..30e7d5b87af 100644 --- a/spartan/aztec-network/values/1-validator-with-proving.yaml +++ b/spartan/aztec-network/values/1-validator-with-proving.yaml @@ -32,6 +32,10 @@ jobs: deployL1Verifier: enable: true +aztec: + slotDuration: 36 + epochDuration: 32 + telemetry: enabled: true otelCollectorEndpoint: http://metrics-opentelemetry-collector.metrics:4318 diff --git a/spartan/aztec-network/values/gcp-proving-test.yaml b/spartan/aztec-network/values/gcp-proving-test.yaml new file mode 100644 index 00000000000..70b2612b4d7 --- /dev/null +++ b/spartan/aztec-network/values/gcp-proving-test.yaml @@ -0,0 +1,85 @@ +telemetry: + enabled: true + otelCollectorEndpoint: http://metrics-opentelemetry-collector.metrics:4318 + +validator: + replicas: 1 + realProofs: true + validatorKeys: + - 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + validatorAddresses: + - 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 + validator: + disabled: false + sequencer: + maxSecondsBetweenBlocks: 0 + minTxsPerBlock: 1 + maxTxsPerBlock: 8 + enforceTimeTable: false + resources: + requests: + memory: "8Gi" + cpu: "8" + storage: "128Gi" + +bootNode: + realProofs: true + validator: + disabled: true + resources: + requests: + memory: "8Gi" + cpu: "8" + storage: "128Gi" + +proverNode: + realProofs: true + resources: + requests: + memory: "8Gi" + cpu: "8" + storage: "128Gi" + +proverAgent: + replicas: 120 + realProofs: true + bb: + hardwareConcurrency: 31 + nodeSelector: + cloud.google.com/compute-class: "Performance" + cloud.google.com/machine-family: "t2d" + resources: + requests: + memory: "116Gi" + cpu: "31" + +pxe: + proverEnabled: true + +bot: + replicas: 16 + enabled: true + pxeProverEnabled: true + txIntervalSeconds: 1 + proverRealProofs: true + botPrivateKey: "" + privateTransfersPerTx: 1 + publicTransfersPerTx: 1 + followChain: "PENDING" + bb: + hardwareConcurrency: 8 + resources: + requests: + memory: "8Gi" + cpu: "8" + ephemeral-storage: "8Gi" + +jobs: + deployL1Verifier: + enable: true + +fullnameOverride: sp + +aztec: + slotDuration: 36 + epochDuration: 32 diff --git a/spartan/aztec-network/values/prover-node-with-agents.yaml b/spartan/aztec-network/values/prover-node-with-agents.yaml new file mode 100644 index 00000000000..4a58f419958 --- /dev/null +++ b/spartan/aztec-network/values/prover-node-with-agents.yaml @@ -0,0 +1,43 @@ +########## +# BEWARE # +########## +# You need to deploy the metrics helm chart before using this values file. +# head to spartan/metrics and run `./install.sh` +# (then `./forward.sh` if you want to see it) +telemetry: + enabled: true + otelCollectorEndpoint: http://metrics-opentelemetry-collector.metrics:4318 + +validator: + external: true + +bootNode: + debug: "aztec:*,-aztec:avm_simulator:*,-aztec:world-state:database,discv5:*,-JsonProxy:*" + validator: + disabled: true + +proverNode: + realProofs: false + +proverAgent: + replicas: 1 + realProofs: false + bb: + hardwareConcurrency: 16 + +pxe: + external: false + proverEnabled: true + +bot: + enabled: false + pxeProverEnabled: false + txIntervalSeconds: 200 + +jobs: + deployL1Verifier: + enable: false + +ethereum: + external: true + externalHost: "" diff --git a/spartan/chaos-mesh/install.sh b/spartan/chaos-mesh/install.sh index 52146403cd5..00fa8b346c6 100755 --- a/spartan/chaos-mesh/install.sh +++ b/spartan/chaos-mesh/install.sh @@ -1,6 +1,6 @@ #!/bin/bash -SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" +SCRIPT_DIR="$(dirname $(realpath -s "${BASH_SOURCE[0]}"))" cd "$SCRIPT_DIR" # check if chaos-mesh is already installed diff --git a/spartan/metrics/forward.sh b/spartan/metrics/forward.sh index 8e1f80e707c..c9a16171067 100755 --- a/spartan/metrics/forward.sh +++ b/spartan/metrics/forward.sh @@ -1,9 +1,12 @@ #!/bin/bash -echo "Run this script after the metrics pods all come up. After running this script, port forward 3000 locally" -echo "Then navigate to https://localhost:3000 and login with user admin, and password as follows:" + +PORT=${1:-3000} + +echo "Run this script after the metrics pods all come up. After running this script, port forward $PORT locally" +echo "Then navigate to https://localhost:$PORT and login with user admin, and password as follows:" echo kubectl get secrets -n metrics metrics-grafana -o jsonpath='{.data.admin-password}' | base64 --decode # skip two empty lines echo echo -kubectl port-forward -n metrics service/metrics-grafana 3000:80 +kubectl port-forward -n metrics service/metrics-grafana $PORT:80 diff --git a/spartan/metrics/install.sh b/spartan/metrics/install.sh index 66bd2cbd919..46efddd62de 100755 --- a/spartan/metrics/install.sh +++ b/spartan/metrics/install.sh @@ -1,7 +1,7 @@ #!/bin/bash set -eu -SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" +SCRIPT_DIR="$(dirname $(realpath -s "${BASH_SOURCE[0]}"))" cd "$SCRIPT_DIR" # check if metrics is already installed @@ -14,4 +14,5 @@ helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm helm repo add grafana https://grafana.github.io/helm-charts helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm dependency update -helm upgrade metrics "$SCRIPT_DIR" -n metrics --install --create-namespace --atomic +# need to disable node exporter for GKE autopilot to be happy +helm upgrade metrics "$SCRIPT_DIR" -n metrics --install --create-namespace --atomic --set prometheus.prometheus-node-exporter.enabled=false \ No newline at end of file diff --git a/spartan/scripts/setup_local_k8s.sh b/spartan/scripts/setup_local_k8s.sh index 431600dc558..0571aebfe9e 100755 --- a/spartan/scripts/setup_local_k8s.sh +++ b/spartan/scripts/setup_local_k8s.sh @@ -2,7 +2,7 @@ set -e -SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" +SCRIPT_DIR="$(dirname $(realpath -s "${BASH_SOURCE[0]}"))" # exit if we are not on linux amd64 if [ "$(uname)" != "Linux" ] || [ "$(uname -m)" != "x86_64" ]; then diff --git a/spartan/terraform/eks-cluster/main.tf b/spartan/terraform/eks-cluster/main.tf index 09ef171443f..5dc2fe23511 100644 --- a/spartan/terraform/eks-cluster/main.tf +++ b/spartan/terraform/eks-cluster/main.tf @@ -1,8 +1,8 @@ terraform { backend "s3" { - bucket = "aztec-terraform" - key = "spartan/terraform.tfstate" - region = "eu-west-2" + bucket = "aztec-terraform" + key = "spartan/terraform.tfstate" + region = "eu-west-2" } required_providers { @@ -26,6 +26,54 @@ data "aws_availability_zones" "available" { } } +# Create security group for node traffic +resource "aws_security_group" "node_traffic" { + name_prefix = "eks-node-traffic" + description = "Security group for EKS node UDP and TCP traffic" + vpc_id = module.vpc.vpc_id + + # Ingress UDP rule + ingress { + from_port = 40400 + to_port = 40499 + protocol = "udp" + cidr_blocks = ["0.0.0.0/0"] + description = "Allow incoming UDP traffic" + } + + # Ingress TCP rule + ingress { + from_port = 40400 + to_port = 40499 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + description = "Allow incoming TCP traffic" + } + + # Egress UDP rule + egress { + from_port = 40400 + to_port = 40499 + protocol = "udp" + cidr_blocks = ["0.0.0.0/0"] + description = "Allow outgoing UDP traffic" + } + + # Egress TCP rule + egress { + from_port = 40400 + to_port = 40499 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + description = "Allow outgoing TCP traffic" + } + + tags = { + Name = "${var.cluster_name}-node-traffic" + Project = var.cluster_name + } +} + module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "5.8.1" @@ -33,14 +81,14 @@ module "vpc" { name = var.cluster_name cidr = "10.1.0.0/16" - azs = slice(data.aws_availability_zones.available.names, 0, 3) - private_subnets = ["10.1.1.0/24", "10.1.2.0/24"] - public_subnets = ["10.1.3.0/24", "10.1.4.0/24"] + azs = slice(data.aws_availability_zones.available.names, 0, 3) + private_subnets = ["10.1.1.0/24", "10.1.2.0/24"] + public_subnets = ["10.1.3.0/24", "10.1.4.0/24"] enable_nat_gateway = true single_nat_gateway = true enable_dns_hostnames = true - enable_vpn_gateway = true + enable_vpn_gateway = true public_subnet_tags = { "kubernetes.io/role/elb" = 1 @@ -51,7 +99,7 @@ module "vpc" { } tags = { - Project = var.cluster_name + Project = var.cluster_name } } @@ -83,17 +131,17 @@ module "eks" { eks_managed_node_groups = { default = { - name = "node-group-1" + name = "node-group-1" instance_types = ["m6a.2xlarge"] min_size = 1 - max_size = 2 - desired_size = 1 + max_size = 10 + desired_size = 10 } } tags = { - Project = var.cluster_name + Project = var.cluster_name } } diff --git a/spartan/terraform/gke-cluster/main.tf b/spartan/terraform/gke-cluster/main.tf new file mode 100644 index 00000000000..46c1a51dc6c --- /dev/null +++ b/spartan/terraform/gke-cluster/main.tf @@ -0,0 +1,173 @@ +terraform { + backend "s3" { + bucket = "aztec-terraform" + key = "spartan-gke-cluster/terraform.tfstate" + region = "eu-west-2" + } + required_providers { + google = { + source = "hashicorp/google" + version = "~> 5.0" + } + } +} + +# Configure the Google Cloud provider +provider "google" { + project = var.project + region = var.region +} + +# Create the service account +resource "google_service_account" "gke_sa" { + account_id = "gke-nodes-sa" + display_name = "GKE Nodes Service Account" + description = "Service account for GKE nodes" +} + +# Add IAM roles to the service account +resource "google_project_iam_member" "gke_sa_roles" { + for_each = toset([ + "roles/logging.logWriter", + "roles/monitoring.metricWriter", + "roles/monitoring.viewer", + "roles/artifactregistry.reader" + ]) + + project = var.project + role = each.key + member = "serviceAccount:${google_service_account.gke_sa.email}" +} + +# Create ingress firewall rule for UDP +resource "google_compute_firewall" "udp_ingress" { + name = "allow-udp-ingress-40400-40499" + network = "default" + + allow { + protocol = "udp" + ports = ["40400-40499"] + } + + direction = "INGRESS" + source_ranges = ["0.0.0.0/0"] + target_tags = ["gke-node"] +} + +# Create egress firewall rule for UDP +resource "google_compute_firewall" "udp_egress" { + name = "allow-udp-egress-40400-40499" + network = "default" + + allow { + protocol = "udp" + ports = ["40400-40499"] + } + + direction = "EGRESS" + destination_ranges = ["0.0.0.0/0"] + target_tags = ["gke-node"] +} + +# Create a GKE cluster +resource "google_container_cluster" "primary" { + name = "spartan-gke" + location = var.zone + initial_node_count = 1 + + # Remove default node pool after cluster creation + remove_default_node_pool = true + + # Kubernetes version + min_master_version = "latest" + + # Network configuration + network = "default" + subnetwork = "default" + + # Master auth configuration + master_auth { + client_certificate_config { + issue_client_certificate = false + } + } +} + +# Create primary node pool with autoscaling +resource "google_container_node_pool" "primary_nodes" { + name = "primary-node-pool" + location = var.zone + cluster = google_container_cluster.primary.name + + # Enable autoscaling + autoscaling { + min_node_count = 1 + max_node_count = 5 + } + + # Node configuration + node_config { + machine_type = "t2d-standard-16" + + service_account = google_service_account.gke_sa.email + oauth_scopes = [ + "https://www.googleapis.com/auth/cloud-platform" + ] + + labels = { + env = "production" + } + + tags = ["gke-node"] + } + + # Management configuration + management { + auto_repair = true + auto_upgrade = true + } +} + +# Create spot instance node pool with autoscaling +resource "google_container_node_pool" "spot_nodes" { + name = "spot-node-pool" + location = var.zone + cluster = google_container_cluster.primary.name + + # Enable autoscaling + autoscaling { + min_node_count = 0 + max_node_count = 10 + } + + # Node configuration + node_config { + machine_type = "t2d-standard-16" + spot = true + + service_account = google_service_account.gke_sa.email + oauth_scopes = [ + "https://www.googleapis.com/auth/cloud-platform" + ] + + labels = { + env = "production" + pool = "spot" + } + + tags = ["gke-node", "spot"] + + # Spot instance termination handler + taint { + key = "cloud.google.com/gke-spot" + value = "true" + effect = "NO_SCHEDULE" + } + } + + # Management configuration + management { + auto_repair = true + auto_upgrade = true + } +} diff --git a/spartan/terraform/gke-cluster/outputs.tf b/spartan/terraform/gke-cluster/outputs.tf new file mode 100644 index 00000000000..befaa28092e --- /dev/null +++ b/spartan/terraform/gke-cluster/outputs.tf @@ -0,0 +1,17 @@ +output "cluster_endpoint" { + value = google_container_cluster.primary.endpoint +} + +output "service_account_email" { + value = google_service_account.gke_sa.email +} + +output "region" { + description = "Google cloud region" + value = var.region +} + +output "kubernetes_cluster_name" { + description = "GKE Cluster Name" + value = google_container_cluster.primary.name +} diff --git a/spartan/terraform/gke-cluster/variables.tf b/spartan/terraform/gke-cluster/variables.tf new file mode 100644 index 00000000000..555458daa5d --- /dev/null +++ b/spartan/terraform/gke-cluster/variables.tf @@ -0,0 +1,11 @@ +variable "project" { + default = "testnet-440309" +} + +variable "region" { + default = "us-east4" +} + +variable "zone" { + default = "us-east4-a" +} diff --git a/spartan/terraform/multicloud-deploy/main.tf b/spartan/terraform/multicloud-deploy/main.tf new file mode 100644 index 00000000000..add82c42b26 --- /dev/null +++ b/spartan/terraform/multicloud-deploy/main.tf @@ -0,0 +1,79 @@ +terraform { + backend "s3" { + bucket = "aztec-terraform" + key = "multicloud-deploy/terraform.tfstate" + region = "eu-west-2" + } + required_providers { + helm = { + source = "hashicorp/helm" + version = "~> 2.12.1" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.24.0" + } + } +} + +# Define providers for different contexts +provider "kubernetes" { + alias = "eks-cluster" + config_path = "~/.kube/config" + config_context = var.eks_cluster_context +} + +provider "kubernetes" { + alias = "gke-cluster" + config_path = "~/.kube/config" + config_context = var.gke_cluster_context +} + +# Helm providers for each cluster +provider "helm" { + alias = "eks-cluster" + kubernetes { + config_path = "~/.kube/config" + config_context = var.eks_cluster_context + } +} + +provider "helm" { + alias = "gke-cluster" + kubernetes { + config_path = "~/.kube/config" + config_context = var.gke_cluster_context + } +} + +# Aztec Helm release for eks-cluster +resource "helm_release" "aztec-eks-cluster" { + provider = helm.eks-cluster + name = var.testnet_name + repository = "../../" + chart = "aztec-network" + namespace = var.testnet_name + create_namespace = true + values = [file("../../aztec-network/values/${var.eks-values-file}")] + + # Setting timeout and wait conditions + timeout = 1800 # 30 minutes in seconds + wait = true + wait_for_jobs = true +} + +# Aztec Helm release for gke-cluster +resource "helm_release" "aztec-gke-cluster" { + provider = helm.gke-cluster + name = var.testnet_name + repository = "../../" + chart = "aztec-network" + namespace = var.testnet_name + create_namespace = true + values = [file("../../aztec-network/values/${var.gke-values-file}")] + + # Setting timeout and wait conditions + timeout = 1800 # 30 minutes in seconds + wait = true + wait_for_jobs = true +} diff --git a/spartan/terraform/multicloud-deploy/outputs.tf b/spartan/terraform/multicloud-deploy/outputs.tf new file mode 100644 index 00000000000..90b7a51a6d0 --- /dev/null +++ b/spartan/terraform/multicloud-deploy/outputs.tf @@ -0,0 +1,25 @@ +output "eks_cluster_deployment" { + description = "Details of the EKS cluster Helm deployment" + value = { + name = helm_release.aztec-eks-cluster.name + namespace = helm_release.aztec-eks-cluster.namespace + chart = helm_release.aztec-eks-cluster.chart + version = helm_release.aztec-eks-cluster.version + status = helm_release.aztec-eks-cluster.status + values_file = var.eks-values-file + cluster = var.eks_cluster_context + } +} + +output "gke_cluster_deployment" { + description = "Details of the GKE cluster Helm deployment" + value = { + name = helm_release.aztec-gke-cluster.name + namespace = helm_release.aztec-gke-cluster.namespace + chart = helm_release.aztec-gke-cluster.chart + version = helm_release.aztec-gke-cluster.version + status = helm_release.aztec-gke-cluster.status + values_file = var.gke-values-file + cluster = var.gke_cluster_context + } +} diff --git a/spartan/terraform/multicloud-deploy/variables.tf b/spartan/terraform/multicloud-deploy/variables.tf new file mode 100644 index 00000000000..b58de3d7d5a --- /dev/null +++ b/spartan/terraform/multicloud-deploy/variables.tf @@ -0,0 +1,29 @@ +variable "eks_cluster_context" { + description = "EKS cluster context" + type = string + default = "arn:aws:eks:us-east-1:278380418400:cluster/spartan" +} + +variable "gke_cluster_context" { + description = "GKE cluster context" + type = string + default = "gke_testnet-440309_us-east1_spartan-provers" +} + +variable "testnet_name" { + description = "Name of helm deployment and k8s namespace" + type = string + default = "terratest" +} + +variable "eks-values-file" { + description = "Name of the values file to use for eks cluster" + type = string + default = "1-validators.yaml" +} + +variable "gke-values-file" { + description = "Name of the values file to use for gke cluster" + type = string + default = "1-validators.yaml" +} diff --git a/yarn-project/.earthlyignore b/yarn-project/.earthlyignore index bd9d331e9a6..0fc5487b6b8 100644 --- a/yarn-project/.earthlyignore +++ b/yarn-project/.earthlyignore @@ -44,6 +44,7 @@ aztec-faucet/data* aztec-node/data* aztec/log circuits.js/fixtures/*.json +circuit-types/src/test/artifacts docs/dist end-to-end/addresses.json end-to-end/log diff --git a/yarn-project/.gitignore b/yarn-project/.gitignore index a6182305e1e..abacb3d21aa 100644 --- a/yarn-project/.gitignore +++ b/yarn-project/.gitignore @@ -17,6 +17,7 @@ aztec-faucet/data* aztec-node/data* aztec/log circuits.js/fixtures/*.json +circuit-types/src/test/artifacts docs/dist end-to-end/addresses.json end-to-end/flame_graph @@ -27,9 +28,6 @@ end-to-end/src/web/main.js.LICENSE.txt l1-artifacts/generated l1-contracts/generated builder/target/ -builder/proofs/ -builder/Prover.toml -builder/Verifier.toml builder/noir-protocol-circuits-types/.gitignore wow builder/proofs/ builder/Prover.toml @@ -43,6 +41,7 @@ noir-protocol-circuits-types/src/types/ ivc-integration/artifacts ivc-integration/src/types/ protocol-contracts/artifacts +protocol-contracts/src/protocol_contract_data.ts scripts/tmp noir-contracts.js/src noir-contracts.js/artifacts/ diff --git a/yarn-project/archiver/src/archiver/archiver.test.ts b/yarn-project/archiver/src/archiver/archiver.test.ts index 4338feb084c..9d19fae994a 100644 --- a/yarn-project/archiver/src/archiver/archiver.test.ts +++ b/yarn-project/archiver/src/archiver/archiver.test.ts @@ -201,6 +201,12 @@ describe('Archiver', () => { expect(totalNumUnencryptedLogs).toEqual(expectedTotalNumUnencryptedLogs); }); + blockNumbers.forEach(async x => { + const expectedTotalNumContractClassLogs = 4; + const contractClassLogs = await archiver.getContractClassLogs({ fromBlock: x, toBlock: x + 1 }); + expect(contractClassLogs.logs.length).toEqual(expectedTotalNumContractClassLogs); + }); + // Check last proven block number const provenBlockNumber = await archiver.getProvenBlockNumber(); expect(provenBlockNumber).toEqual(1); diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 4c8adef9a6f..a2a10d8c7a2 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -1,4 +1,5 @@ import { + type EncryptedL2Log, type FromLogType, type GetUnencryptedLogsResponse, type InboxLeaf, @@ -14,7 +15,7 @@ import { type TxEffect, type TxHash, type TxReceipt, - type TxScopedEncryptedL2NoteLog, + type TxScopedL2Log, type UnencryptedL2Log, } from '@aztec/circuit-types'; import { @@ -638,7 +639,7 @@ export class Archiver implements ArchiveSource { * @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match * that tag. */ - getLogsByTags(tags: Fr[]): Promise { + getLogsByTags(tags: Fr[]): Promise { return this.store.getLogsByTags(tags); } @@ -651,6 +652,15 @@ export class Archiver implements ArchiveSource { return this.store.getUnencryptedLogs(filter); } + /** + * Gets contract class logs based on the provided filter. + * @param filter - The filter to apply to the logs. + * @returns The requested logs. + */ + getContractClassLogs(filter: LogFilter): Promise { + return this.store.getContractClassLogs(filter); + } + /** * Gets the number of the latest L2 block processed by the block source implementation. * @returns The number of the latest L2 block processed by the block source implementation. @@ -789,7 +799,7 @@ class ArchiverStoreHelper * Extracts and stores contract instances out of ContractInstanceDeployed events emitted by the canonical deployer contract. * @param allLogs - All logs emitted in a bunch of blocks. */ - async #updateDeployedContractInstances(allLogs: UnencryptedL2Log[], blockNum: number, operation: Operation) { + async #updateDeployedContractInstances(allLogs: EncryptedL2Log[], blockNum: number, operation: Operation) { const contractInstances = ContractInstanceDeployedEvent.fromLogs(allLogs).map(e => e.toContractInstance()); if (contractInstances.length > 0) { contractInstances.forEach(c => @@ -868,15 +878,18 @@ class ArchiverStoreHelper // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them ...(await Promise.all( blocks.map(async block => { - const blockLogs = block.data.body.txEffects - .flatMap(txEffect => (txEffect ? [txEffect.unencryptedLogs] : [])) + const contractClassLogs = block.data.body.txEffects + .flatMap(txEffect => (txEffect ? [txEffect.contractClassLogs] : [])) + .flatMap(txLog => txLog.unrollLogs()); + // ContractInstanceDeployed event logs are now broadcast in .encryptedLogs + const allEncryptedLogs = block.data.body.txEffects + .flatMap(txEffect => (txEffect ? [txEffect.encryptedLogs] : [])) .flatMap(txLog => txLog.unrollLogs()); - return ( await Promise.all([ - this.#updateRegisteredContractClasses(blockLogs, block.data.number, Operation.Store), - this.#updateDeployedContractInstances(blockLogs, block.data.number, Operation.Store), - this.#storeBroadcastedIndividualFunctions(blockLogs, block.data.number), + this.#updateRegisteredContractClasses(contractClassLogs, block.data.number, Operation.Store), + this.#updateDeployedContractInstances(allEncryptedLogs, block.data.number, Operation.Store), + this.#storeBroadcastedIndividualFunctions(contractClassLogs, block.data.number), ]) ).every(Boolean); }), @@ -898,11 +911,15 @@ class ArchiverStoreHelper // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them ...(await Promise.all( blocks.map(async block => { - const blockLogs = block.data.body.txEffects - .flatMap(txEffect => (txEffect ? [txEffect.unencryptedLogs] : [])) + const contractClassLogs = block.data.body.txEffects + .flatMap(txEffect => (txEffect ? [txEffect.contractClassLogs] : [])) .flatMap(txLog => txLog.unrollLogs()); - await this.#updateRegisteredContractClasses(blockLogs, block.data.number, Operation.Delete); - await this.#updateDeployedContractInstances(blockLogs, block.data.number, Operation.Delete); + // ContractInstanceDeployed event logs are now broadcast in .encryptedLogs + const allEncryptedLogs = block.data.body.txEffects + .flatMap(txEffect => (txEffect ? [txEffect.encryptedLogs] : [])) + .flatMap(txLog => txLog.unrollLogs()); + await this.#updateRegisteredContractClasses(contractClassLogs, block.data.number, Operation.Delete); + await this.#updateDeployedContractInstances(allEncryptedLogs, block.data.number, Operation.Delete); }), )), this.store.deleteLogs(blocks.map(b => b.data)), @@ -938,12 +955,15 @@ class ArchiverStoreHelper ): Promise>[]> { return this.store.getLogs(from, limit, logType); } - getLogsByTags(tags: Fr[]): Promise { + getLogsByTags(tags: Fr[]): Promise { return this.store.getLogsByTags(tags); } getUnencryptedLogs(filter: LogFilter): Promise { return this.store.getUnencryptedLogs(filter); } + getContractClassLogs(filter: LogFilter): Promise { + return this.store.getContractClassLogs(filter); + } getSynchedL2BlockNumber(): Promise { return this.store.getSynchedL2BlockNumber(); } diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index 5038dd4afeb..4eb2c80ccc0 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -9,7 +9,7 @@ import { type TxEffect, type TxHash, type TxReceipt, - type TxScopedEncryptedL2NoteLog, + type TxScopedL2Log, } from '@aztec/circuit-types'; import { type ContractClassPublic, @@ -142,7 +142,7 @@ export interface ArchiverDataStore { * @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match * that tag. */ - getLogsByTags(tags: Fr[]): Promise; + getLogsByTags(tags: Fr[]): Promise; /** * Gets unencrypted logs based on the provided filter. @@ -151,6 +151,13 @@ export interface ArchiverDataStore { */ getUnencryptedLogs(filter: LogFilter): Promise; + /** + * Gets contract class logs based on the provided filter. + * @param filter - The filter to apply to the logs. + * @returns The requested logs. + */ + getContractClassLogs(filter: LogFilter): Promise; + /** * Gets the number of the latest L2 block processed. * @returns The number of the latest L2 block processed. diff --git a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts index 1311c6ec03e..cd30af56a78 100644 --- a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts +++ b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts @@ -344,14 +344,24 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch describe('getLogsByTags', () => { const txsPerBlock = 4; const numPrivateFunctionCalls = 3; - const numNoteEncryptedLogs = 2; + const numPublicFunctionCalls = 1; + const numEncryptedLogsPerFn = 2; + const numUnencryptedLogsPerFn = 1; const numBlocks = 10; let blocks: L1Published[]; - let tags: { [i: number]: { [j: number]: Buffer[] } } = {}; + let encryptedLogTags: { [i: number]: { [j: number]: Buffer[] } } = {}; + let unencryptedLogTags: { [i: number]: { [j: number]: Buffer[] } } = {}; beforeEach(async () => { blocks = times(numBlocks, (index: number) => ({ - data: L2Block.random(index + 1, txsPerBlock, numPrivateFunctionCalls, 2, numNoteEncryptedLogs, 2), + data: L2Block.random( + index + 1, + txsPerBlock, + numPrivateFunctionCalls, + numPublicFunctionCalls, + numEncryptedLogsPerFn, + numUnencryptedLogsPerFn, + ), l1: { blockNumber: BigInt(index), blockHash: `0x${index}`, timestamp: BigInt(index) }, })); // Last block has the note encrypted log tags of the first tx copied from the previous block @@ -373,47 +383,94 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch await store.addBlocks(blocks); await store.addLogs(blocks.map(b => b.data)); - tags = {}; + encryptedLogTags = {}; + unencryptedLogTags = {}; blocks.forEach((b, blockIndex) => { - if (!tags[blockIndex]) { - tags[blockIndex] = {}; + if (!encryptedLogTags[blockIndex]) { + encryptedLogTags[blockIndex] = {}; + } + if (!unencryptedLogTags[blockIndex]) { + unencryptedLogTags[blockIndex] = {}; } b.data.body.noteEncryptedLogs.txLogs.forEach((txLogs, txIndex) => { - if (!tags[blockIndex][txIndex]) { - tags[blockIndex][txIndex] = []; + if (!encryptedLogTags[blockIndex][txIndex]) { + encryptedLogTags[blockIndex][txIndex] = []; + } + encryptedLogTags[blockIndex][txIndex].push(...txLogs.unrollLogs().map(log => log.data.subarray(0, 32))); + }); + b.data.body.unencryptedLogs.txLogs.forEach((txLogs, txIndex) => { + if (!unencryptedLogTags[blockIndex][txIndex]) { + unencryptedLogTags[blockIndex][txIndex] = []; } - tags[blockIndex][txIndex].push(...txLogs.unrollLogs().map(log => log.data.subarray(0, 32))); + unencryptedLogTags[blockIndex][txIndex].push(...txLogs.unrollLogs().map(log => log.data.subarray(0, 32))); }); }); }); - it('is possible to batch request all logs of a tx via tags', async () => { + it('is possible to batch request encrypted logs of a tx via tags', async () => { // get random tx from any block that's not the last one const targetBlockIndex = randomInt(numBlocks - 2); const targetTxIndex = randomInt(txsPerBlock); const logsByTags = await store.getLogsByTags( - tags[targetBlockIndex][targetTxIndex].map(buffer => new Fr(buffer)), + encryptedLogTags[targetBlockIndex][targetTxIndex].map(buffer => new Fr(buffer)), ); - const expectedResponseSize = numPrivateFunctionCalls * numNoteEncryptedLogs; + const expectedResponseSize = numPrivateFunctionCalls * numEncryptedLogsPerFn; expect(logsByTags.length).toEqual(expectedResponseSize); logsByTags.forEach((logsByTag, logIndex) => { expect(logsByTag).toHaveLength(1); const [scopedLog] = logsByTag; expect(scopedLog.txHash).toEqual(blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].txHash); - expect(scopedLog.log).toEqual( - blocks[targetBlockIndex].data.body.noteEncryptedLogs.txLogs[targetTxIndex].unrollLogs()[logIndex], + expect(scopedLog.logData).toEqual( + blocks[targetBlockIndex].data.body.noteEncryptedLogs.txLogs[targetTxIndex].unrollLogs()[logIndex].data, ); }); }); - it('is possible to batch request all logs of different blocks via tags', async () => { + // TODO: Allow this test when #9835 is fixed and tags can be correctly decoded + it.skip('is possible to batch request all logs (encrypted and unencrypted) of a tx via tags', async () => { + // get random tx from any block that's not the last one + const targetBlockIndex = randomInt(numBlocks - 2); + const targetTxIndex = randomInt(txsPerBlock); + + const logsByTags = await store.getLogsByTags( + encryptedLogTags[targetBlockIndex][targetTxIndex] + .concat(unencryptedLogTags[targetBlockIndex][targetTxIndex]) + .map(buffer => new Fr(buffer)), + ); + + const expectedResponseSize = + numPrivateFunctionCalls * numEncryptedLogsPerFn + numPublicFunctionCalls * numUnencryptedLogsPerFn; + expect(logsByTags.length).toEqual(expectedResponseSize); + + const encryptedLogsByTags = logsByTags.slice(0, numPrivateFunctionCalls * numEncryptedLogsPerFn); + const unencryptedLogsByTags = logsByTags.slice(numPrivateFunctionCalls * numEncryptedLogsPerFn); + encryptedLogsByTags.forEach((logsByTag, logIndex) => { + expect(logsByTag).toHaveLength(1); + const [scopedLog] = logsByTag; + expect(scopedLog.txHash).toEqual(blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].txHash); + expect(scopedLog.logData).toEqual( + blocks[targetBlockIndex].data.body.noteEncryptedLogs.txLogs[targetTxIndex].unrollLogs()[logIndex].data, + ); + }); + unencryptedLogsByTags.forEach((logsByTag, logIndex) => { + expect(logsByTag).toHaveLength(1); + const [scopedLog] = logsByTag; + expect(scopedLog.logData).toEqual( + blocks[targetBlockIndex].data.body.unencryptedLogs.txLogs[targetTxIndex].unrollLogs()[logIndex].data, + ); + }); + }); + + it('is possible to batch request logs of different blocks via tags', async () => { // get first tx of first block and second tx of second block - const logsByTags = await store.getLogsByTags([...tags[0][0], ...tags[1][1]].map(buffer => new Fr(buffer))); + const logsByTags = await store.getLogsByTags( + [...encryptedLogTags[0][0], ...encryptedLogTags[1][1]].map(buffer => new Fr(buffer)), + ); - const expectedResponseSize = 2 * numPrivateFunctionCalls * numNoteEncryptedLogs; + const expectedResponseSize = 2 * numPrivateFunctionCalls * numEncryptedLogsPerFn; expect(logsByTags.length).toEqual(expectedResponseSize); logsByTags.forEach(logsByTag => expect(logsByTag).toHaveLength(1)); @@ -421,14 +478,14 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch it('is possible to batch request logs that have the same tag but different content', async () => { // get first tx of last block - const logsByTags = await store.getLogsByTags(tags[numBlocks - 1][0].map(buffer => new Fr(buffer))); + const logsByTags = await store.getLogsByTags(encryptedLogTags[numBlocks - 1][0].map(buffer => new Fr(buffer))); - const expectedResponseSize = numPrivateFunctionCalls * numNoteEncryptedLogs; + const expectedResponseSize = numPrivateFunctionCalls * numEncryptedLogsPerFn; expect(logsByTags.length).toEqual(expectedResponseSize); logsByTags.forEach(logsByTag => { expect(logsByTag).toHaveLength(2); - const [tag0, tag1] = logsByTag.map(scopedLog => new Fr(scopedLog.log.data.subarray(0, 32))); + const [tag0, tag1] = logsByTag.map(scopedLog => new Fr(scopedLog.logData.subarray(0, 32))); expect(tag0).toEqual(tag1); }); }); @@ -440,10 +497,10 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch const logsByTags = await store.getLogsByTags([ Fr.random(), - ...tags[targetBlockIndex][targetTxIndex].slice(1).map(buffer => new Fr(buffer)), + ...encryptedLogTags[targetBlockIndex][targetTxIndex].slice(1).map(buffer => new Fr(buffer)), ]); - const expectedResponseSize = numPrivateFunctionCalls * numNoteEncryptedLogs; + const expectedResponseSize = numPrivateFunctionCalls * numEncryptedLogsPerFn; expect(logsByTags.length).toEqual(expectedResponseSize); const [emptyLogsByTag, ...populatedLogsByTags] = logsByTags; @@ -453,8 +510,8 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch expect(logsByTag).toHaveLength(1); const [scopedLog] = logsByTag; expect(scopedLog.txHash).toEqual(blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].txHash); - expect(scopedLog.log).toEqual( - blocks[targetBlockIndex].data.body.noteEncryptedLogs.txLogs[targetTxIndex].unrollLogs()[logIndex + 1], + expect(scopedLog.logData).toEqual( + blocks[targetBlockIndex].data.body.noteEncryptedLogs.txLogs[targetTxIndex].unrollLogs()[logIndex + 1].data, ); }); }); diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts index d7ff5f8c1d5..8cbb627a5ce 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts @@ -9,7 +9,7 @@ import { type TxEffect, type TxHash, type TxReceipt, - type TxScopedEncryptedL2NoteLog, + type TxScopedL2Log, } from '@aztec/circuit-types'; import { type ContractClassPublic, @@ -245,7 +245,7 @@ export class KVArchiverDataStore implements ArchiverDataStore { * @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match * that tag. */ - getLogsByTags(tags: Fr[]): Promise { + getLogsByTags(tags: Fr[]): Promise { try { return this.#logStore.getLogsByTags(tags); } catch (err) { @@ -266,6 +266,19 @@ export class KVArchiverDataStore implements ArchiverDataStore { } } + /** + * Gets contract class logs based on the provided filter. + * @param filter - The filter to apply to the logs. + * @returns The requested logs. + */ + getContractClassLogs(filter: LogFilter): Promise { + try { + return Promise.resolve(this.#logStore.getContractClassLogs(filter)); + } catch (err) { + return Promise.reject(err); + } + } + /** * Gets the number of the latest L2 block processed. * @returns The number of the latest L2 block processed. diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts index 2cdbb52b34c..f6c0abbc327 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/log_store.ts @@ -1,4 +1,6 @@ import { + type Body, + ContractClass2BlockL2Logs, EncryptedL2BlockL2Logs, EncryptedNoteL2BlockL2Logs, ExtendedUnencryptedL2Log, @@ -9,14 +11,14 @@ import { type LogFilter, LogId, LogType, - TxScopedEncryptedL2NoteLog, + TxScopedL2Log, UnencryptedL2BlockL2Logs, type UnencryptedL2Log, } from '@aztec/circuit-types'; import { Fr } from '@aztec/circuits.js'; import { INITIAL_L2_BLOCK_NUM, MAX_NOTE_HASHES_PER_TX } from '@aztec/circuits.js/constants'; import { createDebugLogger } from '@aztec/foundation/log'; -import { type AztecKVStore, type AztecMap, type AztecMultiMap } from '@aztec/kv-store'; +import { type AztecKVStore, type AztecMap } from '@aztec/kv-store'; import { type BlockStore } from './block_store.js'; @@ -25,66 +27,123 @@ import { type BlockStore } from './block_store.js'; */ export class LogStore { #noteEncryptedLogsByBlock: AztecMap; - #noteEncryptedLogsByHash: AztecMap; - #noteEncryptedLogHashesByTag: AztecMultiMap; - #noteEncryptedLogTagsByBlock: AztecMultiMap; + #logsByTag: AztecMap; + #logTagsByBlock: AztecMap; #encryptedLogsByBlock: AztecMap; #unencryptedLogsByBlock: AztecMap; + #contractClassLogsByBlock: AztecMap; #logsMaxPageSize: number; #log = createDebugLogger('aztec:archiver:log_store'); constructor(private db: AztecKVStore, private blockStore: BlockStore, logsMaxPageSize: number = 1000) { this.#noteEncryptedLogsByBlock = db.openMap('archiver_note_encrypted_logs_by_block'); - this.#noteEncryptedLogsByHash = db.openMap('archiver_note_encrypted_logs_by_hash'); - this.#noteEncryptedLogHashesByTag = db.openMultiMap('archiver_tagged_note_encrypted_log_hashes_by_tag'); - this.#noteEncryptedLogTagsByBlock = db.openMultiMap('archiver_note_encrypted_log_tags_by_block'); + this.#logsByTag = db.openMap('archiver_tagged_logs_by_tag'); + this.#logTagsByBlock = db.openMap('archiver_log_tags_by_block'); this.#encryptedLogsByBlock = db.openMap('archiver_encrypted_logs_by_block'); this.#unencryptedLogsByBlock = db.openMap('archiver_unencrypted_logs_by_block'); + this.#contractClassLogsByBlock = db.openMap('archiver_contract_class_logs_by_block'); this.#logsMaxPageSize = logsMaxPageSize; } + #extractTaggedLogs(block: L2Block, logType: keyof Pick) { + const taggedLogs = new Map(); + const dataStartIndexForBlock = + block.header.state.partial.noteHashTree.nextAvailableLeafIndex - + block.body.numberOfTxsIncludingPadded * MAX_NOTE_HASHES_PER_TX; + block.body[logType].txLogs.forEach((txLogs, txIndex) => { + const txHash = block.body.txEffects[txIndex].txHash; + const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX; + const logs = txLogs.unrollLogs(); + logs.forEach(log => { + if ( + (logType == 'noteEncryptedLogs' && log.data.length < 32) || + // TODO remove when #9835 and #9836 are fixed + (logType === 'unencryptedLogs' && log.data.length < 32 * 33) + ) { + this.#log.warn(`Skipping log (${logType}) with invalid data length: ${log.data.length}`); + return; + } + try { + let tag = Fr.ZERO; + // TODO remove when #9835 and #9836 are fixed. The partial note logs are emitted as bytes, but encoded as Fields. + // This means that for every 32 bytes of payload, we only have 1 byte of data. + // Also, the tag is not stored in the first 32 bytes of the log, (that's the length of public fields now) but in the next 32. + if (logType === 'unencryptedLogs') { + const correctedBuffer = Buffer.alloc(32); + const initialOffset = 32; + for (let i = 0; i < 32; i++) { + const byte = Fr.fromBuffer( + log.data.subarray(i * 32 + initialOffset, i * 32 + 32 + initialOffset), + ).toNumber(); + correctedBuffer.writeUInt8(byte, i); + } + tag = new Fr(correctedBuffer); + } else { + tag = new Fr(log.data.subarray(0, 32)); + } + this.#log.verbose(`Found tagged (${logType}) log with tag ${tag.toString()} in block ${block.number}`); + const currentLogs = taggedLogs.get(tag.toString()) ?? []; + currentLogs.push( + new TxScopedL2Log( + txHash, + dataStartIndexForTx, + block.number, + logType === 'unencryptedLogs', + log.data, + ).toBuffer(), + ); + taggedLogs.set(tag.toString(), currentLogs); + } catch (err) { + this.#log.warn(`Failed to add tagged log to store: ${err}`); + } + }); + }); + return taggedLogs; + } + /** * Append new logs to the store's list. * @param blocks - The blocks for which to add the logs. * @returns True if the operation is successful. */ - addLogs(blocks: L2Block[]): Promise { + async addLogs(blocks: L2Block[]): Promise { + const taggedLogsToAdd = blocks + .flatMap(block => [ + this.#extractTaggedLogs(block, 'noteEncryptedLogs'), + this.#extractTaggedLogs(block, 'unencryptedLogs'), + ]) + .reduce((acc, val) => { + for (const [tag, logs] of val.entries()) { + const currentLogs = acc.get(tag) ?? []; + acc.set(tag, currentLogs.concat(logs)); + } + return acc; + }); + const tagsToUpdate = Array.from(taggedLogsToAdd.keys()); + const currentTaggedLogs = await this.db.transaction(() => + tagsToUpdate.map(tag => ({ tag, logBuffers: this.#logsByTag.get(tag) })), + ); + currentTaggedLogs.forEach(taggedLogBuffer => { + if (taggedLogBuffer.logBuffers && taggedLogBuffer.logBuffers.length > 0) { + taggedLogsToAdd.set( + taggedLogBuffer.tag, + taggedLogBuffer.logBuffers!.concat(taggedLogsToAdd.get(taggedLogBuffer.tag)!), + ); + } + }); return this.db.transaction(() => { blocks.forEach(block => { - const dataStartIndexForBlock = - block.header.state.partial.noteHashTree.nextAvailableLeafIndex - - block.body.numberOfTxsIncludingPadded * MAX_NOTE_HASHES_PER_TX; + const tagsInBlock = []; + for (const [tag, logs] of taggedLogsToAdd.entries()) { + void this.#logsByTag.set(tag, logs); + tagsInBlock.push(tag); + } + void this.#logTagsByBlock.set(block.number, tagsInBlock); void this.#noteEncryptedLogsByBlock.set(block.number, block.body.noteEncryptedLogs.toBuffer()); - block.body.noteEncryptedLogs.txLogs.forEach((txLogs, txIndex) => { - const txHash = block.body.txEffects[txIndex].txHash; - const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX; - const noteLogs = txLogs.unrollLogs(); - noteLogs.forEach(noteLog => { - if (noteLog.data.length < 32) { - this.#log.warn(`Skipping note log with invalid data length: ${noteLog.data.length}`); - return; - } - try { - const tag = new Fr(noteLog.data.subarray(0, 32)); - const hexHash = noteLog.hash().toString('hex'); - // Ideally we'd store all of the logs for a matching tag in an AztecMultiMap, but this type doesn't - // handle storing buffers well. The 'ordered-binary' encoding returns an error trying to decode buffers - // ('the number <> cannot be converted to a BigInt because it is not an integer'). We therefore store - // instead the hashes of the logs. - void this.#noteEncryptedLogHashesByTag.set(tag.toString(), hexHash); - void this.#noteEncryptedLogsByHash.set( - hexHash, - new TxScopedEncryptedL2NoteLog(txHash, dataStartIndexForTx, noteLog).toBuffer(), - ); - void this.#noteEncryptedLogTagsByBlock.set(block.number, tag.toString()); - } catch (err) { - this.#log.warn(`Failed to add tagged note log to store: ${err}`); - } - }); - }); void this.#encryptedLogsByBlock.set(block.number, block.body.encryptedLogs.toBuffer()); void this.#unencryptedLogsByBlock.set(block.number, block.body.unencryptedLogs.toBuffer()); + void this.#contractClassLogsByBlock.set(block.number, block.body.contractClassLogs.toBuffer()); }); return true; @@ -92,26 +151,19 @@ export class LogStore { } async deleteLogs(blocks: L2Block[]): Promise { - const noteTagsToDelete = await this.db.transaction(() => { - return blocks.flatMap(block => Array.from(this.#noteEncryptedLogTagsByBlock.getValues(block.number))); - }); - const noteLogHashesToDelete = await this.db.transaction(() => { - return noteTagsToDelete.flatMap(tag => Array.from(this.#noteEncryptedLogHashesByTag.getValues(tag))); + const tagsToDelete = await this.db.transaction(() => { + return blocks.flatMap(block => this.#logTagsByBlock.get(block.number)?.map(tag => tag.toString()) ?? []); }); return this.db.transaction(() => { blocks.forEach(block => { void this.#noteEncryptedLogsByBlock.delete(block.number); void this.#encryptedLogsByBlock.delete(block.number); void this.#unencryptedLogsByBlock.delete(block.number); - void this.#noteEncryptedLogTagsByBlock.delete(block.number); - }); - - noteTagsToDelete.forEach(tag => { - void this.#noteEncryptedLogHashesByTag.delete(tag.toString()); + void this.#logTagsByBlock.delete(block.number); }); - noteLogHashesToDelete.forEach(hash => { - void this.#noteEncryptedLogsByHash.delete(hash); + tagsToDelete.forEach(tag => { + void this.#logsByTag.delete(tag.toString()); }); return true; @@ -164,20 +216,12 @@ export class LogStore { * @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match * that tag. */ - getLogsByTags(tags: Fr[]): Promise { - return this.db.transaction(() => { - return tags.map(tag => { - const logHashes = Array.from(this.#noteEncryptedLogHashesByTag.getValues(tag.toString())); - return ( - logHashes - .map(hash => this.#noteEncryptedLogsByHash.get(hash)) - // addLogs should ensure that we never have undefined logs, but we filter them out regardless to protect - // ourselves from database corruption - .filter(noteLogBuffer => noteLogBuffer != undefined) - .map(noteLogBuffer => TxScopedEncryptedL2NoteLog.fromBuffer(noteLogBuffer!)) - ); - }); - }); + getLogsByTags(tags: Fr[]): Promise { + return this.db.transaction(() => + tags + .map(tag => this.#logsByTag.get(tag.toString())) + .map(noteLogBuffers => noteLogBuffers?.map(noteLogBuffer => TxScopedL2Log.fromBuffer(noteLogBuffer)) ?? []), + ); } /** @@ -244,6 +288,72 @@ export class LogStore { return { logs, maxLogsHit }; } + /** + * Gets contract class logs based on the provided filter. + * @param filter - The filter to apply to the logs. + * @returns The requested logs. + */ + getContractClassLogs(filter: LogFilter): GetUnencryptedLogsResponse { + if (filter.afterLog) { + return this.#filterContractClassLogsBetweenBlocks(filter); + } else if (filter.txHash) { + return this.#filterContractClassLogsOfTx(filter); + } else { + return this.#filterContractClassLogsBetweenBlocks(filter); + } + } + + #filterContractClassLogsOfTx(filter: LogFilter): GetUnencryptedLogsResponse { + if (!filter.txHash) { + throw new Error('Missing txHash'); + } + + const [blockNumber, txIndex] = this.blockStore.getTxLocation(filter.txHash) ?? []; + if (typeof blockNumber !== 'number' || typeof txIndex !== 'number') { + return { logs: [], maxLogsHit: false }; + } + const contractClassLogsBuffer = this.#contractClassLogsByBlock.get(blockNumber); + const contractClassLogsInBlock = contractClassLogsBuffer + ? ContractClass2BlockL2Logs.fromBuffer(contractClassLogsBuffer) + : new ContractClass2BlockL2Logs([]); + const txLogs = contractClassLogsInBlock.txLogs[txIndex].unrollLogs(); + + const logs: ExtendedUnencryptedL2Log[] = []; + const maxLogsHit = this.#accumulateLogs(logs, blockNumber, txIndex, txLogs, filter); + + return { logs, maxLogsHit }; + } + + #filterContractClassLogsBetweenBlocks(filter: LogFilter): GetUnencryptedLogsResponse { + const start = + filter.afterLog?.blockNumber ?? Math.max(filter.fromBlock ?? INITIAL_L2_BLOCK_NUM, INITIAL_L2_BLOCK_NUM); + const end = filter.toBlock; + + if (typeof end === 'number' && end < start) { + return { + logs: [], + maxLogsHit: true, + }; + } + + const logs: ExtendedUnencryptedL2Log[] = []; + + let maxLogsHit = false; + loopOverBlocks: for (const [blockNumber, logBuffer] of this.#contractClassLogsByBlock.entries({ start, end })) { + const contractClassLogsInBlock = ContractClass2BlockL2Logs.fromBuffer(logBuffer); + for (let txIndex = filter.afterLog?.txIndex ?? 0; txIndex < contractClassLogsInBlock.txLogs.length; txIndex++) { + const txLogs = contractClassLogsInBlock.txLogs[txIndex].unrollLogs(); + maxLogsHit = this.#accumulateLogs(logs, blockNumber, txIndex, txLogs, filter); + if (maxLogsHit) { + this.#log.debug(`Max logs hit at block ${blockNumber}`); + break loopOverBlocks; + } + } + } + + return { logs, maxLogsHit }; + } + #accumulateLogs( results: ExtendedUnencryptedL2Log[], blockNumber: number, diff --git a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts index 14637a80a10..e49ab8eccc2 100644 --- a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts @@ -1,4 +1,6 @@ import { + type Body, + type ContractClass2BlockL2Logs, type EncryptedL2BlockL2Logs, type EncryptedNoteL2BlockL2Logs, ExtendedUnencryptedL2Log, @@ -13,7 +15,7 @@ import { type TxEffect, type TxHash, TxReceipt, - TxScopedEncryptedL2NoteLog, + TxScopedL2Log, type UnencryptedL2BlockL2Logs, } from '@aztec/circuit-types'; import { @@ -52,14 +54,16 @@ export class MemoryArchiverStore implements ArchiverDataStore { private noteEncryptedLogsPerBlock: Map = new Map(); - private taggedNoteEncryptedLogs: Map = new Map(); + private taggedLogs: Map = new Map(); - private noteEncryptedLogTagsPerBlock: Map = new Map(); + private logTagsPerBlock: Map = new Map(); private encryptedLogsPerBlock: Map = new Map(); private unencryptedLogsPerBlock: Map = new Map(); + private contractClassLogsPerBlock: Map = new Map(); + /** * Contains all L1 to L2 messages. */ @@ -207,6 +211,56 @@ export class MemoryArchiverStore implements ArchiverDataStore { return Promise.resolve(true); } + #storeTaggedLogs(block: L2Block, logType: keyof Pick): void { + const dataStartIndexForBlock = + block.header.state.partial.noteHashTree.nextAvailableLeafIndex - + block.body.numberOfTxsIncludingPadded * MAX_NOTE_HASHES_PER_TX; + block.body[logType].txLogs.forEach((txLogs, txIndex) => { + const txHash = block.body.txEffects[txIndex].txHash; + const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX; + const logs = txLogs.unrollLogs(); + logs.forEach(log => { + if ( + (logType == 'noteEncryptedLogs' && log.data.length < 32) || + // TODO remove when #9835 and #9836 are fixed + (logType === 'unencryptedLogs' && log.data.length < 32 * 33) + ) { + this.#log.warn(`Skipping log (${logType}) with invalid data length: ${log.data.length}`); + return; + } + try { + let tag = Fr.ZERO; + // TODO remove when #9835 and #9836 are fixed. The partial note logs are emitted as bytes, but encoded as Fields. + // This means that for every 32 bytes of payload, we only have 1 byte of data. + // Also, the tag is not stored in the first 32 bytes of the log, (that's the length of public fields now) but in the next 32. + if (logType === 'unencryptedLogs') { + const correctedBuffer = Buffer.alloc(32); + const initialOffset = 32; + for (let i = 0; i < 32; i++) { + const byte = Fr.fromBuffer( + log.data.subarray(i * 32 + initialOffset, i * 32 + 32 + initialOffset), + ).toNumber(); + correctedBuffer.writeUInt8(byte, i); + } + tag = new Fr(correctedBuffer); + } else { + tag = new Fr(log.data.subarray(0, 32)); + } + this.#log.verbose(`Storing tagged (${logType}) log with tag ${tag.toString()} in block ${block.number}`); + const currentLogs = this.taggedLogs.get(tag.toString()) || []; + this.taggedLogs.set(tag.toString(), [ + ...currentLogs, + new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, logType === 'unencryptedLogs', log.data), + ]); + const currentTagsInBlock = this.logTagsPerBlock.get(block.number) || []; + this.logTagsPerBlock.set(block.number, [...currentTagsInBlock, tag]); + } catch (err) { + this.#log.warn(`Failed to add tagged log to store: ${err}`); + } + }); + }); + } + /** * Append new logs to the store's list. * @param block - The block for which to add the logs. @@ -214,52 +268,30 @@ export class MemoryArchiverStore implements ArchiverDataStore { */ addLogs(blocks: L2Block[]): Promise { blocks.forEach(block => { - const dataStartIndexForBlock = - block.header.state.partial.noteHashTree.nextAvailableLeafIndex - - block.body.numberOfTxsIncludingPadded * MAX_NOTE_HASHES_PER_TX; + void this.#storeTaggedLogs(block, 'noteEncryptedLogs'); + void this.#storeTaggedLogs(block, 'unencryptedLogs'); this.noteEncryptedLogsPerBlock.set(block.number, block.body.noteEncryptedLogs); - block.body.noteEncryptedLogs.txLogs.forEach((txLogs, txIndex) => { - const txHash = block.body.txEffects[txIndex].txHash; - const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX; - const noteLogs = txLogs.unrollLogs(); - noteLogs.forEach(noteLog => { - if (noteLog.data.length < 32) { - this.#log.warn(`Skipping note log with invalid data length: ${noteLog.data.length}`); - return; - } - try { - const tag = new Fr(noteLog.data.subarray(0, 32)); - const currentNoteLogs = this.taggedNoteEncryptedLogs.get(tag.toString()) || []; - this.taggedNoteEncryptedLogs.set(tag.toString(), [ - ...currentNoteLogs, - new TxScopedEncryptedL2NoteLog(txHash, dataStartIndexForTx, noteLog), - ]); - const currentTagsInBlock = this.noteEncryptedLogTagsPerBlock.get(block.number) || []; - this.noteEncryptedLogTagsPerBlock.set(block.number, [...currentTagsInBlock, tag]); - } catch (err) { - this.#log.warn(`Failed to add tagged note log to store: ${err}`); - } - }); - }); this.encryptedLogsPerBlock.set(block.number, block.body.encryptedLogs); this.unencryptedLogsPerBlock.set(block.number, block.body.unencryptedLogs); + this.contractClassLogsPerBlock.set(block.number, block.body.contractClassLogs); }); return Promise.resolve(true); } deleteLogs(blocks: L2Block[]): Promise { - const noteTagsToDelete = blocks.flatMap(block => this.noteEncryptedLogTagsPerBlock.get(block.number)); - noteTagsToDelete + const tagsToDelete = blocks.flatMap(block => this.logTagsPerBlock.get(block.number)); + tagsToDelete .filter(tag => tag != undefined) .forEach(tag => { - this.taggedNoteEncryptedLogs.delete(tag!.toString()); + this.taggedLogs.delete(tag!.toString()); }); blocks.forEach(block => { this.encryptedLogsPerBlock.delete(block.number); this.noteEncryptedLogsPerBlock.delete(block.number); this.unencryptedLogsPerBlock.delete(block.number); - this.noteEncryptedLogTagsPerBlock.delete(block.number); + this.logTagsPerBlock.delete(block.number); + this.contractClassLogsPerBlock.delete(block.number); }); return Promise.resolve(true); @@ -428,8 +460,8 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match * that tag. */ - getLogsByTags(tags: Fr[]): Promise { - const noteLogs = tags.map(tag => this.taggedNoteEncryptedLogs.get(tag.toString()) || []); + getLogsByTags(tags: Fr[]): Promise { + const noteLogs = tags.map(tag => this.taggedLogs.get(tag.toString()) || []); return Promise.resolve(noteLogs); } @@ -516,6 +548,90 @@ export class MemoryArchiverStore implements ArchiverDataStore { }); } + /** + * Gets contract class logs based on the provided filter. + * NB: clone of the above fn, but for contract class logs + * @param filter - The filter to apply to the logs. + * @returns The requested logs. + * @remarks Works by doing an intersection of all params in the filter. + */ + getContractClassLogs(filter: LogFilter): Promise { + let txHash: TxHash | undefined; + let fromBlock = 0; + let toBlock = this.l2Blocks.length + INITIAL_L2_BLOCK_NUM; + let txIndexInBlock = 0; + let logIndexInTx = 0; + + if (filter.afterLog) { + // Continuation parameter is set --> tx hash is ignored + if (filter.fromBlock == undefined || filter.fromBlock <= filter.afterLog.blockNumber) { + fromBlock = filter.afterLog.blockNumber; + txIndexInBlock = filter.afterLog.txIndex; + logIndexInTx = filter.afterLog.logIndex + 1; // We want to start from the next log + } else { + fromBlock = filter.fromBlock; + } + } else { + txHash = filter.txHash; + + if (filter.fromBlock !== undefined) { + fromBlock = filter.fromBlock; + } + } + + if (filter.toBlock !== undefined) { + toBlock = filter.toBlock; + } + + // Ensure the indices are within block array bounds + fromBlock = Math.max(fromBlock, INITIAL_L2_BLOCK_NUM); + toBlock = Math.min(toBlock, this.l2Blocks.length + INITIAL_L2_BLOCK_NUM); + + if (fromBlock > this.l2Blocks.length || toBlock < fromBlock || toBlock <= 0) { + return Promise.resolve({ + logs: [], + maxLogsHit: false, + }); + } + + const contractAddress = filter.contractAddress; + + const logs: ExtendedUnencryptedL2Log[] = []; + + for (; fromBlock < toBlock; fromBlock++) { + const block = this.l2Blocks[fromBlock - INITIAL_L2_BLOCK_NUM]; + const blockLogs = this.contractClassLogsPerBlock.get(fromBlock); + + if (blockLogs) { + for (; txIndexInBlock < blockLogs.txLogs.length; txIndexInBlock++) { + const txLogs = blockLogs.txLogs[txIndexInBlock].unrollLogs(); + for (; logIndexInTx < txLogs.length; logIndexInTx++) { + const log = txLogs[logIndexInTx]; + if ( + (!txHash || block.data.body.txEffects[txIndexInBlock].txHash.equals(txHash)) && + (!contractAddress || log.contractAddress.equals(contractAddress)) + ) { + logs.push(new ExtendedUnencryptedL2Log(new LogId(block.data.number, txIndexInBlock, logIndexInTx), log)); + if (logs.length === this.maxLogs) { + return Promise.resolve({ + logs, + maxLogsHit: true, + }); + } + } + } + logIndexInTx = 0; + } + } + txIndexInBlock = 0; + } + + return Promise.resolve({ + logs, + maxLogsHit: false, + }); + } + /** * Gets the number of the latest L2 block processed. * @returns The number of the latest L2 block processed. diff --git a/yarn-project/archiver/src/factory.ts b/yarn-project/archiver/src/factory.ts index b7f5d8d8ab8..ac5b2786757 100644 --- a/yarn-project/archiver/src/factory.ts +++ b/yarn-project/archiver/src/factory.ts @@ -1,5 +1,7 @@ +import { type ArchiverApi, type Service } from '@aztec/circuit-types'; import { type ContractClassPublic } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; +import { type Maybe } from '@aztec/foundation/types'; import { createStore } from '@aztec/kv-store/utils'; import { getCanonicalProtocolContract, protocolContractNames } from '@aztec/protocol-contracts'; import { type TelemetryClient } from '@aztec/telemetry-client'; @@ -8,13 +10,13 @@ import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { Archiver } from './archiver/archiver.js'; import { type ArchiverConfig } from './archiver/config.js'; import { KVArchiverDataStore } from './archiver/index.js'; -import { createArchiverClient } from './rpc/archiver_client.js'; +import { createArchiverClient } from './rpc/index.js'; export async function createArchiver( config: ArchiverConfig, telemetry: TelemetryClient = new NoopTelemetryClient(), opts: { blockUntilSync: boolean } = { blockUntilSync: true }, -) { +): Promise> { if (!config.archiverUrl) { const store = await createStore('archiver', config, createDebugLogger('aztec:archiver:lmdb')); const archiverStore = new KVArchiverDataStore(store, config.maxLogs); diff --git a/yarn-project/archiver/src/rpc/archiver_client.ts b/yarn-project/archiver/src/rpc/archiver_client.ts deleted file mode 100644 index 562b89148c2..00000000000 --- a/yarn-project/archiver/src/rpc/archiver_client.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { - EncryptedNoteL2BlockL2Logs, - ExtendedUnencryptedL2Log, - L2Block, - NullifierMembershipWitness, - TxReceipt, - UnencryptedL2BlockL2Logs, -} from '@aztec/circuit-types'; -import { EthAddress, Fr } from '@aztec/circuits.js'; -import { createJsonRpcClient, makeFetch } from '@aztec/foundation/json-rpc/client'; - -import { type ArchiveSource } from '../archiver/archiver.js'; - -export const createArchiverClient = (url: string, fetch = makeFetch([1, 2, 3], true)): ArchiveSource => - createJsonRpcClient( - url, - { - EthAddress, - ExtendedUnencryptedL2Log, - Fr, - L2Block, - EncryptedNoteL2BlockL2Logs, - UnencryptedL2BlockL2Logs, - }, - { TxReceipt, NullifierMembershipWitness }, - false, - 'archiver', - fetch, - ) as ArchiveSource; diff --git a/yarn-project/archiver/src/rpc/archiver_server.ts b/yarn-project/archiver/src/rpc/archiver_server.ts deleted file mode 100644 index be18f647e79..00000000000 --- a/yarn-project/archiver/src/rpc/archiver_server.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { - EncryptedNoteL2BlockL2Logs, - ExtendedUnencryptedL2Log, - L2Block, - NullifierMembershipWitness, - TxEffect, - TxReceipt, - UnencryptedL2BlockL2Logs, -} from '@aztec/circuit-types'; -import { EthAddress, Fr } from '@aztec/circuits.js'; -import { JsonRpcServer } from '@aztec/foundation/json-rpc/server'; - -import { type Archiver } from '../archiver/archiver.js'; - -/** - * Wrap an Archiver instance with a JSON RPC HTTP server. - * @param archiverService - The Archiver instance - * @returns An JSON-RPC HTTP server - */ -export function createArchiverRpcServer(archiverService: Archiver): JsonRpcServer { - return new JsonRpcServer( - archiverService, - { - EthAddress, - ExtendedUnencryptedL2Log, - Fr, - L2Block, - EncryptedNoteL2BlockL2Logs, - UnencryptedL2BlockL2Logs, - TxEffect, - }, - { TxReceipt, NullifierMembershipWitness }, - ['start', 'stop'], - ); -} diff --git a/yarn-project/archiver/src/rpc/index.ts b/yarn-project/archiver/src/rpc/index.ts index 726d9120af8..5845eacb4b8 100644 --- a/yarn-project/archiver/src/rpc/index.ts +++ b/yarn-project/archiver/src/rpc/index.ts @@ -1,2 +1,11 @@ -export * from './archiver_client.js'; -export * from './archiver_server.js'; +import { type ArchiverApi, ArchiverApiSchema } from '@aztec/circuit-types'; +import { createSafeJsonRpcClient, makeFetch } from '@aztec/foundation/json-rpc/client'; +import { createSafeJsonRpcServer } from '@aztec/foundation/json-rpc/server'; + +export function createArchiverClient(url: string, fetch = makeFetch([1, 2, 3], true)): ArchiverApi { + return createSafeJsonRpcClient(url, ArchiverApiSchema, false, 'archiver', fetch); +} + +export function createArchiverRpcServer(handler: ArchiverApi) { + return createSafeJsonRpcServer(handler, ArchiverApiSchema); +} diff --git a/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts b/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts index 00553b4d004..3ceaf4c6c69 100644 --- a/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts +++ b/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts @@ -1,28 +1,5 @@ -import { - type AztecNode, - EncryptedL2NoteLog, - EncryptedNoteL2BlockL2Logs, - EpochProofQuote, - ExtendedUnencryptedL2Log, - L2Block, - LogId, - NullifierMembershipWitness, - PublicDataWitness, - PublicSimulationOutput, - SiblingPath, - Tx, - TxEffect, - TxHash, - TxReceipt, - UnencryptedL2BlockL2Logs, -} from '@aztec/circuit-types'; -import { FunctionSelector, Header, PublicKeys } from '@aztec/circuits.js'; -import { NoteSelector } from '@aztec/foundation/abi'; -import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { Buffer32 } from '@aztec/foundation/buffer'; -import { EthAddress } from '@aztec/foundation/eth-address'; -import { Fr } from '@aztec/foundation/fields'; -import { JsonRpcServer } from '@aztec/foundation/json-rpc/server'; +import { type AztecNode, AztecNodeApiSchema } from '@aztec/circuit-types'; +import { createSafeJsonRpcServer } from '@aztec/foundation/json-rpc/server'; /** * Wrap an AztecNode instance with a JSON RPC HTTP server. @@ -30,37 +7,5 @@ import { JsonRpcServer } from '@aztec/foundation/json-rpc/server'; * @returns An JSON-RPC HTTP server */ export function createAztecNodeRpcServer(node: AztecNode) { - const rpc = new JsonRpcServer( - node, - { - AztecAddress, - EthAddress, - ExtendedUnencryptedL2Log, - Fr, - FunctionSelector, - Header, - L2Block, - TxEffect, - LogId, - TxHash, - Buffer32, - PublicDataWitness, - PublicKeys, - SiblingPath, - }, - { - EncryptedNoteL2BlockL2Logs, - EncryptedL2NoteLog, - NoteSelector, - NullifierMembershipWitness, - PublicSimulationOutput, - Tx, - TxReceipt, - UnencryptedL2BlockL2Logs, - EpochProofQuote, - }, - // disable methods not part of the AztecNode interface - ['start', 'stop'], - ); - return rpc; + return createSafeJsonRpcServer(node, AztecNodeApiSchema); } diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index cf3f9b787d3..04e0b642b13 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -21,15 +21,17 @@ import { PublicDataWitness, PublicSimulationOutput, type SequencerConfig, + type Service, SiblingPath, type Tx, type TxEffect, type TxHash, TxReceipt, - type TxScopedEncryptedL2NoteLog, + type TxScopedL2Log, TxStatus, type TxValidator, type WorldStateSynchronizer, + tryStop, } from '@aztec/circuit-types'; import { type ARCHIVE_HEIGHT, @@ -90,7 +92,7 @@ export class AztecNodeService implements AztecNode { constructor( protected config: AztecNodeConfig, protected readonly p2pClient: P2P, - protected readonly blockSource: L2BlockSource, + protected readonly blockSource: L2BlockSource & Partial, protected readonly encryptedLogsSource: L2LogsSource, protected readonly unencryptedLogsSource: L2LogsSource, protected readonly contractDataSource: ContractDataSource, @@ -337,7 +339,7 @@ export class AztecNodeService implements AztecNode { * @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match * that tag. */ - public getLogsByTags(tags: Fr[]): Promise { + public getLogsByTags(tags: Fr[]): Promise { return this.encryptedLogsSource.getLogsByTags(tags); } @@ -350,6 +352,15 @@ export class AztecNodeService implements AztecNode { return this.unencryptedLogsSource.getUnencryptedLogs(filter); } + /** + * Gets contract class logs based on the provided filter. + * @param filter - The filter to apply to the logs. + * @returns The requested logs. + */ + getContractClassLogs(filter: LogFilter): Promise { + return this.unencryptedLogsSource.getContractClassLogs(filter); + } + /** * Method to submit a transaction to the p2p pool. * @param tx - The transaction to be submitted. @@ -397,7 +408,7 @@ export class AztecNodeService implements AztecNode { await this.sequencer?.stop(); await this.p2pClient.stop(); await this.worldStateSynchronizer.stop(); - await this.blockSource.stop(); + await tryStop(this.blockSource); await this.telemetry.stop(); this.log.info(`Stopped`); } @@ -424,19 +435,19 @@ export class AztecNodeService implements AztecNode { } /** - * Find the index of the given leaf in the given tree. - * @param blockNumber - The block number at which to get the data + * Find the indexes of the given leaves in the given tree. + * @param blockNumber - The block number at which to get the data or 'latest' for latest data * @param treeId - The tree to search in. - * @param leafValue - The value to search for - * @returns The index of the given leaf in the given tree or undefined if not found. + * @param leafValue - The values to search for + * @returns The indexes of the given leaves in the given tree or undefined if not found. */ - public async findLeafIndex( + public async findLeavesIndexes( blockNumber: L2BlockNumber, treeId: MerkleTreeId, - leafValue: Fr, - ): Promise { + leafValues: Fr[], + ): Promise<(bigint | undefined)[]> { const committedDb = await this.#getWorldState(blockNumber); - return committedDb.findLeafIndex(treeId, leafValue.toBuffer()); + return await Promise.all(leafValues.map(leafValue => committedDb.findLeafIndex(treeId, leafValue.toBuffer()))); } /** diff --git a/yarn-project/aztec.js/src/account_manager/deploy_account_sent_tx.ts b/yarn-project/aztec.js/src/account_manager/deploy_account_sent_tx.ts index fe96e478c38..3ffdfe4ebaa 100644 --- a/yarn-project/aztec.js/src/account_manager/deploy_account_sent_tx.ts +++ b/yarn-project/aztec.js/src/account_manager/deploy_account_sent_tx.ts @@ -3,7 +3,6 @@ import { type FieldsOf } from '@aztec/foundation/types'; import { type Wallet } from '../account/index.js'; import { DefaultWaitOpts, SentTx, type WaitOpts } from '../contract/sent_tx.js'; -import { waitForAccountSynch } from '../utils/account.js'; /** Extends a transaction receipt with a wallet instance for the newly deployed contract. */ export type DeployAccountTxReceipt = FieldsOf & { @@ -37,7 +36,6 @@ export class DeployAccountSentTx extends SentTx { public override async wait(opts: WaitOpts = DefaultWaitOpts): Promise { const receipt = await super.wait(opts); const wallet = await this.getWalletPromise; - await waitForAccountSynch(this.pxe, wallet.getCompleteAddress(), opts); return { ...receipt, wallet }; } } diff --git a/yarn-project/aztec.js/src/account_manager/index.ts b/yarn-project/aztec.js/src/account_manager/index.ts index 4ea49a57103..e4e3316a6db 100644 --- a/yarn-project/aztec.js/src/account_manager/index.ts +++ b/yarn-project/aztec.js/src/account_manager/index.ts @@ -8,7 +8,6 @@ import { type AccountInterface } from '../account/interface.js'; import { type DeployOptions } from '../contract/deploy_method.js'; import { DefaultWaitOpts, type WaitOpts } from '../contract/sent_tx.js'; import { DefaultMultiCallEntrypoint } from '../entrypoint/default_multi_call_entrypoint.js'; -import { waitForAccountSynch } from '../utils/account.js'; import { AccountWalletWithSecretKey, SignerlessWallet } from '../wallet/index.js'; import { DeployAccountMethod } from './deploy_account_method.js'; import { DeployAccountSentTx } from './deploy_account_sent_tx.js'; @@ -105,7 +104,7 @@ export class AccountManager { * @param opts - Options to wait for the account to be synched. * @returns A Wallet instance. */ - public async register(opts: WaitOpts = DefaultWaitOpts): Promise { + public async register(): Promise { await this.pxe.registerContract({ artifact: this.accountContract.getContractArtifact(), instance: this.getInstance(), @@ -113,7 +112,6 @@ export class AccountManager { await this.pxe.registerAccount(this.secretKey, this.getCompleteAddress().partialAddress); - await waitForAccountSynch(this.pxe, this.getCompleteAddress(), opts); return this.getWallet(); } diff --git a/yarn-project/aztec.js/src/contract/batch_call.ts b/yarn-project/aztec.js/src/contract/batch_call.ts index 89cc0beb8ae..31f6ce37df1 100644 --- a/yarn-project/aztec.js/src/contract/batch_call.ts +++ b/yarn-project/aztec.js/src/contract/batch_call.ts @@ -70,7 +70,10 @@ export class BatchCall extends BaseContractInteraction { const unconstrainedCalls = unconstrained.map(async indexedCall => { const call = indexedCall[0]; - return [await this.wallet.simulateUnconstrained(call.name, call.args, call.to, options?.from), indexedCall[1]]; + return [ + await this.wallet.simulateUnconstrained(call.name, call.args, call.to, options?.from), + indexedCall[1], + ] as const; }); const [unconstrainedResults, simulatedTx] = await Promise.all([ diff --git a/yarn-project/aztec.js/src/contract/get_gas_limits.test.ts b/yarn-project/aztec.js/src/contract/get_gas_limits.test.ts index bd77479e8f0..f42e45a0655 100644 --- a/yarn-project/aztec.js/src/contract/get_gas_limits.test.ts +++ b/yarn-project/aztec.js/src/contract/get_gas_limits.test.ts @@ -10,7 +10,7 @@ describe('getGasLimits', () => { txSimulationResult = mockSimulatedTx(); const tx = mockTxForRollup(); - tx.data.forRollup!.end.gasUsed = Gas.from({ daGas: 100, l2Gas: 200 }); + tx.data.gasUsed = Gas.from({ daGas: 100, l2Gas: 200 }); txSimulationResult.publicInputs = tx.data; txSimulationResult.publicOutput!.gasUsed = { diff --git a/yarn-project/aztec.js/src/contract/proven_tx.ts b/yarn-project/aztec.js/src/contract/proven_tx.ts index 05c8defd745..a02eb0c28d3 100644 --- a/yarn-project/aztec.js/src/contract/proven_tx.ts +++ b/yarn-project/aztec.js/src/contract/proven_tx.ts @@ -14,6 +14,7 @@ export class ProvenTx extends Tx { tx.noteEncryptedLogs, tx.encryptedLogs, tx.unencryptedLogs, + tx.contractClassLogs, tx.enqueuedPublicFunctionCalls, tx.publicTeardownFunctionCall, ); @@ -27,6 +28,7 @@ export class ProvenTx extends Tx { this.noteEncryptedLogs, this.encryptedLogs, this.unencryptedLogs, + this.contractClassLogs, this.enqueuedPublicFunctionCalls, this.publicTeardownFunctionCall, ); diff --git a/yarn-project/aztec.js/src/contract/sent_tx.test.ts b/yarn-project/aztec.js/src/contract/sent_tx.test.ts index d7125dd4755..13a2def98cd 100644 --- a/yarn-project/aztec.js/src/contract/sent_tx.test.ts +++ b/yarn-project/aztec.js/src/contract/sent_tx.test.ts @@ -23,34 +23,27 @@ describe('SentTx', () => { pxe.getTxReceipt.mockResolvedValue(txReceipt); }); - it('waits for all notes accounts to be synced', async () => { - pxe.getSyncStatus - .mockResolvedValueOnce({ blocks: 25, notes: { '0x1': 19, '0x2': 20 } }) - .mockResolvedValueOnce({ blocks: 25, notes: { '0x1': 20, '0x2': 20 } }); + it('waits for all notes of the accounts to be available', async () => { + pxe.getSyncStatus.mockResolvedValueOnce({ blocks: 25 }).mockResolvedValueOnce({ blocks: 25 }); const actual = await sentTx.wait({ timeout: 1, interval: 0.4 }); expect(actual).toEqual(txReceipt); }); - it('fails if an account is not synced', async () => { - pxe.getSyncStatus.mockResolvedValue({ blocks: 25, notes: { '0x1': 19, '0x2': 20 } }); - await expect(sentTx.wait({ timeout: 1, interval: 0.4 })).rejects.toThrow(/timeout/i); - }); - it('does not wait for notes sync', async () => { - pxe.getSyncStatus.mockResolvedValue({ blocks: 19, notes: { '0x1': 19, '0x2': 19 } }); - const actual = await sentTx.wait({ timeout: 1, interval: 0.4, waitForNotesSync: false }); + pxe.getSyncStatus.mockResolvedValue({ blocks: 19 }); + const actual = await sentTx.wait({ timeout: 1, interval: 0.4, waitForNotesAvailable: false }); expect(actual).toEqual(txReceipt); }); it('throws if tx is dropped', async () => { pxe.getTxReceipt.mockResolvedValue({ ...txReceipt, status: TxStatus.DROPPED } as TxReceipt); - pxe.getSyncStatus.mockResolvedValue({ blocks: 19, notes: { '0x1': 19, '0x2': 19 } }); + pxe.getSyncStatus.mockResolvedValue({ blocks: 19 }); await expect(sentTx.wait({ timeout: 1, interval: 0.4 })).rejects.toThrow(/dropped/); }); it('waits for the tx to be proven', async () => { - const waitOpts = { timeout: 1, interval: 0.4, waitForNotesSync: false, proven: true, provenTimeout: 2 }; + const waitOpts = { timeout: 1, interval: 0.4, waitForNotesAvailable: false, proven: true, provenTimeout: 2 }; pxe.getProvenBlockNumber.mockResolvedValue(10); await expect(sentTx.wait(waitOpts)).rejects.toThrow(/timeout/i); diff --git a/yarn-project/aztec.js/src/contract/sent_tx.ts b/yarn-project/aztec.js/src/contract/sent_tx.ts index 91b0f5ea2c0..7b85b3fd853 100644 --- a/yarn-project/aztec.js/src/contract/sent_tx.ts +++ b/yarn-project/aztec.js/src/contract/sent_tx.ts @@ -1,11 +1,4 @@ -import { - type ExtendedNote, - type GetUnencryptedLogsResponse, - type PXE, - type TxHash, - type TxReceipt, - TxStatus, -} from '@aztec/circuit-types'; +import { type GetUnencryptedLogsResponse, type PXE, type TxHash, type TxReceipt, TxStatus } from '@aztec/circuit-types'; import { retryUntil } from '@aztec/foundation/retry'; import { type FieldsOf } from '@aztec/foundation/types'; @@ -20,10 +13,10 @@ export type WaitOpts = { /** Whether to wait for the tx to be proven. */ proven?: boolean; /** - * Whether to wait for the PXE Service to sync all notes up to the block in which this tx was mined. + * Whether to wait for the node to notify that the block in which this tx was mined is available to fetch notes from. * If false, then any queries that depend on state set by this transaction may return stale data. Defaults to true. **/ - waitForNotesSync?: boolean; + waitForNotesAvailable?: boolean; /** Whether to include information useful for debugging/testing in the receipt. */ debug?: boolean; /** Whether to accept a revert as a status code for the tx when waiting for it. If false, will throw if the tx reverts. */ @@ -34,8 +27,8 @@ export const DefaultWaitOpts: WaitOpts = { timeout: 60, provenTimeout: 600, interval: 1, - waitForNotesSync: true, debug: false, + waitForNotesAvailable: true, }; /** @@ -74,9 +67,6 @@ export class SentTx { * @returns The transaction receipt. */ public async wait(opts?: WaitOpts): Promise> { - if (opts?.debug && opts.waitForNotesSync === false) { - throw new Error('Cannot set debug to true if waitForNotesSync is false'); - } const receipt = await this.waitForReceipt(opts); if (receipt.status !== TxStatus.SUCCESS && !opts?.dontThrowOnRevert) { throw new Error( @@ -89,15 +79,11 @@ export class SentTx { if (opts?.debug) { const txHash = await this.getTxHash(); const tx = (await this.pxe.getTxEffect(txHash))!; - const visibleIncomingNotes = await this.pxe.getIncomingNotes({ txHash }); - const visibleOutgoingNotes = await this.pxe.getOutgoingNotes({ txHash }); receipt.debugInfo = { noteHashes: tx.noteHashes, nullifiers: tx.nullifiers, publicDataWrites: tx.publicDataWrites, l2ToL1Msgs: tx.l2ToL1Msgs, - visibleIncomingNotes, - visibleOutgoingNotes, }; } return receipt; @@ -113,16 +99,6 @@ export class SentTx { return this.pxe.getUnencryptedLogs({ txHash: await this.getTxHash() }); } - /** - * Get notes of accounts registered in the provided PXE/Wallet created in this tx. - * @remarks This function will wait for the tx to be mined if it hasn't been already. - * @returns The requested notes. - */ - public async getVisibleNotes(): Promise { - await this.wait(); - return this.pxe.getIncomingNotes({ txHash: await this.getTxHash() }); - } - protected async waitForReceipt(opts?: WaitOpts): Promise { const txHash = await this.getTxHash(); return await retryUntil( @@ -137,15 +113,15 @@ export class SentTx { return txReceipt; } // If we don't care about waiting for notes to be synced, return the receipt - const waitForNotesSync = opts?.waitForNotesSync ?? DefaultWaitOpts.waitForNotesSync; - if (!waitForNotesSync) { + const waitForNotesAvailable = opts?.waitForNotesAvailable ?? DefaultWaitOpts.waitForNotesAvailable; + if (!waitForNotesAvailable) { return txReceipt; } // Check if all sync blocks on the PXE Service are greater or equal than the block in which the tx was mined - const { blocks, notes } = await this.pxe.getSyncStatus(); + const { blocks } = await this.pxe.getSyncStatus(); const targetBlock = txReceipt.blockNumber!; - const areNotesSynced = blocks >= targetBlock && Object.values(notes).every(block => block >= targetBlock); - return areNotesSynced ? txReceipt : undefined; + const areNotesAvailable = blocks >= targetBlock; + return areNotesAvailable ? txReceipt : undefined; }, 'isMined', opts?.timeout ?? DefaultWaitOpts.timeout, diff --git a/yarn-project/aztec.js/src/fee/fee_juice_payment_method_with_claim.ts b/yarn-project/aztec.js/src/fee/fee_juice_payment_method_with_claim.ts index 2c3fa87bb59..f69f515388e 100644 --- a/yarn-project/aztec.js/src/fee/fee_juice_payment_method_with_claim.ts +++ b/yarn-project/aztec.js/src/fee/fee_juice_payment_method_with_claim.ts @@ -32,7 +32,12 @@ export class FeeJuicePaymentMethodWithClaim extends FeeJuicePaymentMethod { name: 'claim', selector, isStatic: false, - args: [this.sender, this.claim.claimAmount, this.claim.claimSecret, new Fr(this.claim.messageLeafIndex)], + args: [ + this.sender.toField(), + this.claim.claimAmount, + this.claim.claimSecret, + new Fr(this.claim.messageLeafIndex), + ], returnTypes: [], type: FunctionType.PRIVATE, }, diff --git a/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts b/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts index 0578179ef1c..e505901da36 100644 --- a/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts @@ -65,7 +65,7 @@ export class PrivateFeePaymentMethod implements FeePaymentMethod { caller: this.paymentContract, action: { name: 'setup_refund', - args: [this.feeRecipient, this.wallet.getAddress(), maxFee, nonce], + args: [this.feeRecipient.toField(), this.wallet.getAddress().toField(), maxFee, nonce], selector: FunctionSelector.fromSignature('setup_refund((Field),(Field),Field,Field)'), type: FunctionType.PRIVATE, isStatic: false, @@ -81,7 +81,7 @@ export class PrivateFeePaymentMethod implements FeePaymentMethod { selector: FunctionSelector.fromSignature('fee_entrypoint_private(Field,(Field),Field)'), type: FunctionType.PRIVATE, isStatic: false, - args: [maxFee, this.asset, nonce], + args: [maxFee, this.asset.toField(), nonce], returnTypes: [], }, ]; diff --git a/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts b/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts index dae20d5fe8a..144e307d7ea 100644 --- a/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts @@ -53,9 +53,9 @@ export class PublicFeePaymentMethod implements FeePaymentMethod { { caller: this.paymentContract, action: { - name: 'transfer_public', - args: [this.wallet.getAddress(), this.paymentContract, maxFee, nonce], - selector: FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'), + name: 'transfer_in_public', + args: [this.wallet.getAddress().toField(), this.paymentContract.toField(), maxFee, nonce], + selector: FunctionSelector.fromSignature('transfer_in_public((Field),(Field),Field,Field)'), type: FunctionType.PUBLIC, isStatic: false, to: this.asset, @@ -71,7 +71,7 @@ export class PublicFeePaymentMethod implements FeePaymentMethod { selector: FunctionSelector.fromSignature('fee_entrypoint_public(Field,(Field),Field)'), type: FunctionType.PRIVATE, isStatic: false, - args: [maxFee, this.asset, nonce], + args: [maxFee, this.asset.toField(), nonce], returnTypes: [], }, ]); diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index 52595470936..5adffcba01f 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -53,7 +53,6 @@ export { generateClaimSecret, generatePublicKey, readFieldCompressedString, - waitForAccountSynch, waitForPXE, type AztecAddressLike, type EthAddressLike, @@ -62,7 +61,7 @@ export { type FunctionSelectorLike, type L2AmountClaim, type L2Claim, - type L2RedeemableAmountClaim, + type L2AmountClaimWithRecipient, type WrappedFieldLike, } from './utils/index.js'; @@ -112,6 +111,7 @@ export { Body, Comparator, CompleteAddress, + ContractClass2BlockL2Logs, EncryptedL2BlockL2Logs, EncryptedLogPayload, EncryptedNoteL2BlockL2Logs, diff --git a/yarn-project/aztec.js/src/rpc_clients/pxe_client.ts b/yarn-project/aztec.js/src/rpc_clients/pxe_client.ts index 0e7a81a0714..b95c3802fff 100644 --- a/yarn-project/aztec.js/src/rpc_clients/pxe_client.ts +++ b/yarn-project/aztec.js/src/rpc_clients/pxe_client.ts @@ -1,45 +1,5 @@ -import { - AuthWitness, - CountedNoteLog, - CountedPublicExecutionRequest, - EncryptedL2Log, - EncryptedL2NoteLog, - EncryptedNoteL2BlockL2Logs, - EventMetadata, - ExtendedNote, - ExtendedUnencryptedL2Log, - L2Block, - LogId, - Note, - NullifierMembershipWitness, - type PXE, - PrivateExecutionResult, - SiblingPath, - Tx, - TxEffect, - TxExecutionRequest, - TxHash, - TxProvingResult, - TxReceipt, - TxSimulationResult, - UnencryptedL2BlockL2Logs, - UnencryptedL2Log, - UniqueNote, -} from '@aztec/circuit-types'; -import { - AztecAddress, - CompleteAddress, - EthAddress, - Fr, - FunctionSelector, - GrumpkinScalar, - Point, - PrivateCircuitPublicInputs, - PublicKeys, -} from '@aztec/circuits.js'; -import { EventSelector, NoteSelector } from '@aztec/foundation/abi'; -import { Buffer32 } from '@aztec/foundation/buffer'; -import { createJsonRpcClient, makeFetch } from '@aztec/foundation/json-rpc/client'; +import { type PXE, PXESchema } from '@aztec/circuit-types'; +import { createSafeJsonRpcClient, makeFetch } from '@aztec/foundation/json-rpc/client'; /** * Creates a JSON-RPC client to remotely talk to PXE. @@ -47,51 +7,6 @@ import { createJsonRpcClient, makeFetch } from '@aztec/foundation/json-rpc/clien * @param fetch - The fetch implementation to use. * @returns A JSON-RPC client of PXE. */ -export const createPXEClient = (url: string, fetch = makeFetch([1, 2, 3], false)): PXE => - createJsonRpcClient( - url, - { - AuthWitness, - AztecAddress, - CompleteAddress, - FunctionSelector, - EthAddress, - EventSelector, - ExtendedNote, - UniqueNote, - ExtendedUnencryptedL2Log, - Fr, - GrumpkinScalar, - L2Block, - TxEffect, - LogId, - Note, - Point, - PublicKeys, - TxExecutionRequest, - TxHash, - Buffer32, - SiblingPath, - }, - { - EncryptedNoteL2BlockL2Logs, - EncryptedL2NoteLog, - EncryptedL2Log, - EventMetadata, - UnencryptedL2Log, - NoteSelector, - NullifierMembershipWitness, - TxSimulationResult, - TxProvingResult, - PrivateCircuitPublicInputs, - PrivateExecutionResult, - CountedPublicExecutionRequest, - CountedNoteLog, - Tx, - TxReceipt, - UnencryptedL2BlockL2Logs, - }, - false, - 'pxe', - fetch, - ) as PXE; +export function createPXEClient(url: string, fetch = makeFetch([1, 2, 3], false)): PXE { + return createSafeJsonRpcClient(url, PXESchema, false, 'pxe', fetch); +} diff --git a/yarn-project/aztec.js/src/utils/abi_types.ts b/yarn-project/aztec.js/src/utils/abi_types.ts index 304c109899b..96f43ac5de3 100644 --- a/yarn-project/aztec.js/src/utils/abi_types.ts +++ b/yarn-project/aztec.js/src/utils/abi_types.ts @@ -13,7 +13,7 @@ export type FieldLike = Fr | Buffer | bigint | number | { /** Converts to field export type EthAddressLike = { /** Wrapped address */ address: FieldLike } | EthAddress; /** Any type that can be converted into an AztecAddress Aztec.nr struct. */ -export type AztecAddressLike = { /** Wrapped address */ address: FieldLike } | AztecAddress; +export type AztecAddressLike = { /** Wrapped address */ address: FieldLike } | AztecAddress | Fr; /** Any type that can be converted into a FunctionSelector Aztec.nr struct. */ export type FunctionSelectorLike = FieldLike | FunctionSelector; diff --git a/yarn-project/aztec.js/src/utils/account.ts b/yarn-project/aztec.js/src/utils/account.ts deleted file mode 100644 index 5f11c192ede..00000000000 --- a/yarn-project/aztec.js/src/utils/account.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { type PXE } from '@aztec/circuit-types'; -import { type CompleteAddress } from '@aztec/circuits.js'; -import { retryUntil } from '@aztec/foundation/retry'; - -import { DefaultWaitOpts, type WaitOpts } from '../contract/sent_tx.js'; - -/** - * Waits for the account to finish synchronizing with the PXE Service. - * @param pxe - PXE instance - * @param address - Address to wait for synch - * @param opts - Wait options - */ -export async function waitForAccountSynch( - pxe: PXE, - address: CompleteAddress, - { interval, timeout }: WaitOpts = DefaultWaitOpts, -): Promise { - const accountAddress = address.address.toString(); - await retryUntil( - async () => { - const status = await pxe.getSyncStatus(); - const accountSynchedToBlock = status.notes[accountAddress]; - if (typeof accountSynchedToBlock === 'undefined') { - return false; - } else { - return accountSynchedToBlock >= status.blocks; - } - }, - 'waitForAccountSynch', - timeout, - interval, - ); -} diff --git a/yarn-project/aztec.js/src/utils/authwit.ts b/yarn-project/aztec.js/src/utils/authwit.ts index d59ef37e3d0..51c62370891 100644 --- a/yarn-project/aztec.js/src/utils/authwit.ts +++ b/yarn-project/aztec.js/src/utils/authwit.ts @@ -57,7 +57,7 @@ export const computeAuthWitMessageHash = (intent: IntentInnerHash | IntentAction if ('caller' in intent) { const action = intent.action instanceof ContractFunctionInteraction ? intent.action.request() : intent.action; return computeOuterAuthWitHash( - action.to.toField(), + action.to, chainId, version, computeInnerAuthWitHashFromAction(intent.caller, action), diff --git a/yarn-project/aztec.js/src/utils/cheat_codes.ts b/yarn-project/aztec.js/src/utils/cheat_codes.ts index 7bbc95044cc..f35ae53c25f 100644 --- a/yarn-project/aztec.js/src/utils/cheat_codes.ts +++ b/yarn-project/aztec.js/src/utils/cheat_codes.ts @@ -444,7 +444,8 @@ export class AztecCheatCodes { * @returns The storage slot of the value in the map */ public computeSlotInMap(mapSlot: Fr | bigint, key: Fr | bigint | AztecAddress): Fr { - return deriveStorageSlotInMap(mapSlot, new Fr(key)); + const keyFr = typeof key === 'bigint' ? new Fr(key) : key.toField(); + return deriveStorageSlotInMap(mapSlot, keyFr); } /** diff --git a/yarn-project/aztec.js/src/utils/index.ts b/yarn-project/aztec.js/src/utils/index.ts index 4d9c7dc3969..7a980b6ca68 100644 --- a/yarn-project/aztec.js/src/utils/index.ts +++ b/yarn-project/aztec.js/src/utils/index.ts @@ -4,7 +4,6 @@ export * from './abi_types.js'; export * from './cheat_codes.js'; export * from './authwit.js'; export * from './pxe.js'; -export * from './account.js'; export * from './anvil_test_watcher.js'; export * from './field_compressed_string.js'; export * from './portal_manager.js'; diff --git a/yarn-project/aztec.js/src/utils/portal_manager.ts b/yarn-project/aztec.js/src/utils/portal_manager.ts index 3953f32f54e..7d3c3d2bae2 100644 --- a/yarn-project/aztec.js/src/utils/portal_manager.ts +++ b/yarn-project/aztec.js/src/utils/portal_manager.ts @@ -38,10 +38,9 @@ export type L2Claim = { /** L1 to L2 message info that corresponds to an amount to claim. */ export type L2AmountClaim = L2Claim & { /** Amount to claim */ claimAmount: Fr }; -/** L1 to L2 message info that corresponds to an amount to claim with associated notes to be redeemed. */ -export type L2RedeemableAmountClaim = L2AmountClaim & { - /** Secret for redeeming the minted notes */ redeemSecret: Fr; - /** Hash of the redeem secret*/ redeemSecretHash: Fr; +/** L1 to L2 message info that corresponds to an amount to claim with associated recipient. */ +export type L2AmountClaimWithRecipient = L2AmountClaim & { + /** Address that will receive the newly minted notes. */ recipient: AztecAddress; }; /** Stringifies an eth address for logging. */ @@ -279,17 +278,15 @@ export class L1ToL2TokenPortalManager { * @param amount - Amount of tokens to send. * @param mint - Whether to mint the tokens before sending (only during testing). */ - public async bridgeTokensPrivate(to: AztecAddress, amount: bigint, mint = false): Promise { + public async bridgeTokensPrivate( + to: AztecAddress, + amount: bigint, + mint = false, + ): Promise { const [claimSecret, claimSecretHash] = await this.bridgeSetup(amount, mint); - const redeemSecret = Fr.random(); - const redeemSecretHash = computeSecretHash(redeemSecret); this.logger.info('Sending L1 tokens to L2 to be claimed privately'); - const { request } = await this.portal.simulate.depositToAztecPrivate([ - redeemSecretHash.toString(), - amount, - claimSecretHash.toString(), - ]); + const { request } = await this.portal.simulate.depositToAztecPrivate([amount, claimSecretHash.toString()]); const txReceipt = await this.publicClient.waitForTransactionReceipt({ hash: await this.walletClient.writeContract(request), @@ -300,21 +297,19 @@ export class L1ToL2TokenPortalManager { this.portal.address, this.portal.abi, 'DepositToAztecPrivate', - log => - log.args.secretHashForRedeemingMintedNotes === redeemSecretHash.toString() && - log.args.amount === amount && - log.args.secretHashForL2MessageConsumption === claimSecretHash.toString(), + log => log.args.amount === amount && log.args.secretHashForL2MessageConsumption === claimSecretHash.toString(), this.logger, ); - this.logger.info(`Redeem shield secret: ${redeemSecret.toString()}, secret hash: ${redeemSecretHash.toString()}`); + this.logger.info( + `Claim message secret: ${claimSecret.toString()}, claim message secret hash: ${claimSecretHash.toString()}`, + ); return { claimAmount: new Fr(amount), claimSecret, claimSecretHash, - redeemSecret, - redeemSecretHash, + recipient: to, messageHash: log.args.key, messageLeafIndex: log.args.index, }; @@ -329,7 +324,7 @@ export class L1ToL2TokenPortalManager { } } -/** Helper for interacting with a test TokenPortal on L1 for both withdrawing from and briding to L2. */ +/** Helper for interacting with a test TokenPortal on L1 for both withdrawing from and bridging to L2. */ export class L1TokenPortalManager extends L1ToL2TokenPortalManager { private readonly outbox: GetContractReturnType>; diff --git a/yarn-project/aztec.js/src/utils/pxe.ts b/yarn-project/aztec.js/src/utils/pxe.ts index 700a003d217..57d79ce15ae 100644 --- a/yarn-project/aztec.js/src/utils/pxe.ts +++ b/yarn-project/aztec.js/src/utils/pxe.ts @@ -5,8 +5,9 @@ import { retryUntil } from '@aztec/foundation/retry'; export const waitForPXE = async (pxe: PXE, logger?: DebugLogger) => { await retryUntil(async () => { try { - logger?.debug('Attempting to contact PXE...'); + logger?.verbose('Attempting to contact PXE...'); await pxe.getNodeInfo(); + logger?.verbose('Contacted PXE'); return true; } catch (error) { logger?.verbose('Failed to contact PXE'); diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index bc896799004..00cc9127a38 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -1,6 +1,6 @@ import { type AuthWitness, - type EventType, + type EventMetadataDefinition, type ExtendedNote, type GetUnencryptedLogsResponse, type IncomingNotesFilter, @@ -21,7 +21,6 @@ import { type TxSimulationResult, type UniqueNote, } from '@aztec/circuit-types'; -import { type NoteProcessorStats } from '@aztec/circuit-types/stats'; import { type AztecAddress, type CompleteAddress, @@ -33,7 +32,7 @@ import { type PartialAddress, type Point, } from '@aztec/circuits.js'; -import type { AbiType, ContractArtifact, EventSelector } from '@aztec/foundation/abi'; +import type { AbiDecoded, ContractArtifact } from '@aztec/foundation/abi'; import { type Wallet } from '../account/wallet.js'; import { type ExecutionRequestInit } from '../entrypoint/entrypoint.js'; @@ -152,12 +151,15 @@ export abstract class BaseWallet implements Wallet { args: any[], to: AztecAddress, from?: AztecAddress | undefined, - ): Promise { + ): Promise { return this.pxe.simulateUnconstrained(functionName, args, to, from); } getUnencryptedLogs(filter: LogFilter): Promise { return this.pxe.getUnencryptedLogs(filter); } + getContractClassLogs(filter: LogFilter): Promise { + return this.pxe.getContractClassLogs(filter); + } getBlockNumber(): Promise { return this.pxe.getBlockNumber(); } @@ -170,15 +172,9 @@ export abstract class BaseWallet implements Wallet { isGlobalStateSynchronized() { return this.pxe.isGlobalStateSynchronized(); } - isAccountStateSynchronized(account: AztecAddress) { - return this.pxe.isAccountStateSynchronized(account); - } getSyncStatus(): Promise { return this.pxe.getSyncStatus(); } - getSyncStats(): Promise<{ [key: string]: NoteProcessorStats }> { - return this.pxe.getSyncStats(); - } addAuthWitness(authWitness: AuthWitness) { return this.pxe.addAuthWitness(authWitness); } @@ -197,16 +193,8 @@ export abstract class BaseWallet implements Wallet { getPXEInfo(): Promise { return this.pxe.getPXEInfo(); } - getEvents( - type: EventType, - event: { - /** The event selector */ - eventSelector: EventSelector; - /** The event's abi type */ - abiType: AbiType; - /** The field names */ - fieldNames: string[]; - }, + getEncryptedEvents( + event: EventMetadataDefinition, from: number, limit: number, vpks: Point[] = [ @@ -214,7 +202,10 @@ export abstract class BaseWallet implements Wallet { this.getCompleteAddress().publicKeys.masterOutgoingViewingPublicKey, ], ): Promise { - return this.pxe.getEvents(type, event, from, limit, vpks); + return this.pxe.getEncryptedEvents(event, from, limit, vpks); + } + getUnencryptedEvents(event: EventMetadataDefinition, from: number, limit: number): Promise { + return this.pxe.getUnencryptedEvents(event, from, limit); } public getL1ToL2MembershipWitness( contractAddress: AztecAddress, diff --git a/yarn-project/aztec/src/cli/cli.ts b/yarn-project/aztec/src/cli/cli.ts index 24251b0165e..57650fede28 100644 --- a/yarn-project/aztec/src/cli/cli.ts +++ b/yarn-project/aztec/src/cli/cli.ts @@ -1,11 +1,13 @@ import { deployInitialTestAccounts } from '@aztec/accounts/testing'; -import { createAztecNodeRpcServer } from '@aztec/aztec-node'; -import { type ServerList, createNamespacedJsonRpcServer, createStatusRouter } from '@aztec/foundation/json-rpc/server'; +import { AztecNodeApiSchema, PXESchema } from '@aztec/circuit-types'; +import { + type NamespacedApiHandlers, + createNamespacedSafeJsonRpcServer, + startHttpRpcServer, +} from '@aztec/foundation/json-rpc/server'; import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; -import { createPXERpcServer } from '@aztec/pxe'; import { Command } from 'commander'; -import http from 'http'; import { setupConsoleJsonLog } from '../logging.js'; import { createSandbox } from '../sandbox.js'; @@ -44,7 +46,7 @@ export function injectAztecCommands(program: Command, userLog: LogFn, debugLogge // list of 'stop' functions to call when process ends const signalHandlers: Array<() => Promise> = []; - let services: ServerList = []; + const services: NamespacedApiHandlers = {}; if (options.sandbox) { const sandboxOptions = extractNamespacedOptions(options, 'sandbox'); @@ -69,38 +71,37 @@ export function injectAztecCommands(program: Command, userLog: LogFn, debugLogge } // Start Node and PXE JSON-RPC server - const nodeServer = createAztecNodeRpcServer(node); - const pxeServer = createPXERpcServer(pxe); signalHandlers.push(stop); - services = [{ node: nodeServer }, { pxe: pxeServer }]; + services.node = [node, AztecNodeApiSchema]; + services.pxe = [pxe, PXESchema]; } else { if (options.node) { const { startNode } = await import('./cmds/start_node.js'); - services = await startNode(options, signalHandlers, userLog); + await startNode(options, signalHandlers, services, userLog); } else if (options.proofVerifier) { const { startProofVerifier } = await import('./cmds/start_proof_verifier.js'); - services = await startProofVerifier(options, signalHandlers, userLog); + await startProofVerifier(options, signalHandlers, userLog); } else if (options.bot) { const { startBot } = await import('./cmds/start_bot.js'); - services = await startBot(options, signalHandlers, userLog); + await startBot(options, signalHandlers, services, userLog); } else if (options.proverNode) { const { startProverNode } = await import('./cmds/start_prover_node.js'); - services = await startProverNode(options, signalHandlers, userLog); + await startProverNode(options, signalHandlers, services, userLog); } else if (options.pxe) { const { startPXE } = await import('./cmds/start_pxe.js'); - services = await startPXE(options, signalHandlers, userLog); + await startPXE(options, signalHandlers, services, userLog); } else if (options.archiver) { const { startArchiver } = await import('./cmds/start_archiver.js'); - services = await startArchiver(options, signalHandlers); + await startArchiver(options, signalHandlers, services); } else if (options.p2pBootstrap) { const { startP2PBootstrap } = await import('./cmds/start_p2p_bootstrap.js'); await startP2PBootstrap(options, userLog, debugLogger); } else if (options.prover) { const { startProverAgent } = await import('./cmds/start_prover_agent.js'); - services = await startProverAgent(options, signalHandlers, userLog); + await startProverAgent(options, signalHandlers, services, userLog); } else if (options.txe) { const { startTXE } = await import('./cmds/start_txe.js'); - startTXE(options, debugLogger); + await startTXE(options, debugLogger); } else if (options.sequencer) { userLog(`Cannot run a standalone sequencer without a node`); process.exit(1); @@ -112,17 +113,10 @@ export function injectAztecCommands(program: Command, userLog: LogFn, debugLogge installSignalHandlers(debugLogger.info, signalHandlers); - if (services.length) { - const rpcServer = createNamespacedJsonRpcServer(services, debugLogger); - - const app = rpcServer.getApp(options.apiPrefix); - // add status route - const statusRouter = createStatusRouter(() => rpcServer.isHealthy(), options.apiPrefix); - app.use(statusRouter.routes()).use(statusRouter.allowedMethods()); - - const httpServer = http.createServer(app.callback()); - httpServer.listen(options.port); - debugLogger.info(`Aztec Server listening on port ${options.port}`); + if (Object.entries(services).length > 0) { + const rpcServer = createNamespacedSafeJsonRpcServer(services, debugLogger); + const { port } = await startHttpRpcServer(rpcServer, { port: options.port }); + debugLogger.info(`Aztec Server listening on port ${port}`); } }); diff --git a/yarn-project/aztec/src/cli/cmds/start_archiver.ts b/yarn-project/aztec/src/cli/cmds/start_archiver.ts index d9e0c092aa7..cdee55cc214 100644 --- a/yarn-project/aztec/src/cli/cmds/start_archiver.ts +++ b/yarn-project/aztec/src/cli/cmds/start_archiver.ts @@ -1,12 +1,7 @@ -import { - Archiver, - type ArchiverConfig, - KVArchiverDataStore, - archiverConfigMappings, - createArchiverRpcServer, -} from '@aztec/archiver'; +import { Archiver, type ArchiverConfig, KVArchiverDataStore, archiverConfigMappings } from '@aztec/archiver'; import { createDebugLogger } from '@aztec/aztec.js'; -import { type ServerList } from '@aztec/foundation/json-rpc/server'; +import { ArchiverApiSchema } from '@aztec/circuit-types'; +import { type NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server'; import { createStore } from '@aztec/kv-store/utils'; import { createAndStartTelemetryClient, @@ -15,9 +10,12 @@ import { import { extractRelevantOptions } from '../util.js'; -export const startArchiver = async (options: any, signalHandlers: (() => Promise)[]) => { - const services: ServerList = []; - // Start a standalone archiver. +/** Starts a standalone archiver. */ +export async function startArchiver( + options: any, + signalHandlers: (() => Promise)[], + services: NamespacedApiHandlers, +) { const archiverConfig = extractRelevantOptions(options, archiverConfigMappings, 'archiver'); const storeLog = createDebugLogger('aztec:archiver:lmdb'); @@ -26,8 +24,7 @@ export const startArchiver = async (options: any, signalHandlers: (() => Promise const telemetry = await createAndStartTelemetryClient(getTelemetryClientConfig()); const archiver = await Archiver.createAndSync(archiverConfig, archiverStore, telemetry, true); - const archiverServer = createArchiverRpcServer(archiver); - services.push({ archiver: archiverServer }); + services.archiver = [archiver, ArchiverApiSchema]; signalHandlers.push(archiver.stop); return services; -}; +} diff --git a/yarn-project/aztec/src/cli/cmds/start_bot.ts b/yarn-project/aztec/src/cli/cmds/start_bot.ts index cf61ed0aa95..1d3e110db33 100644 --- a/yarn-project/aztec/src/cli/cmds/start_bot.ts +++ b/yarn-project/aztec/src/cli/cmds/start_bot.ts @@ -1,6 +1,6 @@ -import { type BotConfig, BotRunner, botConfigMappings, createBotRunnerRpcServer } from '@aztec/bot'; +import { type BotConfig, BotRunner, botConfigMappings, getBotRunnerApiHandler } from '@aztec/bot'; import { type AztecNode, type PXE } from '@aztec/circuit-types'; -import { type ServerList } from '@aztec/foundation/json-rpc/server'; +import { type NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server'; import { type LogFn } from '@aztec/foundation/log'; import { extractRelevantOptions } from '../util.js'; @@ -8,11 +8,9 @@ import { extractRelevantOptions } from '../util.js'; export async function startBot( options: any, signalHandlers: (() => Promise)[], + services: NamespacedApiHandlers, userLog: LogFn, -): Promise { - // Services that will be started in a single multi-rpc server - const services: ServerList = []; - +) { const { proverNode, archiver, sequencer, p2pBootstrap, txe, prover } = options; if (proverNode || archiver || sequencer || p2pBootstrap || txe || prover) { userLog( @@ -24,27 +22,25 @@ export async function startBot( let pxe: PXE | undefined; if (options.pxe) { const { addPXE } = await import('./start_pxe.js'); - pxe = await addPXE(options, services, signalHandlers, userLog); + pxe = await addPXE(options, signalHandlers, services, userLog); } - await addBot(options, services, signalHandlers, { pxe }); - return services; + await addBot(options, signalHandlers, services, { pxe }); } export function addBot( options: any, - services: ServerList, signalHandlers: (() => Promise)[], + services: NamespacedApiHandlers, deps: { pxe?: PXE; node?: AztecNode } = {}, ) { const config = extractRelevantOptions(options, botConfigMappings, 'bot'); const botRunner = new BotRunner(config, deps); - const botServer = createBotRunnerRpcServer(botRunner); if (!config.noStart) { void botRunner.start(); // Do not block since bot setup takes time } - services.push({ bot: botServer }); + services.bot = getBotRunnerApiHandler(botRunner); signalHandlers.push(botRunner.stop); return Promise.resolve(); } diff --git a/yarn-project/aztec/src/cli/cmds/start_node.ts b/yarn-project/aztec/src/cli/cmds/start_node.ts index ad0cb056257..939776c345b 100644 --- a/yarn-project/aztec/src/cli/cmds/start_node.ts +++ b/yarn-project/aztec/src/cli/cmds/start_node.ts @@ -1,7 +1,7 @@ -import { aztecNodeConfigMappings, createAztecNodeRpcServer } from '@aztec/aztec-node'; -import { type PXE } from '@aztec/circuit-types'; +import { aztecNodeConfigMappings } from '@aztec/aztec-node'; +import { AztecNodeApiSchema, type PXE } from '@aztec/circuit-types'; import { NULL_KEY } from '@aztec/ethereum'; -import { type ServerList } from '@aztec/foundation/json-rpc/server'; +import { type NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server'; import { type LogFn } from '@aztec/foundation/log'; import { type TelemetryClientConfig, @@ -14,14 +14,12 @@ import { mnemonicToAccount, privateKeyToAccount } from 'viem/accounts'; import { createAztecNode, deployContractsToL1 } from '../../sandbox.js'; import { extractNamespacedOptions, extractRelevantOptions } from '../util.js'; -export const startNode = async ( +export async function startNode( options: any, signalHandlers: (() => Promise)[], + services: NamespacedApiHandlers, userLog: LogFn, -): Promise => { - // Services that will be started in a single multi-rpc server - const services: ServerList = []; - +) { // options specifically namespaced with --node.