From cc420a081e23558b9441cbf563625002e1d45f18 Mon Sep 17 00:00:00 2001 From: Ilyas Ridhuan Date: Tue, 30 Jul 2024 11:42:28 +0100 Subject: [PATCH 01/35] feat(avm): pedersen commitment sim (#7632) Please read [contributing guidelines](CONTRIBUTING.md) and remove this line. --- avm-transpiler/src/opcodes.rs | 2 + avm-transpiler/src/transpile.rs | 18 ++++ .../vm/avm_trace/avm_deserialization.cpp | 3 +- .../barretenberg/vm/avm_trace/avm_opcode.hpp | 1 + .../contracts/avm_test_contract/src/main.nr | 8 +- yarn-project/simulator/src/avm/avm_gas.ts | 1 + .../simulator/src/avm/avm_simulator.test.ts | 18 +++- .../src/avm/opcodes/commitment.test.ts | 93 +++++++++++++++++++ .../simulator/src/avm/opcodes/commitment.ts | 66 +++++++++++++ .../serialization/bytecode_serialization.ts | 2 + .../instruction_serialization.ts | 1 + 11 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 yarn-project/simulator/src/avm/opcodes/commitment.test.ts create mode 100644 yarn-project/simulator/src/avm/opcodes/commitment.ts diff --git a/avm-transpiler/src/opcodes.rs b/avm-transpiler/src/opcodes.rs index fc177793494..23b67dc18f9 100644 --- a/avm-transpiler/src/opcodes.rs +++ b/avm-transpiler/src/opcodes.rs @@ -74,6 +74,7 @@ pub enum AvmOpcode { PEDERSEN, // temp - may be removed, but alot of contracts rely on it ECADD, MSM, + PEDERSENCOMMITMENT, // temp // Conversions TORADIXLE, // Other @@ -170,6 +171,7 @@ impl AvmOpcode { AvmOpcode::PEDERSEN => "PEDERSEN", AvmOpcode::ECADD => "ECADD", AvmOpcode::MSM => "MSM", + AvmOpcode::PEDERSENCOMMITMENT => "PEDERSENCOMMITMENT", // Conversions AvmOpcode::TORADIXLE => "TORADIXLE", // Other diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index a6d09a975fa..4109a453355 100644 --- a/avm-transpiler/src/transpile.rs +++ b/avm-transpiler/src/transpile.rs @@ -888,6 +888,24 @@ fn handle_black_box_function(avm_instrs: &mut Vec, operation: &B ..Default::default() }); } + // Temporary while we dont have efficient noir implementations (again) + BlackBoxOp::PedersenCommitment { inputs, domain_separator, output } => { + let input_offset = inputs.pointer.0; + let input_size_offset = inputs.size.0; + let index_offset = domain_separator.0; + let output_offset = output.pointer.0; + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::PEDERSENCOMMITMENT, + indirect: Some(ZEROTH_OPERAND_INDIRECT | FIRST_OPERAND_INDIRECT), + operands: vec![ + AvmOperand::U32 { value: input_offset as u32 }, + AvmOperand::U32 { value: output_offset as u32 }, + AvmOperand::U32 { value: input_size_offset as u32 }, + AvmOperand::U32 { value: index_offset as u32 }, + ], + ..Default::default() + }); + } _ => panic!("Transpiler doesn't know how to process {:?}", operation), } } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp index 1663491d3ab..a2d596c12b7 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp @@ -166,10 +166,11 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = OperandType::UINT32 } }, // dst_offset { OpCode::MSM, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, + { OpCode::PEDERSENCOMMITMENT, + { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, // Gadget - Conversion { OpCode::TORADIXLE, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, - // Gadgets - Unused for now { OpCode::SHA256COMPRESSION, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp index f2beb29d32f..c70213f355d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp @@ -106,6 +106,7 @@ enum class OpCode : uint8_t { PEDERSEN, ECADD, MSM, + PEDERSENCOMMITMENT, // Conversions TORADIXLE, // Future Gadgets -- pending changes in noir 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 5bebeadf78d..4c6838558a1 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 @@ -24,7 +24,7 @@ contract AvmTest { global big_field_136_bits: Field = 0x991234567890abcdef1234567890abcdef; // Libs - use std::embedded_curve_ops::multi_scalar_mul; + use std::embedded_curve_ops::{multi_scalar_mul, EmbeddedCurvePoint}; use dep::aztec::protocol_types::constants::CONTRACT_INSTANCE_LENGTH; use dep::aztec::prelude::{Map, Deserialize}; use dep::aztec::state_vars::PublicMutable; @@ -153,6 +153,12 @@ contract AvmTest { triple_g } + #[aztec(public)] + fn pedersen_commit(x: Field, y: Field) -> EmbeddedCurvePoint { + let commitment = dep::std::hash::pedersen_commitment([x, y]); + commitment + } + /************************************************************************ * Misc ************************************************************************/ diff --git a/yarn-project/simulator/src/avm/avm_gas.ts b/yarn-project/simulator/src/avm/avm_gas.ts index 34ee3b492c5..bdb8ef86097 100644 --- a/yarn-project/simulator/src/avm/avm_gas.ts +++ b/yarn-project/simulator/src/avm/avm_gas.ts @@ -124,6 +124,7 @@ const BaseGasCosts: Record = { [Opcode.PEDERSEN]: DefaultBaseGasCost, [Opcode.ECADD]: DefaultBaseGasCost, [Opcode.MSM]: DefaultBaseGasCost, + [Opcode.PEDERSENCOMMITMENT]: DefaultBaseGasCost, // Conversions [Opcode.TORADIXLE]: DefaultBaseGasCost, // Other diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 83d4f95939b..54b42fa3f80 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -3,7 +3,7 @@ import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { computeVarArgsHash } from '@aztec/circuits.js/hash'; import { FunctionSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { keccak256, keccakf1600, pedersenHash, poseidon2Hash, sha256 } from '@aztec/foundation/crypto'; +import { keccak256, keccakf1600, pedersenCommit, pedersenHash, poseidon2Hash, sha256 } from '@aztec/foundation/crypto'; import { Fq, Fr } from '@aztec/foundation/fields'; import { type Fieldable } from '@aztec/foundation/serialize'; @@ -140,6 +140,22 @@ describe('AVM simulator: transpiled Noir contracts', () => { expect(results.output).toEqual([expectedResult.x, expectedResult.y, Fr.ZERO]); }); + it('pedersen commitment operations', async () => { + const calldata: Fr[] = [new Fr(100), new Fr(1)]; + const context = initContext({ env: initExecutionEnvironment({ calldata }) }); + + const bytecode = getAvmTestContractBytecode('pedersen_commit'); + const results = await new AvmSimulator(context).executeBytecode(bytecode); + + expect(results.reverted).toBe(false); + // This doesnt include infinites + const expectedResult = pedersenCommit([Buffer.from([100]), Buffer.from([1])]).map(f => new Fr(f)); + // TODO: Come back to the handling of infinities when we confirm how they're handled in bb + const isInf = expectedResult[0] === new Fr(0) && expectedResult[1] === new Fr(0); + expectedResult.push(new Fr(isInf)); + expect(results.output).toEqual(expectedResult); + }); + describe('U128 addition and overflows', () => { it('U128 addition', async () => { const calldata: Fr[] = [ diff --git a/yarn-project/simulator/src/avm/opcodes/commitment.test.ts b/yarn-project/simulator/src/avm/opcodes/commitment.test.ts new file mode 100644 index 00000000000..c5b7c509334 --- /dev/null +++ b/yarn-project/simulator/src/avm/opcodes/commitment.test.ts @@ -0,0 +1,93 @@ +import { pedersenCommit } from '@aztec/foundation/crypto'; + +import { type AvmContext } from '../avm_context.js'; +import { Field, Uint32 } from '../avm_memory_types.js'; +import { initContext, randomMemoryFields } from '../fixtures/index.js'; +import { Addressing, AddressingMode } from './addressing_mode.js'; +import { PedersenCommitment } from './commitment.js'; + +describe('Commitment Opcode', () => { + let context: AvmContext; + + beforeEach(async () => { + context = initContext(); + }); + + describe('Pedersen Commitment', () => { + it('Should (de)serialize correctly', () => { + const buf = Buffer.from([ + PedersenCommitment.opcode, // opcode + 1, // indirect + ...Buffer.from('23456789', 'hex'), // inputOffset + ...Buffer.from('3456789a', 'hex'), // inputSizeOffset + ...Buffer.from('12345678', 'hex'), // outputOffset + ...Buffer.from('00000000', 'hex'), // genIndexOffset + ]); + const inst = new PedersenCommitment( + /*indirect=*/ 1, + /*inputOffset=*/ 0x23456789, + /*inputSizeOffset=*/ 0x3456789a, + /*outputOffset=*/ 0x12345678, + /*genIndexOffset=*/ 0, + ); + + expect(PedersenCommitment.deserialize(buf)).toEqual(inst); + expect(inst.serialize()).toEqual(buf); + }); + + it('Should commit correctly - direct', async () => { + const args = randomMemoryFields(10); + const inputOffset = 0; + const inputSizeOffset = 20; + const outputOffset = 50; + const indirect = 0; + const generatorIndexOffset = 10; + + context.machineState.memory.setSlice(inputOffset, args); + context.machineState.memory.set(inputSizeOffset, new Uint32(args.length)); + context.machineState.memory.set(generatorIndexOffset, new Uint32(0)); + + const expectedCommitment = pedersenCommit(args.map(f => f.toBuffer())).map(f => new Field(f)); + await new PedersenCommitment(indirect, inputOffset, outputOffset, inputSizeOffset, generatorIndexOffset).execute( + context, + ); + + const result = context.machineState.memory.getSlice(outputOffset, 2); + expect(result).toEqual(expectedCommitment); + // Check Inf + expect(0).toEqual(context.machineState.memory.get(outputOffset + 2).toNumber()); + }); + + it('Should commit correctly - indirect', async () => { + const args = randomMemoryFields(10); + const indirect = new Addressing([ + /*inputOffset=*/ AddressingMode.INDIRECT, + /*outputOffset*/ AddressingMode.INDIRECT, + /*inputSizeOffset=*/ AddressingMode.DIRECT, + /*generatorIndexOffset=*/ AddressingMode.DIRECT, + ]).toWire(); + const inputOffset = 0; + const inputSizeOffset = 20; + const outputOffset = 50; + const realOutputOffset = 100; + const realInputOffset = 200; + const generatorIndexOffset = 51; + + context.machineState.memory.set(outputOffset, new Uint32(realOutputOffset)); + context.machineState.memory.set(inputOffset, new Uint32(realInputOffset)); + context.machineState.memory.setSlice(realInputOffset, args); + context.machineState.memory.set(inputSizeOffset, new Uint32(args.length)); + context.machineState.memory.set(generatorIndexOffset, new Uint32(0)); + + const expectedCommitment = pedersenCommit(args.map(f => f.toBuffer())).map(f => new Field(f)); + await new PedersenCommitment(indirect, inputOffset, outputOffset, inputSizeOffset, generatorIndexOffset).execute( + context, + ); + + const result = context.machineState.memory.getSlice(realOutputOffset, 2); + expect(result).toEqual(expectedCommitment); + // Check Inf + expect(0).toEqual(context.machineState.memory.get(realOutputOffset + 2).toNumber()); + }); + }); +}); diff --git a/yarn-project/simulator/src/avm/opcodes/commitment.ts b/yarn-project/simulator/src/avm/opcodes/commitment.ts new file mode 100644 index 00000000000..ad99064a6d9 --- /dev/null +++ b/yarn-project/simulator/src/avm/opcodes/commitment.ts @@ -0,0 +1,66 @@ +import { pedersenCommit } from '@aztec/foundation/crypto'; + +import { type AvmContext } from '../avm_context.js'; +import { Field, TypeTag, Uint8 } from '../avm_memory_types.js'; +import { Opcode, OperandType } from '../serialization/instruction_serialization.js'; +import { Addressing } from './addressing_mode.js'; +import { Instruction } from './instruction.js'; + +export class PedersenCommitment extends Instruction { + static type: string = 'PEDERSENCOMMITMENT'; + static readonly opcode: Opcode = Opcode.PEDERSENCOMMITMENT; + + // Informs (de)serialization. See Instruction.deserialize. + static readonly wireFormat: OperandType[] = [ + OperandType.UINT8 /* Opcode */, + OperandType.UINT8 /* Indirect */, + OperandType.UINT32 /* Input Offset*/, + OperandType.UINT32 /* Dst Offset */, + OperandType.UINT32 /* Input Size Offset */, + OperandType.UINT32 /* Generator Index Offset */, + ]; + + constructor( + private indirect: number, + private inputOffset: number, + private outputOffset: number, + private inputSizeOffset: number, + private genIndexOffset: number, + ) { + super(); + } + + public async execute(context: AvmContext): Promise { + const memory = context.machineState.memory.track(this.type); + const [inputOffset, outputOffset, inputSizeOffset, genIndexOffset] = Addressing.fromWire(this.indirect).resolve( + [this.inputOffset, this.outputOffset, this.inputSizeOffset, this.genIndexOffset], + memory, + ); + + const inputSize = memory.get(inputSizeOffset).toNumber(); + memory.checkTag(TypeTag.UINT32, inputSizeOffset); + + const inputs = memory.getSlice(inputOffset, inputSize); + memory.checkTagsRange(TypeTag.FIELD, inputOffset, inputSize); + + // Generator index not used for now since we dont utilise it in the pedersenCommit function + memory.checkTag(TypeTag.UINT32, genIndexOffset); + + const memoryOperations = { reads: inputSize + 1, writes: 3, indirect: this.indirect }; + context.machineState.consumeGas(this.gasCost(memoryOperations)); + + const inputBuffer: Buffer[] = inputs.map(input => input.toBuffer()); + // TODO: Add the generate index to the pedersenCommit function + const commitment = pedersenCommit(inputBuffer).map(f => new Field(f)); + // The function doesnt include a flag if the output point is infinity, come back to this + // for now we just check if theyre zero - until we know how bb encodes them + const isInfinity = commitment[0].equals(new Field(0)) && commitment[1].equals(new Field(0)); + + memory.set(outputOffset, commitment[0]); // Field typed + memory.set(outputOffset + 1, commitment[1]); // Field typed + memory.set(outputOffset + 2, new Uint8(isInfinity ? 1 : 0)); // U8 typed + + memory.assert(memoryOperations); + context.machineState.incrementPc(); + } +} diff --git a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts index 03a0d01f0c9..46811568427 100644 --- a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts +++ b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts @@ -1,3 +1,4 @@ +import { PedersenCommitment } from '../opcodes/commitment.js'; import { DAGasLeft, L2GasLeft } from '../opcodes/context_getters.js'; import { EcAdd } from '../opcodes/ec_add.js'; import { Keccak, KeccakF1600, Pedersen, Poseidon2, Sha256 } from '../opcodes/hashing.js'; @@ -146,6 +147,7 @@ const INSTRUCTION_SET = () => [Sha256.opcode, Sha256], [Pedersen.opcode, Pedersen], [MultiScalarMul.opcode, MultiScalarMul], + [PedersenCommitment.opcode, PedersenCommitment], // Conversions [ToRadixLE.opcode, ToRadixLE], // Future Gadgets -- pending changes in noir diff --git a/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts b/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts index c449f49cd8b..013c35ce369 100644 --- a/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts +++ b/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts @@ -78,6 +78,7 @@ export enum Opcode { PEDERSEN, // temp - may be removed, but alot of contracts rely on it ECADD, MSM, + PEDERSENCOMMITMENT, // Conversion TORADIXLE, // Future Gadgets -- pending changes in noir From 45e7867f4b42a3392b4b95767621284ebc7378fe Mon Sep 17 00:00:00 2001 From: Ilyas Ridhuan Date: Tue, 30 Jul 2024 11:42:43 +0100 Subject: [PATCH 02/35] feat(avm): pedersen commit in avm (#7634) Please read [contributing guidelines](CONTRIBUTING.md) and remove this line. --- .../vm/avm_trace/avm_execution.cpp | 8 ++ .../barretenberg/vm/avm_trace/avm_trace.cpp | 92 +++++++++++++++++++ .../barretenberg/vm/avm_trace/avm_trace.hpp | 5 + .../vm/tests/avm_execution.test.cpp | 65 ++++++++++++- .../bb-prover/src/avm_proving.test.ts | 10 +- 5 files changed, 176 insertions(+), 4 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp index 81aefd53187..5e81e6d38a9 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -797,6 +797,14 @@ std::vector Execution::gen_trace(std::vector const& instructio std::get(inst.operands.at(2)), std::get(inst.operands.at(3))); + break; + case OpCode::PEDERSENCOMMITMENT: + trace_builder.op_pedersen_commit(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; default: throw_or_abort("Don't know how to execute opcode " + to_hex(inst.op_code) + " at pc " + std::to_string(pc) + diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp index 5c970222340..620d264c7c7 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -14,6 +14,7 @@ #include #include "barretenberg/common/throw_or_abort.hpp" +#include "barretenberg/crypto/pedersen_commitment/pedersen.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" #include "barretenberg/numeric/uint256/uint256.hpp" #include "barretenberg/polynomials/univariate.hpp" @@ -3430,6 +3431,97 @@ void AvmTraceBuilder::op_variable_msm(uint8_t indirect, pc++; } +void AvmTraceBuilder::op_pedersen_commit(uint8_t indirect, + uint32_t input_offset, + uint32_t output_offset, + uint32_t input_size_offset, + uint32_t gen_ctx_offset) +{ + auto clk = static_cast(main_trace.size()) + 1; + auto [resolved_input_offset, resolved_output_offset, resolved_input_size_offset, resolved_gen_ctx_offset] = + unpack_indirects<4>(indirect, { input_offset, output_offset, input_size_offset, gen_ctx_offset }); + + auto input_length_read = constrained_read_from_memory( + call_ptr, clk, resolved_input_size_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IA); + auto gen_ctx_read = constrained_read_from_memory( + call_ptr, clk, resolved_gen_ctx_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IB); + + main_trace.push_back(Row{ + .main_clk = clk, + .main_ia = input_length_read.val, + .main_ib = gen_ctx_read.val, + .main_ind_addr_a = FF(input_length_read.indirect_address), + .main_ind_addr_b = FF(gen_ctx_read.indirect_address), + .main_internal_return_ptr = FF(internal_return_ptr), + .main_mem_addr_a = FF(input_length_read.direct_address), + .main_mem_addr_b = FF(gen_ctx_read.direct_address), + .main_pc = FF(pc), + .main_r_in_tag = FF(static_cast(AvmMemoryTag::U32)), + .main_sel_mem_op_a = FF(1), + .main_sel_mem_op_b = FF(1), + .main_sel_resolve_ind_addr_a = FF(static_cast(input_length_read.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(gen_ctx_read.is_indirect)), + }); + clk++; + + std::vector inputs; + auto num_rows = read_slice_to_memory(call_ptr, + clk, + resolved_input_offset, + AvmMemoryTag::FF, + AvmMemoryTag::U0, + FF(internal_return_ptr), + uint32_t(input_length_read.val), + inputs); + clk += num_rows; + + grumpkin::g1::affine_element result = + crypto::pedersen_commitment::commit_native(inputs, uint32_t(gen_ctx_read.val)); + + auto write_x = constrained_write_to_memory( + call_ptr, clk, resolved_output_offset, result.x, AvmMemoryTag::U0, AvmMemoryTag::FF, IntermRegister::IA); + + mem_trace_builder.write_into_memory( + call_ptr, clk, IntermRegister::IB, write_x.direct_address + 1, result.y, AvmMemoryTag::U0, AvmMemoryTag::FF); + + main_trace.push_back(Row{ + .main_clk = clk, + .main_ia = result.x, + .main_ib = result.y, + .main_ind_addr_a = FF(write_x.indirect_address), + .main_internal_return_ptr = FF(internal_return_ptr), + .main_mem_addr_a = FF(write_x.direct_address), + .main_mem_addr_b = FF(write_x.direct_address + 1), + .main_pc = FF(pc), + .main_rwa = FF(1), + .main_rwb = FF(1), + .main_sel_mem_op_a = FF(1), + .main_sel_mem_op_b = FF(1), + .main_sel_resolve_ind_addr_a = FF(static_cast(write_x.is_indirect)), + .main_w_in_tag = FF(static_cast(AvmMemoryTag::FF)), + }); + + clk++; + mem_trace_builder.write_into_memory(call_ptr, + clk, + IntermRegister::IA, + write_x.direct_address + 2, + result.is_point_at_infinity(), + AvmMemoryTag::U0, + AvmMemoryTag::U8); + main_trace.push_back(Row{ + .main_clk = clk, + .main_ia = static_cast(result.is_point_at_infinity()), + .main_internal_return_ptr = FF(internal_return_ptr), + .main_mem_addr_a = FF(write_x.direct_address + 2), + .main_pc = FF(pc), + .main_rwa = FF(1), + .main_sel_mem_op_a = FF(1), + .main_w_in_tag = FF(static_cast(AvmMemoryTag::U8)), + }); + pc++; +} + /************************************************************************************************** * CONVERSIONS **************************************************************************************************/ diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp index 5ec74970703..06ec1227bdf 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -152,6 +152,11 @@ class AvmTraceBuilder { uint32_t scalars_offset, uint32_t output_offset, uint32_t point_length_offset); + void op_pedersen_commit(uint8_t indirect, + uint32_t output_offset, + uint32_t input_offset, + uint32_t input_size_offset, + uint32_t gen_ctx_offset); // Conversions void op_to_radix_le(uint8_t indirect, uint32_t src_offset, uint32_t dst_offset, uint32_t radix, uint32_t num_limbs); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp index be6f99c52f9..59e627ca707 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -1261,7 +1261,7 @@ 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::CALLDATACOPY) + // Calldatacopy...should fix the limit on calldatacopy + std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // Calldatacopy "00" // Indirect flag "00000000" // cd_offset 0 "0000000a" // copy_size (10 elements) @@ -1319,6 +1319,69 @@ TEST_F(AvmExecutionTests, msmOpCode) validate_trace(std::move(trace), public_inputs, calldata, returndata); } +// Positive test with pedersen commitment +TEST_F(AvmExecutionTests, pedersenCommitmentOpcode) +{ + auto expected_result = + grumpkin::g1::affine_element(fr(uint256_t("054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402")), + fr(uint256_t("209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126"))); + // grumpkin::g1::affine_eleelement; + // grumpkin::g1::affine_element b = grumpkin::g1::affine_element::one(); + + // Remmeber that grumpkin Fq == BN254 Fr => aka FF + grumpkin::g1::Fq scalar_a = grumpkin::g1::Fq::zero(); + grumpkin::g1::Fq scalar_b = grumpkin::g1::Fq::one(); + std::vector expected_output = { expected_result.x, expected_result.y, expected_result.is_point_at_infinity() }; + // Send all the input as Fields and cast them to U8 later + std::vector calldata = { scalar_a, scalar_b }; + std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // Calldatacopy + "00" // Indirect flag + "00000000" // cd_offset 0 + "00000002" // copy_size (2 elements) + "00000000" // dst_offset 0 + + to_hex(OpCode::SET) + // opcode SET for indirect input + "00" // Indirect flag + "03" // U32 + "00000000" // Input stored at memory 0 + "0000000b" // dst offset (11) + + to_hex(OpCode::SET) + // opcode SET for indirect output + "00" // Indirect flag + "03" // U32 + "00000020" // output offset + "0000000d" // dst offset + + to_hex(OpCode::SET) + // opcode SET for input length + "00" // Indirect flag + "03" // U32 + "00000002" // scalars length (2) + "00000002" + // dst offset (2) + to_hex(OpCode::SET) + // opcode SET for ctx index + "00" // Indirect flag + "03" // U32 + "00000000" // ctx index (0) + "0000000f" + // dst offset + to_hex(OpCode::PEDERSENCOMMITMENT) + // opcode MSM + "03" // Indirect flag (first 2 indirect) + "0000000b" // inputs offset + "0000000d" // outputs offset + "00000002" // inputs length offset + "0000000f" // gen ctx index offset + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000020" // ret offset + "00000003"; // ret size 3 + + auto bytecode = hex_to_bytes(bytecode_hex); + auto instructions = Deserialization::parse(bytecode); + + // Assign a vector that we will mutate internally in gen_trace to store the return values; + std::vector returndata; + auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec); + + EXPECT_EQ(returndata, expected_output); + + validate_trace(std::move(trace), public_inputs, calldata, returndata); +} + // Positive test for Kernel Input opcodes TEST_F(AvmExecutionTests, kernelInputOpcodes) { diff --git a/yarn-project/bb-prover/src/avm_proving.test.ts b/yarn-project/bb-prover/src/avm_proving.test.ts index f769425ad68..4cf5b70dded 100644 --- a/yarn-project/bb-prover/src/avm_proving.test.ts +++ b/yarn-project/bb-prover/src/avm_proving.test.ts @@ -149,11 +149,15 @@ describe('AVM WitGen, proof generation and verification', () => { * Avm Embedded Curve functions ************************************************************************/ describe('AVM Embedded Curve functions', () => { - const avmEmbeddedCurveFunctions: string[] = ['elliptic_curve_add_and_double', 'variable_base_msm']; + const avmEmbeddedCurveFunctions: [string, Fr[]][] = [ + ['elliptic_curve_add_and_double', []], + ['variable_base_msm', []], + ['pedersen_commit', [new Fr(1), new Fr(100)]], + ]; it.each(avmEmbeddedCurveFunctions)( 'Should prove %s', - async name => { - await proveAndVerifyAvmTestContract(name); + async (name, calldata) => { + await proveAndVerifyAvmTestContract(name, calldata); }, TIMEOUT, ); From f35bac5d35d22e269d8bf2ffccc4484a715d70ae Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Tue, 30 Jul 2024 07:44:23 -0300 Subject: [PATCH 03/35] feat: Handle L1toL2 msgs in prover-node (#7654) Prover node was not collecting l1 to l2 messages for proofs. This PR adds a call to the archiver to retrieve them for the block being proven, and extends the e2e_prover_node test to include a tx with a msg. --- .../composed/integration_l1_publisher.test.ts | 44 ++---------- .../end-to-end/src/e2e_prover_node.test.ts | 71 ++++++++++++++----- .../l1_to_l2.test.ts | 41 +---------- ...lic_cross_chain_messaging_contract_test.ts | 1 + .../src/fixtures/l1_to_l2_messaging.ts | 58 +++++++++++++++ .../src/shared/cross_chain_test_harness.ts | 5 ++ yarn-project/prover-node/src/factory.ts | 2 +- .../prover-node/src/job/block-proving-job.ts | 9 ++- yarn-project/prover-node/src/prover-node.ts | 4 +- 9 files changed, 137 insertions(+), 98 deletions(-) create mode 100644 yarn-project/end-to-end/src/fixtures/l1_to_l2_messaging.ts diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index a71ff1b65ba..2d6127b601d 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -1,15 +1,6 @@ import { type ArchiveSource } from '@aztec/archiver'; import { getConfigEnvVars } from '@aztec/aztec-node'; -import { - AztecAddress, - Body, - Fr, - GlobalVariables, - L2Actor, - type L2Block, - createDebugLogger, - mockTx, -} from '@aztec/aztec.js'; +import { AztecAddress, Body, Fr, GlobalVariables, type L2Block, createDebugLogger, mockTx } from '@aztec/aztec.js'; // eslint-disable-next-line no-restricted-imports import { PROVING_STATUS, @@ -60,6 +51,7 @@ import { } from 'viem'; import { type PrivateKeyAccount, privateKeyToAccount } from 'viem/accounts'; +import { sendL1ToL2Message } from '../fixtures/l1_to_l2_messaging.js'; import { setupL1Contracts } from '../fixtures/utils.js'; // Accounts 4 and 5 of Anvil default startup with mnemonic: 'test test test test test test test test test test test junk' @@ -188,35 +180,11 @@ describe('L1Publisher integration', () => { return processedTx; }; - const sendToL2 = async (content: Fr, recipientAddress: AztecAddress): Promise => { - // @todo @LHerskind version hardcoded here (update to bigint or field) - const recipient = new L2Actor(recipientAddress, 1); - // getting the 32 byte hex string representation of the content - const contentString = content.toString(); - // Using the 0 value for the secretHash. - const emptySecretHash = Fr.ZERO.toString(); - - const txHash = await inbox.write.sendL2Message( - [{ actor: recipient.recipient.toString(), version: BigInt(recipient.version) }, contentString, emptySecretHash], - {} as any, + const sendToL2 = (content: Fr, recipient: AztecAddress): Promise => { + return sendL1ToL2Message( + { content, secretHash: Fr.ZERO, recipient }, + { publicClient, walletClient, l1ContractAddresses }, ); - - const txReceipt = await publicClient.waitForTransactionReceipt({ - hash: txHash, - }); - - // Exactly 1 event should be emitted in the transaction - expect(txReceipt.logs.length).toBe(1); - - // We decode the event log before checking it - const txLog = txReceipt.logs[0]; - const topics = decodeEventLog({ - abi: InboxAbi, - data: txLog.data, - topics: txLog.topics, - }); - - return Fr.fromString(topics.args.hash); }; /** diff --git a/yarn-project/end-to-end/src/e2e_prover_node.test.ts b/yarn-project/end-to-end/src/e2e_prover_node.test.ts index af0bf72045a..e2e5f6941c7 100644 --- a/yarn-project/end-to-end/src/e2e_prover_node.test.ts +++ b/yarn-project/end-to-end/src/e2e_prover_node.test.ts @@ -4,16 +4,21 @@ import { type AccountWalletWithSecretKey, type AztecAddress, type DebugLogger, + EthAddress, type FieldsOf, + Fr, + SignerlessWallet, type TxReceipt, + computeSecretHash, createDebugLogger, retryUntil, sleep, } from '@aztec/aztec.js'; -import { StatefulTestContract } from '@aztec/noir-contracts.js'; -import { createProverNode } from '@aztec/prover-node'; +import { StatefulTestContract, TestContract } from '@aztec/noir-contracts.js'; +import { type ProverNode, createProverNode } from '@aztec/prover-node'; import { type SequencerClientConfig } from '@aztec/sequencer-client'; +import { sendL1ToL2Message } from './fixtures/l1_to_l2_messaging.js'; import { type ISnapshotManager, type SubsystemsContext, @@ -30,17 +35,36 @@ describe('e2e_prover_node', () => { let wallet: AccountWalletWithSecretKey; let recipient: AztecAddress; let contract: StatefulTestContract; + let msgTestContract: TestContract; let txReceipts: FieldsOf[]; let logger: DebugLogger; - let snapshotManager: ISnapshotManager; + const msgContent: Fr = Fr.fromString('0xcafe'); + const msgSecret: Fr = Fr.fromString('0xfeca'); + beforeAll(async () => { logger = createDebugLogger('aztec:e2e_prover_node'); const config: Partial = { sequencerSkipSubmitProofs: true }; snapshotManager = createSnapshotManager(`e2e_prover_node`, process.env.E2E_DATA_PATH, config); + const testContractOpts = { contractAddressSalt: Fr.ONE, universalDeploy: true }; + await snapshotManager.snapshot( + 'send-l1-to-l2-msg', + async ctx => { + const testContract = TestContract.deploy(new SignerlessWallet(ctx.pxe)).getInstance(testContractOpts); + const msgHash = await sendL1ToL2Message( + { recipient: testContract.address, content: msgContent, secretHash: computeSecretHash(msgSecret) }, + ctx.deployL1ContractsValues, + ); + return { msgHash }; + }, + async (_data, ctx) => { + msgTestContract = await TestContract.deploy(new SignerlessWallet(ctx.pxe)).register(testContractOpts); + }, + ); + await snapshotManager.snapshot('setup', addAccounts(2, logger), async ({ accountKeys }, ctx) => { const accountManagers = accountKeys.map(ak => getSchnorrAccount(ctx.pxe, ak[0], ak[1], 1)); await Promise.all(accountManagers.map(a => a.register())); @@ -64,13 +88,18 @@ describe('e2e_prover_node', () => { await snapshotManager.snapshot( 'create-blocks', - async () => { - const txReceipt1 = await contract.methods.create_note(recipient, recipient, 10).send().wait(); - const txReceipt2 = await contract.methods.increment_public_value(recipient, 20).send().wait(); - return { txReceipt1, txReceipt2 }; + async ctx => { + const msgSender = ctx.deployL1ContractsValues.walletClient.account.address; + const txReceipt1 = await msgTestContract.methods + .consume_message_from_arbitrary_sender_private(msgContent, msgSecret, EthAddress.fromString(msgSender)) + .send() + .wait(); + const txReceipt2 = await contract.methods.create_note(recipient, recipient, 10).send().wait(); + const txReceipt3 = await contract.methods.increment_public_value(recipient, 20).send().wait(); + return { txReceipts: [txReceipt1, txReceipt2, txReceipt3] }; }, - ({ txReceipt1, txReceipt2 }) => { - txReceipts = [txReceipt1, txReceipt2]; + data => { + txReceipts = data.txReceipts; return Promise.resolve(); }, ); @@ -78,11 +107,21 @@ describe('e2e_prover_node', () => { ctx = await snapshotManager.setup(); }); - it('submits two blocks, then prover proves the first one', async () => { + const prove = async (proverNode: ProverNode, blockNumber: number) => { + logger.info(`Proving block ${blockNumber}`); + await proverNode.prove(blockNumber, blockNumber); + + logger.info(`Proof submitted. Awaiting aztec node to sync...`); + await retryUntil(async () => (await ctx.aztecNode.getProvenBlockNumber()) === blockNumber, 'block-1', 10, 1); + expect(await ctx.aztecNode.getProvenBlockNumber()).toEqual(blockNumber); + }; + + it('submits three blocks, then prover proves the first two', async () => { // Check everything went well during setup and txs were mined in two different blocks - const [txReceipt1, txReceipt2] = txReceipts; + const [txReceipt1, txReceipt2, txReceipt3] = txReceipts; const firstBlock = txReceipt1.blockNumber!; expect(txReceipt2.blockNumber).toEqual(firstBlock + 1); + expect(txReceipt3.blockNumber).toEqual(firstBlock + 2); expect(await contract.methods.get_public_value(recipient).simulate()).toEqual(20n); expect(await contract.methods.summed_values(recipient).simulate()).toEqual(10n); expect(await ctx.aztecNode.getProvenBlockNumber()).toEqual(0); @@ -101,12 +140,8 @@ describe('e2e_prover_node', () => { const archiver = ctx.aztecNode.getBlockSource() as Archiver; const proverNode = await createProverNode(proverConfig, { aztecNodeTxProvider: ctx.aztecNode, archiver }); - // Prove block from first tx and block until it is proven - logger.info(`Proving block ${firstBlock}`); - await proverNode.prove(firstBlock, firstBlock); - - logger.info(`Proof submitted. Awaiting aztec node to sync...`); - await retryUntil(async () => (await ctx.aztecNode.getProvenBlockNumber()) === firstBlock, 'proven-block', 10, 1); - expect(await ctx.aztecNode.getProvenBlockNumber()).toEqual(firstBlock); + // Prove the first two blocks + await prove(proverNode, firstBlock); + await prove(proverNode, firstBlock + 1); }); }); diff --git a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging/l1_to_l2.test.ts b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging/l1_to_l2.test.ts index bc31966bfe6..615ea99c97b 100644 --- a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging/l1_to_l2.test.ts +++ b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging/l1_to_l2.test.ts @@ -7,17 +7,15 @@ import { L2Actor, computeSecretHash, } from '@aztec/aztec.js'; -import { InboxAbi } from '@aztec/l1-artifacts'; import { TestContract } from '@aztec/noir-contracts.js'; -import { type Hex, decodeEventLog } from 'viem'; - +import { sendL1ToL2Message } from '../fixtures/l1_to_l2_messaging.js'; import { PublicCrossChainMessagingContractTest } from './public_cross_chain_messaging_contract_test.js'; describe('e2e_public_cross_chain_messaging l1_to_l2', () => { const t = new PublicCrossChainMessagingContractTest('l1_to_l2'); - let { crossChainTestHarness, aztecNode, user1Wallet, inbox } = t; + let { crossChainTestHarness, aztecNode, user1Wallet } = t; beforeAll(async () => { await t.applyBaseSnapshots(); @@ -26,7 +24,6 @@ describe('e2e_public_cross_chain_messaging l1_to_l2', () => { ({ crossChainTestHarness, user1Wallet } = t); aztecNode = crossChainTestHarness.aztecNode; - inbox = crossChainTestHarness.inbox; }, 300_000); afterAll(async () => { @@ -84,39 +81,7 @@ describe('e2e_public_cross_chain_messaging l1_to_l2', () => { ); const sendL2Message = async (message: L1ToL2Message) => { - // We inject the message to Inbox - const txHash = await inbox.write.sendL2Message( - [ - { actor: message.recipient.recipient.toString() as Hex, version: 1n }, - message.content.toString() as Hex, - message.secretHash.toString() as Hex, - ] as const, - {} as any, - ); - - // We check that the message was correctly injected by checking the emitted event - const msgHash = message.hash(); - { - const txReceipt = await crossChainTestHarness.publicClient.waitForTransactionReceipt({ - hash: txHash, - }); - - // Exactly 1 event should be emitted in the transaction - expect(txReceipt.logs.length).toBe(1); - - // We decode the event and get leaf out of it - const txLog = txReceipt.logs[0]; - const topics = decodeEventLog({ - abi: InboxAbi, - data: txLog.data, - topics: txLog.topics, - }); - const receivedMsgHash = topics.args.hash; - - // We check that the leaf inserted into the subtree matches the expected message hash - expect(receivedMsgHash).toBe(msgHash.toString()); - } - + const msgHash = await sendL1ToL2Message(message, crossChainTestHarness); await crossChainTestHarness.makeMessageConsumable(msgHash); }; }); diff --git a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging/public_cross_chain_messaging_contract_test.ts b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging/public_cross_chain_messaging_contract_test.ts index b747d543e91..f344d479131 100644 --- a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging/public_cross_chain_messaging_contract_test.ts +++ b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging/public_cross_chain_messaging_contract_test.ts @@ -166,6 +166,7 @@ export class PublicCrossChainMessagingContractTest { publicClient, walletClient, this.ownerAddress, + this.aztecNodeConfig.l1Contracts, ); this.publicClient = publicClient; diff --git a/yarn-project/end-to-end/src/fixtures/l1_to_l2_messaging.ts b/yarn-project/end-to-end/src/fixtures/l1_to_l2_messaging.ts new file mode 100644 index 00000000000..ff7ab861e2f --- /dev/null +++ b/yarn-project/end-to-end/src/fixtures/l1_to_l2_messaging.ts @@ -0,0 +1,58 @@ +import { type L1ToL2Message } from '@aztec/aztec.js'; +import { type AztecAddress, Fr } from '@aztec/circuits.js'; +import { type L1ContractAddresses } from '@aztec/ethereum'; +import { InboxAbi } from '@aztec/l1-artifacts'; + +import { expect } from '@jest/globals'; +import { type Hex, type PublicClient, type WalletClient, decodeEventLog, getContract } from 'viem'; + +export async function sendL1ToL2Message( + message: L1ToL2Message | { recipient: AztecAddress; content: Fr; secretHash: Fr }, + ctx: { + walletClient: WalletClient; + publicClient: PublicClient; + l1ContractAddresses: Pick; + }, +) { + const inbox = getContract({ + address: ctx.l1ContractAddresses.inboxAddress.toString(), + abi: InboxAbi, + client: ctx.walletClient, + }); + + const recipient = 'recipient' in message.recipient ? message.recipient.recipient : message.recipient; + const version = 'version' in message.recipient ? message.recipient.version : 1; + + // We inject the message to Inbox + const txHash = await inbox.write.sendL2Message( + [ + { actor: recipient.toString() as Hex, version: BigInt(version) }, + message.content.toString() as Hex, + message.secretHash.toString() as Hex, + ] as const, + {} as any, + ); + + // We check that the message was correctly injected by checking the emitted event + const txReceipt = await ctx.publicClient.waitForTransactionReceipt({ hash: txHash }); + + // Exactly 1 event should be emitted in the transaction + expect(txReceipt.logs.length).toBe(1); + + // We decode the event and get leaf out of it + const txLog = txReceipt.logs[0]; + const topics = decodeEventLog({ + abi: InboxAbi, + data: txLog.data, + topics: txLog.topics, + }); + const receivedMsgHash = topics.args.hash; + + // We check that the leaf inserted into the subtree matches the expected message hash + if ('hash' in message) { + const msgHash = message.hash(); + expect(receivedMsgHash).toBe(msgHash.toString()); + } + + return Fr.fromString(receivedMsgHash); +} diff --git a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts index 7adf0e29ac4..b6f43b98435 100644 --- a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts @@ -17,6 +17,7 @@ import { deployL1Contract, retryUntil, } from '@aztec/aztec.js'; +import { type L1ContractAddresses } from '@aztec/ethereum'; import { sha256ToField } from '@aztec/foundation/crypto'; import { InboxAbi, @@ -185,6 +186,7 @@ export class CrossChainTestHarness { publicClient, walletClient, owner.address, + l1ContractAddresses, ); } @@ -221,6 +223,9 @@ export class CrossChainTestHarness { /** Aztec address to use in tests. */ public ownerAddress: AztecAddress, + + /** Deployment addresses for all L1 contracts */ + public readonly l1ContractAddresses: L1ContractAddresses, ) {} /** diff --git a/yarn-project/prover-node/src/factory.ts b/yarn-project/prover-node/src/factory.ts index 6b5c65d20f2..d2e18610b14 100644 --- a/yarn-project/prover-node/src/factory.ts +++ b/yarn-project/prover-node/src/factory.ts @@ -52,5 +52,5 @@ export async function createProverNode( ? new AztecNodeTxProvider(deps.aztecNodeTxProvider) : createTxProvider(config); - return new ProverNode(prover!, publicProcessorFactory, publisher, archiver, txProvider); + return new ProverNode(prover!, publicProcessorFactory, publisher, archiver, archiver, txProvider); } diff --git a/yarn-project/prover-node/src/job/block-proving-job.ts b/yarn-project/prover-node/src/job/block-proving-job.ts index 1857a26bd71..e0d5c76e92f 100644 --- a/yarn-project/prover-node/src/job/block-proving-job.ts +++ b/yarn-project/prover-node/src/job/block-proving-job.ts @@ -1,6 +1,7 @@ import { type BlockProver, EmptyTxValidator, + type L1ToL2MessageSource, type L2Block, type L2BlockSource, PROVING_STATUS, @@ -9,7 +10,6 @@ import { type TxHash, type TxProvider, } from '@aztec/circuit-types'; -import { type Fr } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { type L1Publisher } from '@aztec/sequencer-client'; import { type PublicProcessor, type PublicProcessorFactory } from '@aztec/simulator'; @@ -28,6 +28,7 @@ export class BlockProvingJob { private publicProcessorFactory: PublicProcessorFactory, private publisher: L1Publisher, private l2BlockSource: L2BlockSource, + private l1ToL2MessageSource: L1ToL2MessageSource, private txProvider: TxProvider, ) {} @@ -53,7 +54,7 @@ export class BlockProvingJob { const globalVariables = block.header.globalVariables; const txHashes = block.body.txEffects.map(tx => tx.txHash); const txCount = block.body.numberOfTxsIncludingPadded; - const l1ToL2Messages: Fr[] = []; // TODO: grab L1 to L2 messages for this block + const l1ToL2Messages = await this.getL1ToL2Messages(block); this.log.verbose(`Starting block processing`, { number: block.number, @@ -116,6 +117,10 @@ export class BlockProvingJob { return txs.map(([_, tx]) => tx!); } + private getL1ToL2Messages(block: L2Block) { + return this.l1ToL2MessageSource.getL1ToL2Messages(BigInt(block.number)); + } + private async processTxs( publicProcessor: PublicProcessor, txs: Tx[], diff --git a/yarn-project/prover-node/src/prover-node.ts b/yarn-project/prover-node/src/prover-node.ts index bd41429fb27..1c435e3cfa3 100644 --- a/yarn-project/prover-node/src/prover-node.ts +++ b/yarn-project/prover-node/src/prover-node.ts @@ -1,4 +1,4 @@ -import { type L2BlockSource, type ProverClient, type TxProvider } from '@aztec/circuit-types'; +import { type L1ToL2MessageSource, type L2BlockSource, type ProverClient, type TxProvider } from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; import { RunningPromise } from '@aztec/foundation/running-promise'; import { type L1Publisher } from '@aztec/sequencer-client'; @@ -20,6 +20,7 @@ export class ProverNode { private publicProcessorFactory: PublicProcessorFactory, private publisher: L1Publisher, private l2BlockSource: L2BlockSource, + private l1ToL2MessageSource: L1ToL2MessageSource, private txProvider: TxProvider, private options: { pollingIntervalMs: number; disableAutomaticProving: boolean } = { pollingIntervalMs: 1_000, @@ -102,6 +103,7 @@ export class ProverNode { this.publicProcessorFactory, this.publisher, this.l2BlockSource, + this.l1ToL2MessageSource, this.txProvider, ); } From bc3689fab40ebd7778c321cf4d37560e003ba6b8 Mon Sep 17 00:00:00 2001 From: Aztec Bot <49558828+AztecBot@users.noreply.github.com> Date: Tue, 30 Jul 2024 09:43:47 -0400 Subject: [PATCH 04/35] chore(master): Release 0.47.1 (#7605) :robot: I have created a release *beep* *boop* ---
aztec-package: 0.47.1 ## [0.47.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.47.0...aztec-package-v0.47.1) (2024-07-30) ### Features * Do not evict tx objects from p2p tx pool immediately ([#7652](https://github.com/AztecProtocol/aztec-packages/issues/7652)) ([96492dc](https://github.com/AztecProtocol/aztec-packages/commit/96492dccbf501eb9d05b57827c79c5977b393df7)) * Min and max block times for sequencer ([#7630](https://github.com/AztecProtocol/aztec-packages/issues/7630)) ([2a013b8](https://github.com/AztecProtocol/aztec-packages/commit/2a013b86e554f0516dd1d086a30a4e1e4e4ec684)) * Transaction sender bot ([#7586](https://github.com/AztecProtocol/aztec-packages/issues/7586)) ([176fd08](https://github.com/AztecProtocol/aztec-packages/commit/176fd08c7b72bce2beb405080b7992ebf4ba0a31)), closes [#7562](https://github.com/AztecProtocol/aztec-packages/issues/7562) ### Bug Fixes * Aztec start --prover ([#7617](https://github.com/AztecProtocol/aztec-packages/issues/7617)) ([ac206a6](https://github.com/AztecProtocol/aztec-packages/commit/ac206a609b3fa6bcad5d8981de8e42967b41050b)) ### Miscellaneous * Add tx bot to terraform ([#7609](https://github.com/AztecProtocol/aztec-packages/issues/7609)) ([6caa914](https://github.com/AztecProtocol/aztec-packages/commit/6caa914d96a13d0e50f0403c561aa72e6b455782)) * Merge Devnet back to Master ([#7611](https://github.com/AztecProtocol/aztec-packages/issues/7611)) ([112961c](https://github.com/AztecProtocol/aztec-packages/commit/112961cd9c9276e2cd95b41b6de31d27bb43bb41))
barretenberg.js: 0.47.1 ## [0.47.1](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.47.0...barretenberg.js-v0.47.1) (2024-07-30) ### Miscellaneous * **barretenberg.js:** Synchronize aztec-packages versions
aztec-packages: 0.47.1 ## [0.47.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.47.0...aztec-packages-v0.47.1) (2024-07-30) ### Features * Add recursive aggregation object to proving/verification keys ([#6770](https://github.com/AztecProtocol/aztec-packages/issues/6770)) ([f48b069](https://github.com/AztecProtocol/aztec-packages/commit/f48b069181e316cb2a9d81f0acf6c00ee90e3db3)) * Adding aggregation to honk and rollup ([#7466](https://github.com/AztecProtocol/aztec-packages/issues/7466)) ([2633aa9](https://github.com/AztecProtocol/aztec-packages/commit/2633aa91a97684f481a861aee0be8756c956135a)) * Allow get_notes to return zero notes ([#7621](https://github.com/AztecProtocol/aztec-packages/issues/7621)) ([e16452a](https://github.com/AztecProtocol/aztec-packages/commit/e16452ab7640169e1235b91d598e3d90ba4ce57e)) * **avm:** Pedersen commit in avm ([#7634](https://github.com/AztecProtocol/aztec-packages/issues/7634)) ([45e7867](https://github.com/AztecProtocol/aztec-packages/commit/45e7867f4b42a3392b4b95767621284ebc7378fe)) * **avm:** Pedersen commitment sim ([#7632](https://github.com/AztecProtocol/aztec-packages/issues/7632)) ([cc420a0](https://github.com/AztecProtocol/aztec-packages/commit/cc420a081e23558b9441cbf563625002e1d45f18)) * Do not evict tx objects from p2p tx pool immediately ([#7652](https://github.com/AztecProtocol/aztec-packages/issues/7652)) ([96492dc](https://github.com/AztecProtocol/aztec-packages/commit/96492dccbf501eb9d05b57827c79c5977b393df7)) * Handle L1toL2 msgs in prover-node ([#7654](https://github.com/AztecProtocol/aztec-packages/issues/7654)) ([f35bac5](https://github.com/AztecProtocol/aztec-packages/commit/f35bac5d35d22e269d8bf2ffccc4484a715d70ae)) * Leonidas ([#7597](https://github.com/AztecProtocol/aztec-packages/issues/7597)) ([eda498a](https://github.com/AztecProtocol/aztec-packages/commit/eda498aec6d852c8732c86564e4226f13cb4cdcd)) * Min and max block times for sequencer ([#7630](https://github.com/AztecProtocol/aztec-packages/issues/7630)) ([2a013b8](https://github.com/AztecProtocol/aztec-packages/commit/2a013b86e554f0516dd1d086a30a4e1e4e4ec684)) * **sol-honk:** Integrate solidity honk verifier with bb and acir tests ([#7573](https://github.com/AztecProtocol/aztec-packages/issues/7573)) ([344ca6f](https://github.com/AztecProtocol/aztec-packages/commit/344ca6f413263a3c2c516b388f85a11fada2840f)) * **sol-honk:** Test verifying recursive proof ([#7576](https://github.com/AztecProtocol/aztec-packages/issues/7576)) ([26408c1](https://github.com/AztecProtocol/aztec-packages/commit/26408c197f5c6e8a300d24e441f4a4860210b5f0)) * Static.aztec.network ([#7649](https://github.com/AztecProtocol/aztec-packages/issues/7649)) ([9dffef5](https://github.com/AztecProtocol/aztec-packages/commit/9dffef598dd5adb6fe02ff697916b63f81a4b054)) * Transaction sender bot ([#7586](https://github.com/AztecProtocol/aztec-packages/issues/7586)) ([176fd08](https://github.com/AztecProtocol/aztec-packages/commit/176fd08c7b72bce2beb405080b7992ebf4ba0a31)), closes [#7562](https://github.com/AztecProtocol/aztec-packages/issues/7562) ### Bug Fixes * Aztec start --prover ([#7617](https://github.com/AztecProtocol/aztec-packages/issues/7617)) ([ac206a6](https://github.com/AztecProtocol/aztec-packages/commit/ac206a609b3fa6bcad5d8981de8e42967b41050b)) * Bb mac build ([#7619](https://github.com/AztecProtocol/aztec-packages/issues/7619)) ([e3c5602](https://github.com/AztecProtocol/aztec-packages/commit/e3c560216e1bce7d22e30ef18d428f1ab7335a09)) * Faucet correctly derives its account ([#7645](https://github.com/AztecProtocol/aztec-packages/issues/7645)) ([921773f](https://github.com/AztecProtocol/aztec-packages/commit/921773fa7fbd614948b1c76f655746483935809f)) * Uniswap e2e test "nonce too low" ([#7633](https://github.com/AztecProtocol/aztec-packages/issues/7633)) ([e9e2318](https://github.com/AztecProtocol/aztec-packages/commit/e9e231833a50c0763164f9a502a322549ce9d05c)) ### Miscellaneous * Add tx bot to terraform ([#7609](https://github.com/AztecProtocol/aztec-packages/issues/7609)) ([6caa914](https://github.com/AztecProtocol/aztec-packages/commit/6caa914d96a13d0e50f0403c561aa72e6b455782)) * **bb readme:** Add installation instructions and TODOs ([#7601](https://github.com/AztecProtocol/aztec-packages/issues/7601)) ([1a97698](https://github.com/AztecProtocol/aztec-packages/commit/1a97698071a667cd56510c7b7201373a9ac9c646)) * **bb readme:** Update versioning instructions and add Honk Solidity verifier commands ([#7608](https://github.com/AztecProtocol/aztec-packages/issues/7608)) ([9dd9195](https://github.com/AztecProtocol/aztec-packages/commit/9dd9195d8da2d7e2bc85d39e53b33cc82597da1f)) * Bench client ivc proof verification ([#7553](https://github.com/AztecProtocol/aztec-packages/issues/7553)) ([b060309](https://github.com/AztecProtocol/aztec-packages/commit/b060309540af2c4db5057ae526ee65f5f1fd6d0e)) * Call requests ([#7483](https://github.com/AztecProtocol/aztec-packages/issues/7483)) ([ffedf39](https://github.com/AztecProtocol/aztec-packages/commit/ffedf39d98aee4c4149e55e4a133e878553e1e25)) * Constant inputs for most blackboxes ([#7613](https://github.com/AztecProtocol/aztec-packages/issues/7613)) ([3247058](https://github.com/AztecProtocol/aztec-packages/commit/3247058d2e54e1fb84680ad9fcf9ece611235e96)) * **docs:** Fix links ([#7602](https://github.com/AztecProtocol/aztec-packages/issues/7602)) ([f2029be](https://github.com/AztecProtocol/aztec-packages/commit/f2029be410ce2381eb4cf56fc5fcc8707492db45)) * Merge Devnet back to Master ([#7611](https://github.com/AztecProtocol/aztec-packages/issues/7611)) ([112961c](https://github.com/AztecProtocol/aztec-packages/commit/112961cd9c9276e2cd95b41b6de31d27bb43bb41)) * **p2p:** Tx serialization cleanup ([#7620](https://github.com/AztecProtocol/aztec-packages/issues/7620)) ([022a899](https://github.com/AztecProtocol/aztec-packages/commit/022a899bb729ec0cd8403955908f3537b108c61b)) * Replace relative paths to noir-protocol-circuits ([ebaafc7](https://github.com/AztecProtocol/aztec-packages/commit/ebaafc7f660cd0ee915e1b6daa2d2e499d9d7280)) * Replace relative paths to noir-protocol-circuits ([d3b818d](https://github.com/AztecProtocol/aztec-packages/commit/d3b818d8fcaffe51273b9eea91b621f62ccf8f1f)) * Replace relative paths to noir-protocol-circuits ([4a26a19](https://github.com/AztecProtocol/aztec-packages/commit/4a26a19c4f03d2c7800cf769b46724d09dcb8b0e))
barretenberg: 0.47.1 ## [0.47.1](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.47.0...barretenberg-v0.47.1) (2024-07-30) ### Features * Add recursive aggregation object to proving/verification keys ([#6770](https://github.com/AztecProtocol/aztec-packages/issues/6770)) ([f48b069](https://github.com/AztecProtocol/aztec-packages/commit/f48b069181e316cb2a9d81f0acf6c00ee90e3db3)) * Adding aggregation to honk and rollup ([#7466](https://github.com/AztecProtocol/aztec-packages/issues/7466)) ([2633aa9](https://github.com/AztecProtocol/aztec-packages/commit/2633aa91a97684f481a861aee0be8756c956135a)) * **avm:** Pedersen commit in avm ([#7634](https://github.com/AztecProtocol/aztec-packages/issues/7634)) ([45e7867](https://github.com/AztecProtocol/aztec-packages/commit/45e7867f4b42a3392b4b95767621284ebc7378fe)) * **avm:** Pedersen commitment sim ([#7632](https://github.com/AztecProtocol/aztec-packages/issues/7632)) ([cc420a0](https://github.com/AztecProtocol/aztec-packages/commit/cc420a081e23558b9441cbf563625002e1d45f18)) * **sol-honk:** Integrate solidity honk verifier with bb and acir tests ([#7573](https://github.com/AztecProtocol/aztec-packages/issues/7573)) ([344ca6f](https://github.com/AztecProtocol/aztec-packages/commit/344ca6f413263a3c2c516b388f85a11fada2840f)) * **sol-honk:** Test verifying recursive proof ([#7576](https://github.com/AztecProtocol/aztec-packages/issues/7576)) ([26408c1](https://github.com/AztecProtocol/aztec-packages/commit/26408c197f5c6e8a300d24e441f4a4860210b5f0)) ### Bug Fixes * Bb mac build ([#7619](https://github.com/AztecProtocol/aztec-packages/issues/7619)) ([e3c5602](https://github.com/AztecProtocol/aztec-packages/commit/e3c560216e1bce7d22e30ef18d428f1ab7335a09)) ### Miscellaneous * **bb readme:** Add installation instructions and TODOs ([#7601](https://github.com/AztecProtocol/aztec-packages/issues/7601)) ([1a97698](https://github.com/AztecProtocol/aztec-packages/commit/1a97698071a667cd56510c7b7201373a9ac9c646)) * **bb readme:** Update versioning instructions and add Honk Solidity verifier commands ([#7608](https://github.com/AztecProtocol/aztec-packages/issues/7608)) ([9dd9195](https://github.com/AztecProtocol/aztec-packages/commit/9dd9195d8da2d7e2bc85d39e53b33cc82597da1f)) * Call requests ([#7483](https://github.com/AztecProtocol/aztec-packages/issues/7483)) ([ffedf39](https://github.com/AztecProtocol/aztec-packages/commit/ffedf39d98aee4c4149e55e4a133e878553e1e25)) * Constant inputs for most blackboxes ([#7613](https://github.com/AztecProtocol/aztec-packages/issues/7613)) ([3247058](https://github.com/AztecProtocol/aztec-packages/commit/3247058d2e54e1fb84680ad9fcf9ece611235e96)) * Merge Devnet back to Master ([#7611](https://github.com/AztecProtocol/aztec-packages/issues/7611)) ([112961c](https://github.com/AztecProtocol/aztec-packages/commit/112961cd9c9276e2cd95b41b6de31d27bb43bb41))
--- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- .release-please-manifest.json | 8 +++--- CHANGELOG.md | 43 +++++++++++++++++++++++++++++++++ barretenberg/CHANGELOG.md | 26 ++++++++++++++++++++ barretenberg/cpp/CMakeLists.txt | 2 +- barretenberg/ts/CHANGELOG.md | 7 ++++++ barretenberg/ts/package.json | 2 +- yarn-project/aztec/CHANGELOG.md | 20 +++++++++++++++ yarn-project/aztec/package.json | 2 +- 8 files changed, 103 insertions(+), 7 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 60f7a2fdedb..9eacce17592 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,7 +1,7 @@ { - ".": "0.47.0", + ".": "0.47.1", "yarn-project/cli": "0.35.1", - "yarn-project/aztec": "0.47.0", - "barretenberg": "0.47.0", - "barretenberg/ts": "0.47.0" + "yarn-project/aztec": "0.47.1", + "barretenberg": "0.47.1", + "barretenberg/ts": "0.47.1" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 29dad1c7a1d..b6fa11b0771 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,48 @@ # Changelog +## [0.47.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.47.0...aztec-packages-v0.47.1) (2024-07-30) + + +### Features + +* Add recursive aggregation object to proving/verification keys ([#6770](https://github.com/AztecProtocol/aztec-packages/issues/6770)) ([f48b069](https://github.com/AztecProtocol/aztec-packages/commit/f48b069181e316cb2a9d81f0acf6c00ee90e3db3)) +* Adding aggregation to honk and rollup ([#7466](https://github.com/AztecProtocol/aztec-packages/issues/7466)) ([2633aa9](https://github.com/AztecProtocol/aztec-packages/commit/2633aa91a97684f481a861aee0be8756c956135a)) +* Allow get_notes to return zero notes ([#7621](https://github.com/AztecProtocol/aztec-packages/issues/7621)) ([e16452a](https://github.com/AztecProtocol/aztec-packages/commit/e16452ab7640169e1235b91d598e3d90ba4ce57e)) +* **avm:** Pedersen commit in avm ([#7634](https://github.com/AztecProtocol/aztec-packages/issues/7634)) ([45e7867](https://github.com/AztecProtocol/aztec-packages/commit/45e7867f4b42a3392b4b95767621284ebc7378fe)) +* **avm:** Pedersen commitment sim ([#7632](https://github.com/AztecProtocol/aztec-packages/issues/7632)) ([cc420a0](https://github.com/AztecProtocol/aztec-packages/commit/cc420a081e23558b9441cbf563625002e1d45f18)) +* Do not evict tx objects from p2p tx pool immediately ([#7652](https://github.com/AztecProtocol/aztec-packages/issues/7652)) ([96492dc](https://github.com/AztecProtocol/aztec-packages/commit/96492dccbf501eb9d05b57827c79c5977b393df7)) +* Handle L1toL2 msgs in prover-node ([#7654](https://github.com/AztecProtocol/aztec-packages/issues/7654)) ([f35bac5](https://github.com/AztecProtocol/aztec-packages/commit/f35bac5d35d22e269d8bf2ffccc4484a715d70ae)) +* Leonidas ([#7597](https://github.com/AztecProtocol/aztec-packages/issues/7597)) ([eda498a](https://github.com/AztecProtocol/aztec-packages/commit/eda498aec6d852c8732c86564e4226f13cb4cdcd)) +* Min and max block times for sequencer ([#7630](https://github.com/AztecProtocol/aztec-packages/issues/7630)) ([2a013b8](https://github.com/AztecProtocol/aztec-packages/commit/2a013b86e554f0516dd1d086a30a4e1e4e4ec684)) +* **sol-honk:** Integrate solidity honk verifier with bb and acir tests ([#7573](https://github.com/AztecProtocol/aztec-packages/issues/7573)) ([344ca6f](https://github.com/AztecProtocol/aztec-packages/commit/344ca6f413263a3c2c516b388f85a11fada2840f)) +* **sol-honk:** Test verifying recursive proof ([#7576](https://github.com/AztecProtocol/aztec-packages/issues/7576)) ([26408c1](https://github.com/AztecProtocol/aztec-packages/commit/26408c197f5c6e8a300d24e441f4a4860210b5f0)) +* Static.aztec.network ([#7649](https://github.com/AztecProtocol/aztec-packages/issues/7649)) ([9dffef5](https://github.com/AztecProtocol/aztec-packages/commit/9dffef598dd5adb6fe02ff697916b63f81a4b054)) +* Transaction sender bot ([#7586](https://github.com/AztecProtocol/aztec-packages/issues/7586)) ([176fd08](https://github.com/AztecProtocol/aztec-packages/commit/176fd08c7b72bce2beb405080b7992ebf4ba0a31)), closes [#7562](https://github.com/AztecProtocol/aztec-packages/issues/7562) + + +### Bug Fixes + +* Aztec start --prover ([#7617](https://github.com/AztecProtocol/aztec-packages/issues/7617)) ([ac206a6](https://github.com/AztecProtocol/aztec-packages/commit/ac206a609b3fa6bcad5d8981de8e42967b41050b)) +* Bb mac build ([#7619](https://github.com/AztecProtocol/aztec-packages/issues/7619)) ([e3c5602](https://github.com/AztecProtocol/aztec-packages/commit/e3c560216e1bce7d22e30ef18d428f1ab7335a09)) +* Faucet correctly derives its account ([#7645](https://github.com/AztecProtocol/aztec-packages/issues/7645)) ([921773f](https://github.com/AztecProtocol/aztec-packages/commit/921773fa7fbd614948b1c76f655746483935809f)) +* Uniswap e2e test "nonce too low" ([#7633](https://github.com/AztecProtocol/aztec-packages/issues/7633)) ([e9e2318](https://github.com/AztecProtocol/aztec-packages/commit/e9e231833a50c0763164f9a502a322549ce9d05c)) + + +### Miscellaneous + +* Add tx bot to terraform ([#7609](https://github.com/AztecProtocol/aztec-packages/issues/7609)) ([6caa914](https://github.com/AztecProtocol/aztec-packages/commit/6caa914d96a13d0e50f0403c561aa72e6b455782)) +* **bb readme:** Add installation instructions and TODOs ([#7601](https://github.com/AztecProtocol/aztec-packages/issues/7601)) ([1a97698](https://github.com/AztecProtocol/aztec-packages/commit/1a97698071a667cd56510c7b7201373a9ac9c646)) +* **bb readme:** Update versioning instructions and add Honk Solidity verifier commands ([#7608](https://github.com/AztecProtocol/aztec-packages/issues/7608)) ([9dd9195](https://github.com/AztecProtocol/aztec-packages/commit/9dd9195d8da2d7e2bc85d39e53b33cc82597da1f)) +* Bench client ivc proof verification ([#7553](https://github.com/AztecProtocol/aztec-packages/issues/7553)) ([b060309](https://github.com/AztecProtocol/aztec-packages/commit/b060309540af2c4db5057ae526ee65f5f1fd6d0e)) +* Call requests ([#7483](https://github.com/AztecProtocol/aztec-packages/issues/7483)) ([ffedf39](https://github.com/AztecProtocol/aztec-packages/commit/ffedf39d98aee4c4149e55e4a133e878553e1e25)) +* Constant inputs for most blackboxes ([#7613](https://github.com/AztecProtocol/aztec-packages/issues/7613)) ([3247058](https://github.com/AztecProtocol/aztec-packages/commit/3247058d2e54e1fb84680ad9fcf9ece611235e96)) +* **docs:** Fix links ([#7602](https://github.com/AztecProtocol/aztec-packages/issues/7602)) ([f2029be](https://github.com/AztecProtocol/aztec-packages/commit/f2029be410ce2381eb4cf56fc5fcc8707492db45)) +* Merge Devnet back to Master ([#7611](https://github.com/AztecProtocol/aztec-packages/issues/7611)) ([112961c](https://github.com/AztecProtocol/aztec-packages/commit/112961cd9c9276e2cd95b41b6de31d27bb43bb41)) +* **p2p:** Tx serialization cleanup ([#7620](https://github.com/AztecProtocol/aztec-packages/issues/7620)) ([022a899](https://github.com/AztecProtocol/aztec-packages/commit/022a899bb729ec0cd8403955908f3537b108c61b)) +* Replace relative paths to noir-protocol-circuits ([ebaafc7](https://github.com/AztecProtocol/aztec-packages/commit/ebaafc7f660cd0ee915e1b6daa2d2e499d9d7280)) +* Replace relative paths to noir-protocol-circuits ([d3b818d](https://github.com/AztecProtocol/aztec-packages/commit/d3b818d8fcaffe51273b9eea91b621f62ccf8f1f)) +* Replace relative paths to noir-protocol-circuits ([4a26a19](https://github.com/AztecProtocol/aztec-packages/commit/4a26a19c4f03d2c7800cf769b46724d09dcb8b0e)) + ## [0.47.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.46.7...aztec-packages-v0.47.0) (2024-07-24) diff --git a/barretenberg/CHANGELOG.md b/barretenberg/CHANGELOG.md index e34c66f4308..09141ec6a96 100644 --- a/barretenberg/CHANGELOG.md +++ b/barretenberg/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## [0.47.1](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.47.0...barretenberg-v0.47.1) (2024-07-30) + + +### Features + +* Add recursive aggregation object to proving/verification keys ([#6770](https://github.com/AztecProtocol/aztec-packages/issues/6770)) ([f48b069](https://github.com/AztecProtocol/aztec-packages/commit/f48b069181e316cb2a9d81f0acf6c00ee90e3db3)) +* Adding aggregation to honk and rollup ([#7466](https://github.com/AztecProtocol/aztec-packages/issues/7466)) ([2633aa9](https://github.com/AztecProtocol/aztec-packages/commit/2633aa91a97684f481a861aee0be8756c956135a)) +* **avm:** Pedersen commit in avm ([#7634](https://github.com/AztecProtocol/aztec-packages/issues/7634)) ([45e7867](https://github.com/AztecProtocol/aztec-packages/commit/45e7867f4b42a3392b4b95767621284ebc7378fe)) +* **avm:** Pedersen commitment sim ([#7632](https://github.com/AztecProtocol/aztec-packages/issues/7632)) ([cc420a0](https://github.com/AztecProtocol/aztec-packages/commit/cc420a081e23558b9441cbf563625002e1d45f18)) +* **sol-honk:** Integrate solidity honk verifier with bb and acir tests ([#7573](https://github.com/AztecProtocol/aztec-packages/issues/7573)) ([344ca6f](https://github.com/AztecProtocol/aztec-packages/commit/344ca6f413263a3c2c516b388f85a11fada2840f)) +* **sol-honk:** Test verifying recursive proof ([#7576](https://github.com/AztecProtocol/aztec-packages/issues/7576)) ([26408c1](https://github.com/AztecProtocol/aztec-packages/commit/26408c197f5c6e8a300d24e441f4a4860210b5f0)) + + +### Bug Fixes + +* Bb mac build ([#7619](https://github.com/AztecProtocol/aztec-packages/issues/7619)) ([e3c5602](https://github.com/AztecProtocol/aztec-packages/commit/e3c560216e1bce7d22e30ef18d428f1ab7335a09)) + + +### Miscellaneous + +* **bb readme:** Add installation instructions and TODOs ([#7601](https://github.com/AztecProtocol/aztec-packages/issues/7601)) ([1a97698](https://github.com/AztecProtocol/aztec-packages/commit/1a97698071a667cd56510c7b7201373a9ac9c646)) +* **bb readme:** Update versioning instructions and add Honk Solidity verifier commands ([#7608](https://github.com/AztecProtocol/aztec-packages/issues/7608)) ([9dd9195](https://github.com/AztecProtocol/aztec-packages/commit/9dd9195d8da2d7e2bc85d39e53b33cc82597da1f)) +* Call requests ([#7483](https://github.com/AztecProtocol/aztec-packages/issues/7483)) ([ffedf39](https://github.com/AztecProtocol/aztec-packages/commit/ffedf39d98aee4c4149e55e4a133e878553e1e25)) +* Constant inputs for most blackboxes ([#7613](https://github.com/AztecProtocol/aztec-packages/issues/7613)) ([3247058](https://github.com/AztecProtocol/aztec-packages/commit/3247058d2e54e1fb84680ad9fcf9ece611235e96)) +* Merge Devnet back to Master ([#7611](https://github.com/AztecProtocol/aztec-packages/issues/7611)) ([112961c](https://github.com/AztecProtocol/aztec-packages/commit/112961cd9c9276e2cd95b41b6de31d27bb43bb41)) + ## [0.47.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.46.7...barretenberg-v0.47.0) (2024-07-24) diff --git a/barretenberg/cpp/CMakeLists.txt b/barretenberg/cpp/CMakeLists.txt index 0489c3b789c..364302ba07f 100644 --- a/barretenberg/cpp/CMakeLists.txt +++ b/barretenberg/cpp/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.24 FATAL_ERROR) project( Barretenberg DESCRIPTION "BN254 elliptic curve library, and PLONK SNARK prover" - VERSION 0.47.0 # x-release-please-version + VERSION 0.47.1 # x-release-please-version LANGUAGES CXX C ) # Insert version into `bb` config file diff --git a/barretenberg/ts/CHANGELOG.md b/barretenberg/ts/CHANGELOG.md index 1110066ca61..f07bf247c50 100644 --- a/barretenberg/ts/CHANGELOG.md +++ b/barretenberg/ts/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.47.1](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.47.0...barretenberg.js-v0.47.1) (2024-07-30) + + +### Miscellaneous + +* **barretenberg.js:** Synchronize aztec-packages versions + ## [0.47.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.46.7...barretenberg.js-v0.47.0) (2024-07-24) diff --git a/barretenberg/ts/package.json b/barretenberg/ts/package.json index 0b7eb5193dd..68d8a347f1c 100644 --- a/barretenberg/ts/package.json +++ b/barretenberg/ts/package.json @@ -1,6 +1,6 @@ { "name": "@aztec/bb.js", - "version": "0.47.0", + "version": "0.47.1", "homepage": "https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg/ts", "license": "MIT", "type": "module", diff --git a/yarn-project/aztec/CHANGELOG.md b/yarn-project/aztec/CHANGELOG.md index 5018f3dbbab..90cd8381bcb 100644 --- a/yarn-project/aztec/CHANGELOG.md +++ b/yarn-project/aztec/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [0.47.1](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.47.0...aztec-package-v0.47.1) (2024-07-30) + + +### Features + +* Do not evict tx objects from p2p tx pool immediately ([#7652](https://github.com/AztecProtocol/aztec-packages/issues/7652)) ([96492dc](https://github.com/AztecProtocol/aztec-packages/commit/96492dccbf501eb9d05b57827c79c5977b393df7)) +* Min and max block times for sequencer ([#7630](https://github.com/AztecProtocol/aztec-packages/issues/7630)) ([2a013b8](https://github.com/AztecProtocol/aztec-packages/commit/2a013b86e554f0516dd1d086a30a4e1e4e4ec684)) +* Transaction sender bot ([#7586](https://github.com/AztecProtocol/aztec-packages/issues/7586)) ([176fd08](https://github.com/AztecProtocol/aztec-packages/commit/176fd08c7b72bce2beb405080b7992ebf4ba0a31)), closes [#7562](https://github.com/AztecProtocol/aztec-packages/issues/7562) + + +### Bug Fixes + +* Aztec start --prover ([#7617](https://github.com/AztecProtocol/aztec-packages/issues/7617)) ([ac206a6](https://github.com/AztecProtocol/aztec-packages/commit/ac206a609b3fa6bcad5d8981de8e42967b41050b)) + + +### Miscellaneous + +* Add tx bot to terraform ([#7609](https://github.com/AztecProtocol/aztec-packages/issues/7609)) ([6caa914](https://github.com/AztecProtocol/aztec-packages/commit/6caa914d96a13d0e50f0403c561aa72e6b455782)) +* Merge Devnet back to Master ([#7611](https://github.com/AztecProtocol/aztec-packages/issues/7611)) ([112961c](https://github.com/AztecProtocol/aztec-packages/commit/112961cd9c9276e2cd95b41b6de31d27bb43bb41)) + ## [0.47.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.46.7...aztec-package-v0.47.0) (2024-07-24) diff --git a/yarn-project/aztec/package.json b/yarn-project/aztec/package.json index 66340d3b9d6..6e2097f9462 100644 --- a/yarn-project/aztec/package.json +++ b/yarn-project/aztec/package.json @@ -1,6 +1,6 @@ { "name": "@aztec/aztec", - "version": "0.47.0", + "version": "0.47.1", "type": "module", "exports": { ".": "./dest/index.js" From 729b36f2c1432d3b62d2cb782f82b8b18411c92b Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 30 Jul 2024 15:09:06 +0100 Subject: [PATCH 05/35] fix: devnet CI issues (#7673) - Exit 0 CI if aztec CLI commands fail - Use different private key for publishing contracts to avoid nonce problems with publisher PK --- .github/workflows/devnet-deploys.yml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 7047cb6e510..e604e5b27dd 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -123,12 +123,18 @@ jobs: run: | docker pull aztecprotocol/aztec:${{ env.DEPLOY_TAG }} docker run aztecprotocol/aztec:${{ env.DEPLOY_TAG }} deploy-l1-contracts \ - --private-key ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ + --private-key ${{ secrets.CONTRACT_PUBLISHER_PRIVATE_KEY }} \ --rpc-url https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ --l1-chain-id ${{ env.L1_CHAIN_ID }} \ --json \ | tee ./l1_contracts.json + + if [ $? -ne 0 ]; then + echo "deploy-l1-contracts command failed" + exit 1 + fi + # upload contract addresses to S3 aws s3 cp ./l1_contracts.json ${{ env.CONTRACT_S3_BUCKET }}/${{ env.DEPLOY_TAG }}/l1_contracts.json @@ -211,6 +217,11 @@ jobs: --json \ | tee ./protocol_contracts.json + if [ $? -ne 0 ]; then + echo "deploy-protocol-contracts command failed" + exit 1 + fi + aws s3 cp ./protocol_contracts.json ${{ env.CONTRACT_S3_BUCKET }}/${{ env.DEPLOY_TAG }}/protocol_contracts.json - name: Bootstrap network @@ -220,10 +231,15 @@ jobs: --rpc-url https://api.aztec.network/${{ env.DEPLOY_TAG }}/aztec-pxe/${{ secrets.FORK_API_KEY }} \ --l1-rpc-url https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ --l1-chain-id ${{ env.L1_CHAIN_ID }} \ - --l1-private-key ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ + --l1-private-key ${{ secrets.CONTRACT_PUBLISHER_PRIVATE_KEY }} \ --json \ | tee ./basic_contracts.json + if [ $? -ne 0 ]; then + echo "bootstrap-network command failed" + exit 1 + fi + aws s3 cp ./basic_contracts.json ${{ env.CONTRACT_S3_BUCKET }}/${{ env.DEPLOY_TAG }}/basic_contracts.json deploy-faucet: From 01204628154cf2e41b1f095ec285995f3de22ade Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Tue, 30 Jul 2024 11:50:09 -0300 Subject: [PATCH 06/35] feat: Add proverId to root rollup public inputs (#7639) Adds a field element as a prover identifier to the public inputs of the root rollup. This is passed directly from the root rollup inputs, and set via a PROVER_ID env var. The prover id gets emitted as part of the L2ProofVerified event on L1. Eventually we may want to change the prover id into an L1 or L2 address, but for now it's an arbitrary value. Fixes #7670 --- l1-contracts/src/core/Rollup.sol | 9 ++++--- l1-contracts/src/core/interfaces/IRollup.sol | 3 ++- .../rollup-lib/src/root/root_rollup_inputs.nr | 5 +++- .../src/root/root_rollup_public_inputs.nr | 3 +++ .../archiver/src/archiver/archiver.test.ts | 7 +++-- .../archiver/src/archiver/archiver.ts | 14 +++------- .../archiver/src/archiver/data_retrieval.ts | 27 +++++++++++++++++-- yarn-project/archiver/src/index.ts | 3 +++ .../src/interfaces/block-prover.ts | 3 +++ .../src/interfaces/prover-client.ts | 3 +++ .../src/structs/rollup/root_rollup.ts | 11 ++++++-- .../circuits.js/src/tests/factories.ts | 2 ++ .../integration_proof_verification.test.ts | 3 +++ .../end-to-end/src/e2e_prover_node.test.ts | 15 ++++++++--- .../src/type_conversion.ts | 2 ++ yarn-project/prover-client/src/config.ts | 8 ++++++ .../prover-client/src/mocks/test_context.ts | 3 +++ .../orchestrator/block-building-helpers.ts | 2 ++ .../src/orchestrator/orchestrator.ts | 8 +++++- .../prover-client/src/tx-prover/tx-prover.ts | 13 +++++++-- .../prover-node/src/job/block-proving-job.ts | 8 +++++- .../src/publisher/l1-publisher.ts | 11 +++++++- .../src/publisher/viem-tx-sender.ts | 3 ++- .../src/sequencer/sequencer.ts | 8 +++++- 24 files changed, 142 insertions(+), 32 deletions(-) diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index d2a15d03b8c..d6e7cd65559 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -127,13 +127,14 @@ contract Rollup is Leonidas, IRollup { function submitProof( bytes calldata _header, bytes32 _archive, + bytes32 _proverId, bytes calldata _aggregationObject, bytes calldata _proof ) external override(IRollup) { HeaderLib.Header memory header = HeaderLib.decode(_header); bytes32[] memory publicInputs = - new bytes32[](3 + Constants.HEADER_LENGTH + Constants.AGGREGATION_OBJECT_LENGTH); + new bytes32[](4 + Constants.HEADER_LENGTH + Constants.AGGREGATION_OBJECT_LENGTH); // the archive tree root publicInputs[0] = _archive; // this is the _next_ available leaf in the archive tree @@ -148,6 +149,8 @@ contract Rollup is Leonidas, IRollup { publicInputs[i + 3] = headerFields[i]; } + publicInputs[headerFields.length + 3] = _proverId; + // the block proof is recursive, which means it comes with an aggregation object // this snippet copies it into the public inputs needed for verification // it also guards against empty _aggregationObject used with mocked proofs @@ -157,14 +160,14 @@ contract Rollup is Leonidas, IRollup { assembly { part := calldataload(add(_aggregationObject.offset, mul(i, 32))) } - publicInputs[i + 3 + Constants.HEADER_LENGTH] = part; + publicInputs[i + 4 + Constants.HEADER_LENGTH] = part; } if (!verifier.verify(_proof, publicInputs)) { revert Errors.Rollup__InvalidProof(); } - emit L2ProofVerified(header.globalVariables.blockNumber); + emit L2ProofVerified(header.globalVariables.blockNumber, _proverId); } function _computePublicInputHash(bytes calldata _header, bytes32 _archive) diff --git a/l1-contracts/src/core/interfaces/IRollup.sol b/l1-contracts/src/core/interfaces/IRollup.sol index 006d5ccb2e4..ff66b2efd6b 100644 --- a/l1-contracts/src/core/interfaces/IRollup.sol +++ b/l1-contracts/src/core/interfaces/IRollup.sol @@ -4,13 +4,14 @@ pragma solidity >=0.8.18; interface IRollup { event L2BlockProcessed(uint256 indexed blockNumber); - event L2ProofVerified(uint256 indexed blockNumber); + event L2ProofVerified(uint256 indexed blockNumber, bytes32 indexed proverId); function process(bytes calldata _header, bytes32 _archive) external; function submitProof( bytes calldata _header, bytes32 _archive, + bytes32 _proverId, bytes calldata _aggregationObject, bytes calldata _proof ) external; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr index 863a8074f9d..2331a093195 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr @@ -34,6 +34,8 @@ struct RootRollupInputs { // inputs required to add the block hash start_archive_snapshot : AppendOnlyTreeSnapshot, new_archive_sibling_path : [Field; ARCHIVE_HEIGHT], + + prover_id: Field, } impl RootRollupInputs { @@ -106,7 +108,7 @@ impl RootRollupInputs { 0 ); - RootRollupPublicInputs { archive, header, vk_tree_root } + RootRollupPublicInputs { archive, header, vk_tree_root, prover_id: self.prover_id } } } @@ -120,6 +122,7 @@ impl Empty for RootRollupInputs { start_l1_to_l2_message_tree_snapshot : AppendOnlyTreeSnapshot::zero(), start_archive_snapshot : AppendOnlyTreeSnapshot::zero(), new_archive_sibling_path : [0; ARCHIVE_HEIGHT], + prover_id: 0 } } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr index 40b352a3ff6..9a49f2c8d50 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr @@ -9,4 +9,7 @@ struct RootRollupPublicInputs { // New block header header: Header, + + // Identifier of the prover + prover_id: Field, } diff --git a/yarn-project/archiver/src/archiver/archiver.test.ts b/yarn-project/archiver/src/archiver/archiver.test.ts index 690c52e4f25..6c1984e094d 100644 --- a/yarn-project/archiver/src/archiver/archiver.test.ts +++ b/yarn-project/archiver/src/archiver/archiver.test.ts @@ -36,10 +36,12 @@ describe('Archiver', () => { let publicClient: MockProxy>; let archiverStore: ArchiverDataStore; + let proverId: Fr; beforeEach(() => { publicClient = mock>(); archiverStore = new MemoryArchiverStore(1000); + proverId = Fr.random(); }); it('can start, sync and stop and handle l1 to l2 messages and logs', async () => { @@ -67,7 +69,7 @@ describe('Archiver', () => { messageSent: [makeMessageSentEvent(98n, 1n, 0n), makeMessageSentEvent(99n, 1n, 1n)], txPublished: [makeTxsPublishedEvent(101n, blocks[0].body.getTxsEffectsHash())], l2BlockProcessed: [makeL2BlockProcessedEvent(101n, 1n)], - proofVerified: [makeProofVerifiedEvent(102n, 1n)], + proofVerified: [makeProofVerifiedEvent(102n, 1n, proverId)], }); mockGetLogs({ @@ -271,11 +273,12 @@ function makeMessageSentEvent(l1BlockNum: bigint, l2BlockNumber: bigint, index: } as Log; } -function makeProofVerifiedEvent(l1BlockNum: bigint, l2BlockNumber: bigint) { +function makeProofVerifiedEvent(l1BlockNum: bigint, l2BlockNumber: bigint, proverId: Fr) { return { blockNumber: l1BlockNum, args: { blockNumber: l2BlockNumber, + proverId: proverId.toString(), }, } as Log; } diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 36dbb075eb0..006bccdfd4d 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -28,7 +28,6 @@ import { type EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { RunningPromise } from '@aztec/foundation/running-promise'; -import { RollupAbi } from '@aztec/l1-artifacts'; import { ClassRegistererAddress } from '@aztec/protocol-contracts/class-registerer'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { @@ -41,7 +40,7 @@ import { } from '@aztec/types/contracts'; import groupBy from 'lodash.groupby'; -import { type Chain, type HttpTransport, type PublicClient, createPublicClient, getAbiItem, http } from 'viem'; +import { type Chain, type HttpTransport, type PublicClient, createPublicClient, http } from 'viem'; import { type ArchiverDataStore } from './archiver_store.js'; import { type ArchiverConfig } from './config.js'; @@ -50,6 +49,7 @@ import { retrieveBlockBodiesFromAvailabilityOracle, retrieveBlockMetadataFromRollup, retrieveL1ToL2Messages, + retrieveL2ProofVerifiedEvents, } from './data_retrieval.js'; import { ArchiverInstrumentation } from './instrumentation.js'; @@ -307,20 +307,14 @@ export class Archiver implements ArchiveSource { } private async updateLastProvenL2Block(fromBlock: bigint, toBlock: bigint) { - const logs = await this.publicClient.getLogs({ - address: this.rollupAddress.toString(), - fromBlock, - toBlock: toBlock + 1n, // toBlock is exclusive - strict: true, - event: getAbiItem({ abi: RollupAbi, name: 'L2ProofVerified' }), - }); + const logs = await retrieveL2ProofVerifiedEvents(this.publicClient, this.rollupAddress, fromBlock, toBlock); const lastLog = logs[logs.length - 1]; if (!lastLog) { return; } - const provenBlockNumber = lastLog.args.blockNumber; + const provenBlockNumber = lastLog.l2BlockNumber; if (!provenBlockNumber) { throw new Error(`Missing argument blockNumber from L2ProofVerified event`); } diff --git a/yarn-project/archiver/src/archiver/data_retrieval.ts b/yarn-project/archiver/src/archiver/data_retrieval.ts index 46dd01160f2..e39e9daff80 100644 --- a/yarn-project/archiver/src/archiver/data_retrieval.ts +++ b/yarn-project/archiver/src/archiver/data_retrieval.ts @@ -1,8 +1,9 @@ import { type Body, type InboxLeaf } from '@aztec/circuit-types'; -import { type AppendOnlyTreeSnapshot, type Header } from '@aztec/circuits.js'; +import { type AppendOnlyTreeSnapshot, Fr, type Header } from '@aztec/circuits.js'; import { type EthAddress } from '@aztec/foundation/eth-address'; +import { RollupAbi } from '@aztec/l1-artifacts'; -import { type PublicClient } from 'viem'; +import { type PublicClient, getAbiItem } from 'viem'; import { getL2BlockProcessedLogs, @@ -143,3 +144,25 @@ export async function retrieveL1ToL2Messages( } while (blockUntilSynced && searchStartBlock <= searchEndBlock); return { lastProcessedL1BlockNumber: searchStartBlock - 1n, retrievedData: retrievedL1ToL2Messages }; } + +/** Retrieves L2ProofVerified events from the rollup contract. */ +export async function retrieveL2ProofVerifiedEvents( + publicClient: PublicClient, + rollupAddress: EthAddress, + searchStartBlock: bigint, + searchEndBlock?: bigint, +): Promise<{ l1BlockNumber: bigint; l2BlockNumber: bigint; proverId: Fr }[]> { + const logs = await publicClient.getLogs({ + address: rollupAddress.toString(), + fromBlock: searchStartBlock, + toBlock: searchEndBlock ? searchEndBlock + 1n : undefined, + strict: true, + event: getAbiItem({ abi: RollupAbi, name: 'L2ProofVerified' }), + }); + + return logs.map(log => ({ + l1BlockNumber: log.blockNumber, + l2BlockNumber: log.args.blockNumber, + proverId: Fr.fromString(log.args.proverId), + })); +} diff --git a/yarn-project/archiver/src/index.ts b/yarn-project/archiver/src/index.ts index b961866522f..e47c3ebb5c5 100644 --- a/yarn-project/archiver/src/index.ts +++ b/yarn-project/archiver/src/index.ts @@ -12,6 +12,9 @@ export * from './archiver/index.js'; export * from './rpc/index.js'; export * from './factory.js'; +// We are not storing the info from these events in the archiver for now (and we don't really need to), so we expose this query directly +export { retrieveL2ProofVerifiedEvents } from './archiver/data_retrieval.js'; + const log = createDebugLogger('aztec:archiver'); /** diff --git a/yarn-project/circuit-types/src/interfaces/block-prover.ts b/yarn-project/circuit-types/src/interfaces/block-prover.ts index e238285326d..a2afdc2f494 100644 --- a/yarn-project/circuit-types/src/interfaces/block-prover.ts +++ b/yarn-project/circuit-types/src/interfaces/block-prover.ts @@ -64,4 +64,7 @@ export interface BlockProver { * Will pad the block to it's complete size with empty transactions and prove all the way to the root rollup. */ setBlockCompleted(): Promise; + + /** Returns an identifier for the prover or zero if not set. */ + getProverId(): Fr; } diff --git a/yarn-project/circuit-types/src/interfaces/prover-client.ts b/yarn-project/circuit-types/src/interfaces/prover-client.ts index f8e390c0297..bdf92e94e2c 100644 --- a/yarn-project/circuit-types/src/interfaces/prover-client.ts +++ b/yarn-project/circuit-types/src/interfaces/prover-client.ts @@ -1,4 +1,5 @@ import { type TxHash } from '@aztec/circuit-types'; +import { type Fr } from '@aztec/circuits.js'; import { type BlockProver } from './block-prover.js'; import { type ProvingJobSource } from './proving-job.js'; @@ -21,6 +22,8 @@ export type ProverConfig = { proverJobTimeoutMs: number; /** The interval to check job health status */ proverJobPollIntervalMs: number; + /** Identifier of the prover */ + proverId?: Fr; }; /** diff --git a/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts index dc1e47ef5a5..df1f06970b2 100644 --- a/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts @@ -48,6 +48,8 @@ export class RootRollupInputs { * Sibling path of the new block tree root. */ public newArchiveSiblingPath: Tuple, + /** Identifier of the prover for this root rollup. */ + public proverId: Fr, ) {} /** @@ -89,6 +91,7 @@ export class RootRollupInputs { fields.startL1ToL2MessageTreeSnapshot, fields.startArchiveSnapshot, fields.newArchiveSiblingPath, + fields.proverId, ] as const; } @@ -107,6 +110,7 @@ export class RootRollupInputs { reader.readObject(AppendOnlyTreeSnapshot), reader.readObject(AppendOnlyTreeSnapshot), reader.readArray(ARCHIVE_HEIGHT, Fr), + reader.readObject(Fr), ); } @@ -133,10 +137,12 @@ export class RootRollupPublicInputs { public vkTreeRoot: Fr, /** A header of an L2 block. */ public header: Header, + /** Identifier of the prover who generated this proof. */ + public proverId: Fr, ) {} static getFields(fields: FieldsOf) { - return [fields.archive, fields.vkTreeRoot, fields.header] as const; + return [fields.archive, fields.vkTreeRoot, fields.header, fields.proverId] as const; } toBuffer() { @@ -160,8 +166,9 @@ export class RootRollupPublicInputs { const reader = BufferReader.asReader(buffer); return new RootRollupPublicInputs( reader.readObject(AppendOnlyTreeSnapshot), - Fr.fromBuffer(reader), + reader.readObject(Fr), reader.readObject(Header), + reader.readObject(Fr), ); } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index c70f31f334c..c2e0b89388b 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -932,6 +932,7 @@ export function makeRootRollupInputs(seed = 0, globalVariables?: GlobalVariables makeAppendOnlyTreeSnapshot(seed + 0x2200), makeAppendOnlyTreeSnapshot(seed + 0x2200), makeTuple(ARCHIVE_HEIGHT, fr, 0x2400), + fr(0x2500), ); } @@ -983,6 +984,7 @@ export function makeRootRollupPublicInputs( archive: makeAppendOnlyTreeSnapshot(seed + 0x100), header: makeHeader(seed + 0x200, blockNumber), vkTreeRoot: fr(seed + 0x300), + proverId: fr(seed + 0x400), }); } diff --git a/yarn-project/end-to-end/src/composed/integration_proof_verification.test.ts b/yarn-project/end-to-end/src/composed/integration_proof_verification.test.ts index 8dc7b8630df..641bb5faded 100644 --- a/yarn-project/end-to-end/src/composed/integration_proof_verification.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_proof_verification.test.ts @@ -33,6 +33,7 @@ import { getLogger, setupL1Contracts, startAnvil } from '../fixtures/utils.js'; */ describe('proof_verification', () => { let proof: Proof; + let proverId: Fr; let block: L2Block; let aggregationObject: Fr[]; let anvil: Anvil | undefined; @@ -121,6 +122,7 @@ describe('proof_verification', () => { block = L2Block.fromString(blockResult.block); proof = Proof.fromString(blockResult.proof); + proverId = Fr.ZERO; aggregationObject = blockResult.aggregationObject.map((x: string) => Fr.fromString(x)); }); @@ -183,6 +185,7 @@ describe('proof_verification', () => { const args = [ `0x${block.header.toBuffer().toString('hex')}`, `0x${block.archive.root.toBuffer().toString('hex')}`, + `0x${proverId.toBuffer().toString('hex')}`, `0x${serializeToBuffer(aggregationObject).toString('hex')}`, `0x${proof.withoutPublicInputs().toString('hex')}`, ] as const; diff --git a/yarn-project/end-to-end/src/e2e_prover_node.test.ts b/yarn-project/end-to-end/src/e2e_prover_node.test.ts index e2e5f6941c7..3035ff969f3 100644 --- a/yarn-project/end-to-end/src/e2e_prover_node.test.ts +++ b/yarn-project/end-to-end/src/e2e_prover_node.test.ts @@ -1,5 +1,5 @@ import { getSchnorrAccount } from '@aztec/accounts/schnorr'; -import { type Archiver } from '@aztec/archiver'; +import { type Archiver, retrieveL2ProofVerifiedEvents } from '@aztec/archiver'; import { type AccountWalletWithSecretKey, type AztecAddress, @@ -29,7 +29,7 @@ import { // Tests simple block building with a sequencer that does not upload proofs to L1, // and then follows with a prover node run (with real proofs disabled, but // still simulating all circuits via a prover-client), in order to test -// the coordination between the sequencer and the prover node. +// the coordination through L1 between the sequencer and the prover node. describe('e2e_prover_node', () => { let ctx: SubsystemsContext; let wallet: AccountWalletWithSecretKey; @@ -133,15 +133,22 @@ describe('e2e_prover_node', () => { // Kick off a prover node await sleep(1000); - logger.info('Creating prover node'); + const proverId = Fr.fromString(Buffer.from('awesome-prover', 'utf-8').toString('hex')); + logger.info(`Creating prover node ${proverId.toString()}`); // HACK: We have to use the existing archiver to fetch L2 data, since anvil's chain dump/load used by the // snapshot manager does not include events nor txs, so a new archiver would not "see" old blocks. - const proverConfig = { ...ctx.aztecNodeConfig, txProviderNodeUrl: undefined, dataDirectory: undefined }; + const proverConfig = { ...ctx.aztecNodeConfig, txProviderNodeUrl: undefined, dataDirectory: undefined, proverId }; const archiver = ctx.aztecNode.getBlockSource() as Archiver; const proverNode = await createProverNode(proverConfig, { aztecNodeTxProvider: ctx.aztecNode, archiver }); // Prove the first two blocks await prove(proverNode, firstBlock); await prove(proverNode, firstBlock + 1); + + // Check that the prover id made it to the emitted event + const { publicClient, l1ContractAddresses } = ctx.deployL1ContractsValues; + const logs = await retrieveL2ProofVerifiedEvents(publicClient, l1ContractAddresses.rollupAddress, 1n); + expect(logs[0].l2BlockNumber).toEqual(BigInt(firstBlock)); + expect(logs[0].proverId.toString()).toEqual(proverId.toString()); }); }); diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index c5e787298f5..4cc162811da 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -2005,6 +2005,7 @@ export function mapRootRollupInputsToNoir(rootRollupInputs: RootRollupInputs): R ), start_archive_snapshot: mapAppendOnlyTreeSnapshotToNoir(rootRollupInputs.startArchiveSnapshot), new_archive_sibling_path: mapTuple(rootRollupInputs.newArchiveSiblingPath, mapFieldToNoir), + prover_id: mapFieldToNoir(rootRollupInputs.proverId), }; } @@ -2045,6 +2046,7 @@ export function mapRootRollupPublicInputsFromNoir( mapAppendOnlyTreeSnapshotFromNoir(rootRollupPublicInputs.archive), mapFieldFromNoir(rootRollupPublicInputs.vk_tree_root), mapHeaderFromNoir(rootRollupPublicInputs.header), + mapFieldFromNoir(rootRollupPublicInputs.prover_id), ); } diff --git a/yarn-project/prover-client/src/config.ts b/yarn-project/prover-client/src/config.ts index 383e85fcb36..bf28cf93ee4 100644 --- a/yarn-project/prover-client/src/config.ts +++ b/yarn-project/prover-client/src/config.ts @@ -1,4 +1,5 @@ import { type ProverConfig } from '@aztec/circuit-types'; +import { Fr } from '@aztec/circuits.js'; import { tmpdir } from 'os'; @@ -39,6 +40,7 @@ export function getProverEnvVars(): ProverClientConfig { PROVER_REAL_PROOFS = '', PROVER_JOB_TIMEOUT_MS = '60000', PROVER_JOB_POLL_INTERVAL_MS = '1000', + PROVER_ID, } = process.env; const realProofs = ['1', 'true'].includes(PROVER_REAL_PROOFS); @@ -48,6 +50,7 @@ export function getProverEnvVars(): ProverClientConfig { const proverJobTimeoutMs = safeParseNumber(PROVER_JOB_TIMEOUT_MS, 60000); const proverJobPollIntervalMs = safeParseNumber(PROVER_JOB_POLL_INTERVAL_MS, 1000); const disableProver = ['1', 'true'].includes(PROVER_DISABLED); + const proverId = PROVER_ID ? parseProverId(PROVER_ID) : undefined; return { acvmWorkingDirectory: ACVM_WORKING_DIRECTORY, @@ -62,9 +65,14 @@ export function getProverEnvVars(): ProverClientConfig { nodeUrl: AZTEC_NODE_URL, proverJobPollIntervalMs, proverJobTimeoutMs, + proverId, }; } +function parseProverId(str: string) { + return Fr.fromString(str.startsWith('0x') ? str : Buffer.from(str, 'utf8').toString('hex')); +} + function safeParseNumber(value: string, defaultValue: number): number { const parsedValue = parseInt(value, 10); return Number.isSafeInteger(parsedValue) ? parsedValue : defaultValue; diff --git a/yarn-project/prover-client/src/mocks/test_context.ts b/yarn-project/prover-client/src/mocks/test_context.ts index c1852eaca9d..dbe28edd870 100644 --- a/yarn-project/prover-client/src/mocks/test_context.ts +++ b/yarn-project/prover-client/src/mocks/test_context.ts @@ -53,6 +53,9 @@ class DummyProverClient implements BlockProver { setBlockCompleted(): Promise { return this.orchestrator.setBlockCompleted(); } + getProverId(): Fr { + return this.orchestrator.proverId; + } } export class TestContext { diff --git a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts index c0aaba59c46..556523a5263 100644 --- a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts +++ b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts @@ -224,6 +224,7 @@ export async function getRootRollupInput( messageTreeSnapshot: AppendOnlyTreeSnapshot, messageTreeRootSiblingPath: Tuple, db: MerkleTreeOperations, + proverId: Fr, ) { const previousRollupData: RootRollupInputs['previousRollupData'] = [ getPreviousRollupDataFromPublicInputs(rollupOutputLeft, rollupProofLeft, verificationKeyLeft), @@ -254,6 +255,7 @@ export async function getRootRollupInput( startL1ToL2MessageTreeSnapshot: messageTreeSnapshot, startArchiveSnapshot, newArchiveSiblingPath, + proverId, }); } diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index 0e78d0c7a89..e3ad5b357af 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -97,7 +97,12 @@ export class ProvingOrchestrator { public readonly tracer: Tracer; - constructor(private db: MerkleTreeOperations, private prover: ServerCircuitProver, telemetryClient: TelemetryClient) { + constructor( + private db: MerkleTreeOperations, + private prover: ServerCircuitProver, + telemetryClient: TelemetryClient, + public readonly proverId: Fr = Fr.ZERO, + ) { this.tracer = telemetryClient.getTracer('ProvingOrchestrator'); } @@ -739,6 +744,7 @@ export class ProvingOrchestrator { provingState.messageTreeSnapshot, provingState.messageTreeRootSiblingPath, this.db, + this.proverId, ); this.deferredProving( diff --git a/yarn-project/prover-client/src/tx-prover/tx-prover.ts b/yarn-project/prover-client/src/tx-prover/tx-prover.ts index 013ca478187..b6b78fc9835 100644 --- a/yarn-project/prover-client/src/tx-prover/tx-prover.ts +++ b/yarn-project/prover-client/src/tx-prover/tx-prover.ts @@ -7,7 +7,7 @@ import { type ProvingTicket, type ServerCircuitProver, } from '@aztec/circuit-types/interfaces'; -import { type Fr, type GlobalVariables } from '@aztec/circuits.js'; +import { Fr, type GlobalVariables } from '@aztec/circuits.js'; import { NativeACVMSimulator } from '@aztec/simulator'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { type WorldStateSynchronizer } from '@aztec/world-state'; @@ -32,7 +32,16 @@ export class TxProver implements ProverClient { private agent?: ProverAgent, ) { this.queue = new MemoryProvingQueue(config.proverJobTimeoutMs, config.proverJobPollIntervalMs); - this.orchestrator = new ProvingOrchestrator(worldStateSynchronizer.getLatest(), this.queue, telemetry); + this.orchestrator = new ProvingOrchestrator( + worldStateSynchronizer.getLatest(), + this.queue, + telemetry, + config.proverId, + ); + } + + public getProverId(): Fr { + return this.config.proverId ?? Fr.ZERO; } async updateProverConfig(config: Partial): Promise { diff --git a/yarn-project/prover-node/src/job/block-proving-job.ts b/yarn-project/prover-node/src/job/block-proving-job.ts index e0d5c76e92f..37c5989a963 100644 --- a/yarn-project/prover-node/src/job/block-proving-job.ts +++ b/yarn-project/prover-node/src/job/block-proving-job.ts @@ -92,7 +92,13 @@ export class BlockProvingJob { this.log.info(`Finalised proof for block range`, { fromBlock, toBlock }); this.state = 'publishing-proof'; - await this.publisher.submitProof(block.header, block.archive.root, aggregationObject, proof); + await this.publisher.submitProof( + block.header, + block.archive.root, + this.prover.getProverId(), + aggregationObject, + proof, + ); this.log.info(`Submitted proof for block range`, { fromBlock, toBlock }); this.state = 'completed'; diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index a4bc9fde02d..7ea4c48bd46 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -113,6 +113,8 @@ export type L1SubmitProofArgs = { header: Buffer; /** A root of the archive tree after the L2 block is applied. */ archive: Buffer; + /** Identifier of the prover. */ + proverId: Buffer; /** The proof for the block. */ proof: Buffer; /** The aggregation object for the block's proof. */ @@ -238,12 +240,19 @@ export class L1Publisher implements L2BlockReceiver { return false; } - public async submitProof(header: Header, archiveRoot: Fr, aggregationObject: Fr[], proof: Proof): Promise { + public async submitProof( + header: Header, + archiveRoot: Fr, + proverId: Fr, + aggregationObject: Fr[], + proof: Proof, + ): Promise { const ctx = { blockNumber: header.globalVariables.blockNumber }; const txArgs: L1SubmitProofArgs = { header: header.toBuffer(), archive: archiveRoot.toBuffer(), + proverId: proverId.toBuffer(), aggregationObject: serializeToBuffer(aggregationObject), proof: proof.withoutPublicInputs(), }; diff --git a/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts b/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts index a9456301037..8669c13701f 100644 --- a/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts +++ b/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts @@ -176,10 +176,11 @@ export class ViemTxSender implements L1PublisherTxSender { * @returns The hash of the mined tx. */ async sendSubmitProofTx(submitProofArgs: L1SubmitProofArgs): Promise { - const { header, archive, aggregationObject, proof } = submitProofArgs; + const { header, archive, proverId, aggregationObject, proof } = submitProofArgs; const args = [ `0x${header.toString('hex')}`, `0x${archive.toString('hex')}`, + `0x${proverId.toString('hex')}`, `0x${aggregationObject.toString('hex')}`, `0x${proof.toString('hex')}`, ] as const; diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 3a6ccb0cf72..8fbdff27634 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -365,7 +365,13 @@ export class Sequencer { // This is temporary while we submit one proof per block, but will have to change once we // move onto proving batches of multiple blocks at a time. if (aggregationObject && proof && !this.skipSubmitProofs) { - await this.publisher.submitProof(block.header, block.archive.root, aggregationObject, proof); + await this.publisher.submitProof( + block.header, + block.archive.root, + this.prover.getProverId(), + aggregationObject, + proof, + ); this.log.info(`Submitted proof for block ${block.number}`); } } From dd6176b444ae1b9f8313af98f7ebd5eeb2f31ed7 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Tue, 30 Jul 2024 12:40:32 -0300 Subject: [PATCH 07/35] chore: Handle exceptions in bot runner (#7679) Adds much-needed try/catch statements in the txs bot runner, improve logging in the bot itself, and add a configurable timeout for awaiting txs to be mined. It also defaults the log level to verbose in the tf template. Fixes #7658 --- yarn-project/aztec/terraform/bot/main.tf | 1 + yarn-project/aztec/terraform/bot/variables.tf | 5 ++ yarn-project/bot/src/bot.ts | 23 +++++++-- yarn-project/bot/src/config.ts | 5 ++ yarn-project/bot/src/runner.ts | 48 +++++++++++++++---- 5 files changed, 69 insertions(+), 13 deletions(-) diff --git a/yarn-project/aztec/terraform/bot/main.tf b/yarn-project/aztec/terraform/bot/main.tf index f3e5bc0000c..4353e10a48a 100644 --- a/yarn-project/aztec/terraform/bot/main.tf +++ b/yarn-project/aztec/terraform/bot/main.tf @@ -99,6 +99,7 @@ resource "aws_ecs_task_definition" "aztec-bot" { { name = "BOT_NO_START", value = "true" }, { name = "BOT_PXE_URL", value = "http://${var.DEPLOY_TAG}-aztec-pxe-1.local/${var.DEPLOY_TAG}/aztec-pxe-1/${var.API_KEY}" }, { name = "BOT_TX_INTERVAL_SECONDS", value = 300 }, + { name = "LOG_LEVEL", value = var.LOG_LEVEL }, { name = "AZTEC_PORT", value = "80" }, { name = "API_PREFIX", value = local.api_prefix }, ] diff --git a/yarn-project/aztec/terraform/bot/variables.tf b/yarn-project/aztec/terraform/bot/variables.tf index c724241819a..a4720ad6ac4 100644 --- a/yarn-project/aztec/terraform/bot/variables.tf +++ b/yarn-project/aztec/terraform/bot/variables.tf @@ -17,3 +17,8 @@ variable "BOT_API_KEY" { variable "BOT_PRIVATE_KEY" { type = string } + +variable "LOG_LEVEL" { + type = string + default = "verbose" +} diff --git a/yarn-project/bot/src/bot.ts b/yarn-project/bot/src/bot.ts index 2329f645cc3..1fff1e12f51 100644 --- a/yarn-project/bot/src/bot.ts +++ b/yarn-project/bot/src/bot.ts @@ -34,12 +34,14 @@ export class Bot { } public async run() { + const logCtx = { runId: Date.now() * 1000 + Math.floor(Math.random() * 1000) }; const { privateTransfersPerTx, publicTransfersPerTx, feePaymentMethod } = this.config; const { token, recipient, wallet } = this; const sender = wallet.getAddress(); this.log.verbose( `Sending tx with ${feePaymentMethod} fee with ${privateTransfersPerTx} private and ${publicTransfersPerTx} public transfers`, + logCtx, ); const calls: FunctionCall[] = [ @@ -52,11 +54,24 @@ export class Bot { const paymentMethod = feePaymentMethod === 'native' ? new NativeFeePaymentMethod(sender) : new NoFeePaymentMethod(); const gasSettings = GasSettings.default(); const opts: SendMethodOptions = { estimateGas: true, fee: { paymentMethod, gasSettings } }; - const tx = new BatchCall(wallet, calls).send(opts); - this.log.verbose(`Sent tx ${tx.getTxHash()}`); - const receipt = await tx.wait(); - this.log.info(`Tx ${receipt.txHash} mined in block ${receipt.blockNumber}`); + const batch = new BatchCall(wallet, calls); + this.log.verbose(`Creating batch execution request with ${calls.length} calls`, logCtx); + await batch.create(opts); + + this.log.verbose(`Simulating transaction`, logCtx); + await batch.simulate(); + + this.log.verbose(`Proving transaction`, logCtx); + await batch.prove(opts); + + this.log.verbose(`Sending tx`, logCtx); + const tx = batch.send(opts); + + this.log.verbose(`Awaiting tx ${tx.getTxHash()} to be mined (timeout ${this.config.txMinedWaitSeconds}s)`, logCtx); + const receipt = await tx.wait({ timeout: this.config.txMinedWaitSeconds }); + + this.log.info(`Tx ${receipt.txHash} mined in block ${receipt.blockNumber}`, logCtx); } public async getBalances() { diff --git a/yarn-project/bot/src/config.ts b/yarn-project/bot/src/config.ts index 844ffd9df40..ee93af956c8 100644 --- a/yarn-project/bot/src/config.ts +++ b/yarn-project/bot/src/config.ts @@ -20,6 +20,8 @@ export type BotConfig = { feePaymentMethod: 'native' | 'none'; /** True to not automatically setup or start the bot on initialization. */ noStart: boolean; + /** How long to wait for a tx to be mined before reporting an error. */ + txMinedWaitSeconds: number; }; export function getBotConfigFromEnv(): BotConfig { @@ -32,6 +34,7 @@ export function getBotConfigFromEnv(): BotConfig { BOT_PRIVATE_TRANSFERS_PER_TX, BOT_PUBLIC_TRANSFERS_PER_TX, BOT_NO_START, + BOT_TX_MINED_WAIT_SECONDS, } = process.env; if (BOT_FEE_PAYMENT_METHOD && !['native', 'none'].includes(BOT_FEE_PAYMENT_METHOD)) { throw new Error(`Invalid bot fee payment method: ${BOT_FEE_PAYMENT_METHOD}`); @@ -49,6 +52,7 @@ export function getBotConfigFromEnv(): BotConfig { publicTransfersPerTx: BOT_PUBLIC_TRANSFERS_PER_TX ? parseInt(BOT_PUBLIC_TRANSFERS_PER_TX) : undefined, feePaymentMethod: BOT_FEE_PAYMENT_METHOD ? (BOT_FEE_PAYMENT_METHOD as 'native' | 'none') : undefined, noStart: BOT_NO_START ? ['1', 'true'].includes(BOT_NO_START) : undefined, + txMinedWaitSeconds: BOT_TX_MINED_WAIT_SECONDS ? parseInt(BOT_TX_MINED_WAIT_SECONDS) : undefined, }); } @@ -63,6 +67,7 @@ export function getBotDefaultConfig(overrides: Partial = {}): BotConf publicTransfersPerTx: 1, feePaymentMethod: 'none', noStart: false, + txMinedWaitSeconds: 180, ...compact(overrides), }; } diff --git a/yarn-project/bot/src/runner.ts b/yarn-project/bot/src/runner.ts index 1bcd9445ceb..976a7b2297d 100644 --- a/yarn-project/bot/src/runner.ts +++ b/yarn-project/bot/src/runner.ts @@ -31,7 +31,7 @@ export class BotRunner { await this.setup(); if (!this.interval) { this.log.info(`Starting bot with interval of ${this.config.txIntervalSeconds}s`); - this.interval = setInterval(() => this.run(), this.config.txIntervalSeconds * 1000); + this.interval = setInterval(() => this.#safeRun(), this.config.txIntervalSeconds * 1000); } } @@ -80,14 +80,31 @@ export class BotRunner { */ public async run() { if (!this.bot) { + this.log.error(`Trying to run with uninitialized bot`); throw new Error(`Bot is not initialized`); } - this.log.verbose(`Manually triggered bot run`); - const bot = await this.bot; - const promise = bot.run(); - this.running.add(promise); - await promise; - this.running.delete(promise); + + let bot; + try { + bot = await this.bot; + } catch (err) { + this.log.error(`Error awaiting bot set up: ${err}`); + throw err; + } + + let promise; + try { + promise = bot.run(); + this.running.add(promise); + await promise; + } catch (err) { + this.log.error(`Error running bot: ${err}`); + throw err; + } finally { + if (promise) { + this.running.delete(promise); + } + } } /** Returns the current configuration for the bot. */ @@ -96,7 +113,20 @@ export class BotRunner { } async #createBot() { - this.bot = Bot.create(this.config, { pxe: this.pxe }); - await this.bot; + try { + this.bot = Bot.create(this.config, { pxe: this.pxe }); + await this.bot; + } catch (err) { + this.log.error(`Error setting up bot: ${err}`); + throw err; + } + } + + async #safeRun() { + try { + await this.run(); + } catch (err) { + // Already logged in run() + } } } From 11f3885d11237dbd3e203d07bf4cdb7df316e07a Mon Sep 17 00:00:00 2001 From: guipublic <47281315+guipublic@users.noreply.github.com> Date: Tue, 30 Jul 2024 18:25:52 +0200 Subject: [PATCH 08/35] fix: ensure dummy values are on the curve for MSM (#7653) This PR fix an issue with MSM when trying to verify a circuit having MSM blackbox, because dummy values are not on the curve. I also added a BB unit test which ensure non-constant inputs are properly handled in the 'no witness assignment' case --- .../dsl/acir_format/acir_format.cpp | 2 +- .../dsl/acir_format/multi_scalar_mul.cpp | 28 ++++- .../dsl/acir_format/multi_scalar_mul.hpp | 5 +- .../dsl/acir_format/multi_scalar_mul.test.cpp | 116 ++++++++++++++++++ 4 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.test.cpp 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 c3c1b0c60db..8fb66b1b522 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -176,7 +176,7 @@ void build_constraints(Builder& builder, // Add multi scalar mul constraints for (size_t i = 0; i < constraint_system.multi_scalar_mul_constraints.size(); ++i) { const auto& constraint = constraint_system.multi_scalar_mul_constraints.at(i); - create_multi_scalar_mul_constraint(builder, constraint); + create_multi_scalar_mul_constraint(builder, constraint, has_valid_witness_assignments); track_gate_diff(constraint_system.gates_per_opcode, constraint_system.original_opcode_indices.multi_scalar_mul_constraints.at(i)); } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.cpp index 1baf25b97ec..776baf67227 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.cpp @@ -10,7 +10,10 @@ namespace acir_format { using namespace bb; -template void create_multi_scalar_mul_constraint(Builder& builder, const MultiScalarMul& input) +template +void create_multi_scalar_mul_constraint(Builder& builder, + const MultiScalarMul& input, + bool has_valid_witness_assignments) { using cycle_group_ct = stdlib::cycle_group; using cycle_scalar_ct = typename stdlib::cycle_group::cycle_scalar; @@ -25,9 +28,26 @@ template void create_multi_scalar_mul_constraint(Builder& bui field_ct point_x; field_ct point_y; bool_ct infinite; + point_x = to_field_ct(input.points[i], builder); point_y = to_field_ct(input.points[i + 1], builder); infinite = bool_ct(to_field_ct(input.points[i + 2], builder)); + + // When we do not have the witness assignments, we set is_infinite value to true if it is not constant + // else default values would give a point which is not on the curve and this will fail verification + if (!has_valid_witness_assignments) { + if (!input.points[i + 2].is_constant) { + builder.variables[input.points[i + 2].index] = fr(1); + } else if (input.points[i + 2].value == fr::zero() && + !(input.points[i].is_constant || input.points[i + 1].is_constant)) { + // else, if is_infinite is false, but the coordinates (x, y) are witness + // then we set their value so to a curve point. + auto g1 = bb::grumpkin::g1::affine_one; + builder.variables[input.points[i].index] = g1.x; + builder.variables[input.points[i + 1].index] = g1.y; + } + } + cycle_group_ct input_point(point_x, point_y, infinite); // Reconstruct the scalar from the low and high limbs field_ct scalar_low_as_field; @@ -69,8 +89,10 @@ template void create_multi_scalar_mul_constraint(Builder& bui } template void create_multi_scalar_mul_constraint(UltraCircuitBuilder& builder, - const MultiScalarMul& input); + const MultiScalarMul& input, + bool has_valid_witness_assignments); template void create_multi_scalar_mul_constraint(MegaCircuitBuilder& builder, - const MultiScalarMul& input); + const MultiScalarMul& input, + bool has_valid_witness_assignments); } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.hpp index 0d13aaca513..ac04ae447db 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.hpp @@ -21,6 +21,9 @@ struct MultiScalarMul { friend bool operator==(MultiScalarMul const& lhs, MultiScalarMul const& rhs) = default; }; -template void create_multi_scalar_mul_constraint(Builder& builder, const MultiScalarMul& input); +template +void create_multi_scalar_mul_constraint(Builder& builder, + const MultiScalarMul& input, + bool has_valid_witness_assignments); } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.test.cpp new file mode 100644 index 00000000000..7f59d142d9b --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.test.cpp @@ -0,0 +1,116 @@ +#include "multi_scalar_mul.hpp" +#include "acir_format.hpp" +#include "acir_format_mocks.hpp" +#include "acir_to_constraint_buf.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/plonk/composer/ultra_composer.hpp" +#include "barretenberg/plonk/proof_system/types/proof.hpp" +#include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp" + +#include +#include +#include + +namespace acir_format::tests { + +using namespace bb; +using Composer = plonk::UltraComposer; + +class MSMTests : public ::testing::Test { + protected: + static void SetUpTestSuite() { srs::init_crs_factory("../srs_db/ignition"); } +}; +using fr = field; + +/** + * @brief Create a circuit testing the a simple scalar mul with a constant generator + * + */ +TEST_F(MSMTests, TestMSM) +{ + MultiScalarMul msm_constrain{ + .points = { WitnessOrConstant{ + .index = 0, + .value = fr(1), + .is_constant = true, + }, + WitnessOrConstant{ + .index = 0, + .value = fr("0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c"), + .is_constant = true, + }, + WitnessOrConstant{ + .index = 0, + .value = fr(0), + .is_constant = true, + } }, + .scalars = { WitnessOrConstant{ + .index = 0, + .value = fr(std::string("0x000000000000000000000000000000000000000000000000000000616c696365")), + .is_constant = false, + }, + WitnessOrConstant{ + .index = 0, + .value = fr(0), + .is_constant = true, + } }, + + .out_point_x = 1, + .out_point_y = 2, + .out_point_is_infinite = 3, + }; + + AcirFormat constraint_system{ + .varnum = 9, + .recursive = false, + .num_acir_opcodes = 1, + .public_inputs = {}, + .logic_constraints = {}, + .range_constraints = {}, + .aes128_constraints = {}, + .sha256_constraints = {}, + .sha256_compression = {}, + .schnorr_constraints = {}, + .ecdsa_k1_constraints = {}, + .ecdsa_r1_constraints = {}, + .blake2s_constraints = {}, + .blake3_constraints = {}, + .keccak_constraints = {}, + .keccak_permutations = {}, + .pedersen_constraints = {}, + .pedersen_hash_constraints = {}, + .poseidon2_constraints = {}, + .multi_scalar_mul_constraints = { msm_constrain }, + .ec_add_constraints = {}, + .recursion_constraints = {}, + .honk_recursion_constraints = {}, + .bigint_from_le_bytes_constraints = {}, + .bigint_to_le_bytes_constraints = {}, + .bigint_operations = {}, + .poly_triple_constraints = {}, + .quad_constraints = {}, + .block_constraints = {}, + .original_opcode_indices = create_empty_original_opcode_indices(), + }; + mock_opcode_indices(constraint_system); + + WitnessVector witness{ + fr("0x000000000000000000000000000000000000000000000000000000616c696365"), + fr("0x0bff8247aa94b08d1c680d7a3e10831bd8c8cf2ea2c756b0d1d89acdcad877ad"), + fr("0x2a5d7253a6ed48462fedb2d350cc768d13956310f54e73a8a47914f34a34c5c4"), + fr(0), + }; + + auto builder = create_circuit(constraint_system, /*size_hint=*/0, witness); + auto composer = Composer(); + auto prover = composer.create_ultra_with_keccak_prover(builder); + auto proof = prover.construct_proof(); + + auto builder2 = create_circuit(constraint_system, /*size_hint=*/0, {}); + auto composer2 = Composer(); + auto verifier = composer2.create_ultra_with_keccak_verifier(builder2); + + EXPECT_EQ(verifier.verify_proof(proof), true); +} + +} // namespace acir_format::tests From dc8ad6ee552c98d14eb68484c0ad3cf42d2995cd Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Tue, 30 Jul 2024 17:32:01 -0300 Subject: [PATCH 09/35] fix: Anvil block timestamp (#7686) Anvil uses the time of the forked block as its timestamp as its baseline. Subsequent blocks have a timestamp equal to that baseline plus the time that passed since the fork was created. To fix it, we set the next block timestamp manually to the current date and immediately trigger a block mine. --- iac/mainnet-fork/scripts/run_nginx_anvil.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/iac/mainnet-fork/scripts/run_nginx_anvil.sh b/iac/mainnet-fork/scripts/run_nginx_anvil.sh index d73fb885f6c..2ac3ecfd0a0 100755 --- a/iac/mainnet-fork/scripts/run_nginx_anvil.sh +++ b/iac/mainnet-fork/scripts/run_nginx_anvil.sh @@ -27,6 +27,10 @@ mkdir -p /data echo "Waiting for ethereum host at $ETHEREUM_HOST..." while ! curl -s $ETHEREUM_HOST >/dev/null; do sleep 1; done +# Fix anvil's fork timestamp +./foundry/bin/cast rpc --rpc-url="$ETHEREUM_HOST" evm_setNextBlockTimestamp $(date +%s | xargs printf '0x%x') > /dev/null +./foundry/bin/cast rpc --rpc-url="$ETHEREUM_HOST" evm_mine > /dev/null + echo "Starting nginx..." nginx & wait From dff2ffb81c8dab33567c1263cf412aacce89af66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Rodr=C3=ADguez?= Date: Tue, 30 Jul 2024 22:42:51 +0200 Subject: [PATCH 10/35] feat: Optimize constant array handling in brillig_gen (#7661) Optimize array initialization to avoid repeatedly computing pointers. Instead of tracking indices and recomputing pointers at every step, track the pointers and increase them at every step. --- .../src/brillig/brillig_gen/brillig_block.rs | 136 +++++++++--------- .../brillig/brillig_gen/brillig_slice_ops.rs | 18 ++- .../brillig_ir/codegen_control_flow.rs | 33 +++-- .../src/brillig/brillig_ir/codegen_memory.rs | 44 ++++++ 4 files changed, 149 insertions(+), 82 deletions(-) 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 c2bc1e32cd6..37128508086 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 @@ -938,7 +938,7 @@ impl<'block> BrilligBlock<'block> { if let Some((index_register, value_variable)) = opt_index_and_value { // Then set the value in the newly created array - self.store_variable_in_array( + self.brillig_context.codegen_store_variable_in_array( destination_pointer, SingleAddrVariable::new_usize(index_register), value_variable, @@ -949,47 +949,6 @@ impl<'block> BrilligBlock<'block> { source_size_as_register } - pub(crate) fn store_variable_in_array_with_ctx( - ctx: &mut BrilligContext, - destination_pointer: MemoryAddress, - index_register: SingleAddrVariable, - value_variable: BrilligVariable, - ) { - match value_variable { - BrilligVariable::SingleAddr(value_variable) => { - ctx.codegen_array_set(destination_pointer, index_register, value_variable.address); - } - BrilligVariable::BrilligArray(_) => { - let reference: MemoryAddress = ctx.allocate_register(); - ctx.codegen_allocate_array_reference(reference); - ctx.codegen_store_variable(reference, value_variable); - ctx.codegen_array_set(destination_pointer, index_register, reference); - ctx.deallocate_register(reference); - } - BrilligVariable::BrilligVector(_) => { - let reference = ctx.allocate_register(); - ctx.codegen_allocate_vector_reference(reference); - ctx.codegen_store_variable(reference, value_variable); - ctx.codegen_array_set(destination_pointer, index_register, reference); - ctx.deallocate_register(reference); - } - } - } - - pub(crate) fn store_variable_in_array( - &mut self, - destination_pointer: MemoryAddress, - index_variable: SingleAddrVariable, - value_variable: BrilligVariable, - ) { - Self::store_variable_in_array_with_ctx( - self.brillig_context, - destination_pointer, - index_variable, - value_variable, - ); - } - /// Convert the SSA slice operations to brillig slice operations fn convert_ssa_slice_intrinsic_call( &mut self, @@ -1748,10 +1707,19 @@ impl<'block> BrilligBlock<'block> { subitem_to_repeat_variables.push(self.convert_ssa_value(subitem_id, dfg)); } - let data_length_variable = self + // Initialize loop bound with the array length + let end_pointer_variable = self .brillig_context .make_usize_constant_instruction((item_count * item_types.len()).into()); + // Add the pointer to the array length + self.brillig_context.memory_op_instruction( + end_pointer_variable.address, + pointer, + end_pointer_variable.address, + BrilligBinaryOp::Add, + ); + // If this is an array with complex subitems, we need a custom step in the loop to write all the subitems while iterating. if item_types.len() > 1 { let step_variable = @@ -1760,33 +1728,54 @@ impl<'block> BrilligBlock<'block> { let subitem_pointer = SingleAddrVariable::new_usize(self.brillig_context.allocate_register()); - let initializer_fn = |ctx: &mut BrilligContext<_>, iterator: SingleAddrVariable| { - ctx.mov_instruction(subitem_pointer.address, iterator.address); - for subitem in subitem_to_repeat_variables.into_iter() { - Self::store_variable_in_array_with_ctx(ctx, pointer, subitem_pointer, subitem); - ctx.codegen_usize_op_in_place(subitem_pointer.address, BrilligBinaryOp::Add, 1); - } - }; + let one = self.brillig_context.make_usize_constant_instruction(1_usize.into()); + + // Initializes a single subitem + let initializer_fn = + |ctx: &mut BrilligContext<_>, subitem_start_pointer: SingleAddrVariable| { + ctx.mov_instruction(subitem_pointer.address, subitem_start_pointer.address); + for (subitem_index, subitem) in + subitem_to_repeat_variables.into_iter().enumerate() + { + ctx.codegen_store_variable_in_pointer(subitem_pointer.address, subitem); + if subitem_index != item_types.len() - 1 { + ctx.memory_op_instruction( + subitem_pointer.address, + one.address, + subitem_pointer.address, + BrilligBinaryOp::Add, + ); + } + } + }; - self.brillig_context.codegen_loop_with_bound_and_step( - data_length_variable.address, - step_variable.address, + // for (let subitem_start_pointer = pointer; subitem_start_pointer < pointer + data_length; subitem_start_pointer += step) { initializer_fn(iterator) } + self.brillig_context.codegen_for_loop( + Some(pointer), + end_pointer_variable.address, + Some(step_variable.address), initializer_fn, ); self.brillig_context.deallocate_single_addr(step_variable); self.brillig_context.deallocate_single_addr(subitem_pointer); + self.brillig_context.deallocate_single_addr(one); } else { let subitem = subitem_to_repeat_variables.into_iter().next().unwrap(); - let initializer_fn = |ctx: &mut _, iterator_register| { - Self::store_variable_in_array_with_ctx(ctx, pointer, iterator_register, subitem); + let initializer_fn = |ctx: &mut BrilligContext<_>, item_pointer: SingleAddrVariable| { + ctx.codegen_store_variable_in_pointer(item_pointer.address, subitem); }; - self.brillig_context.codegen_loop(data_length_variable.address, initializer_fn); + // for (let item_pointer = pointer; item_pointer < pointer + data_length; item_pointer += 1) { initializer_fn(iterator) } + self.brillig_context.codegen_for_loop( + Some(pointer), + end_pointer_variable.address, + None, + initializer_fn, + ); } - - self.brillig_context.deallocate_single_addr(data_length_variable); + self.brillig_context.deallocate_single_addr(end_pointer_variable); } fn initialize_constant_array_comptime( @@ -1796,22 +1785,29 @@ impl<'block> BrilligBlock<'block> { pointer: MemoryAddress, ) { // Allocate a register for the iterator - let iterator_register = - self.brillig_context.make_usize_constant_instruction(0_usize.into()); + let write_pointer_register = self.brillig_context.allocate_register(); + let one = self.brillig_context.make_usize_constant_instruction(1_usize.into()); - for element_id in data.iter() { + self.brillig_context.mov_instruction(write_pointer_register, pointer); + + for (element_idx, element_id) in data.iter().enumerate() { let element_variable = self.convert_ssa_value(*element_id, dfg); // Store the item in memory - self.store_variable_in_array(pointer, iterator_register, element_variable); - // Increment the iterator - self.brillig_context.codegen_usize_op_in_place( - iterator_register.address, - BrilligBinaryOp::Add, - 1, - ); + self.brillig_context + .codegen_store_variable_in_pointer(write_pointer_register, element_variable); + if element_idx != data.len() - 1 { + // Increment the write_pointer_register + self.brillig_context.memory_op_instruction( + write_pointer_register, + one.address, + write_pointer_register, + BrilligBinaryOp::Add, + ); + } } - self.brillig_context.deallocate_single_addr(iterator_register); + self.brillig_context.deallocate_register(write_pointer_register); + self.brillig_context.deallocate_single_addr(one); } /// Converts an SSA `ValueId` into a `MemoryAddress`. Initializes if necessary. @@ -1896,7 +1892,7 @@ impl<'block> BrilligBlock<'block> { let inner_array = self.allocate_nested_array(element_type, None); let idx = self.brillig_context.make_usize_constant_instruction(index.into()); - self.store_variable_in_array(array.pointer, idx, inner_array); + self.brillig_context.codegen_store_variable_in_array(array.pointer, idx, inner_array); } Type::Slice(_) => unreachable!("ICE: unsupported slice type in allocate_nested_array(), expects an array or a numeric type"), _ => (), diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index d17b15a13b5..55679432b1f 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs @@ -38,7 +38,11 @@ impl<'block> BrilligBlock<'block> { target_index.address, BrilligBinaryOp::Add, ); - self.store_variable_in_array(target_vector.pointer, target_index, *variable); + self.brillig_context.codegen_store_variable_in_array( + target_vector.pointer, + target_index, + *variable, + ); self.brillig_context.deallocate_single_addr(target_index); } } @@ -79,7 +83,11 @@ impl<'block> BrilligBlock<'block> { // Then we write the items to insert at the start for (index, variable) in variables_to_insert.iter().enumerate() { let target_index = self.brillig_context.make_usize_constant_instruction(index.into()); - self.store_variable_in_array(target_vector.pointer, target_index, *variable); + self.brillig_context.codegen_store_variable_in_array( + target_vector.pointer, + target_index, + *variable, + ); self.brillig_context.deallocate_single_addr(target_index); } @@ -239,7 +247,11 @@ impl<'block> BrilligBlock<'block> { target_index.address, BrilligBinaryOp::Add, ); - self.store_variable_in_array(target_vector.pointer, target_index, *variable); + self.brillig_context.codegen_store_variable_in_array( + target_vector.pointer, + target_index, + *variable, + ); self.brillig_context.deallocate_single_addr(target_index); } 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 5741089a497..8e52cf072b4 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 @@ -38,15 +38,28 @@ impl BrilligContext { self.stop_instruction(); } - /// This codegen will issue a loop do for (let iterator_register = 0; i < loop_bound; i += step) + /// This codegen will issue a loop for (let iterator_register = loop_start; i < loop_bound; i += step) /// The body of the loop should be issued by the caller in the on_iteration closure. - pub(crate) fn codegen_loop_with_bound_and_step( + pub(crate) fn codegen_for_loop( &mut self, + loop_start: Option, // Defaults to zero loop_bound: MemoryAddress, - step: MemoryAddress, + step: Option, // Defaults to 1 on_iteration: impl FnOnce(&mut BrilligContext, SingleAddrVariable), ) { - let iterator_register = self.make_usize_constant_instruction(0_u128.into()); + let iterator_register = if let Some(loop_start) = loop_start { + let iterator_register = SingleAddrVariable::new_usize(self.allocate_register()); + self.mov_instruction(iterator_register.address, loop_start); + iterator_register + } else { + self.make_usize_constant_instruction(0_usize.into()) + }; + + let step_register = if let Some(step) = step { + step + } else { + self.make_usize_constant_instruction(1_usize.into()).address + }; let (loop_section, loop_label) = self.reserve_next_section_label(); self.enter_section(loop_section); @@ -76,7 +89,7 @@ impl BrilligContext { // Add step to the iterator register self.memory_op_instruction( iterator_register.address, - step, + step_register, iterator_register.address, BrilligBinaryOp::Add, ); @@ -89,18 +102,20 @@ impl BrilligContext { // Deallocate our temporary registers self.deallocate_single_addr(iterator_less_than_iterations); self.deallocate_single_addr(iterator_register); + // Only deallocate step if we allocated it + if step.is_none() { + self.deallocate_register(step_register); + } } - /// This codegen will issue a loop that will iterate iteration_count times + /// This codegen will issue a loop that will iterate from 0 to iteration_count /// The body of the loop should be issued by the caller in the on_iteration closure. pub(crate) fn codegen_loop( &mut self, iteration_count: MemoryAddress, on_iteration: impl FnOnce(&mut BrilligContext, SingleAddrVariable), ) { - let step = self.make_usize_constant_instruction(1_u128.into()); - self.codegen_loop_with_bound_and_step(iteration_count, step.address, on_iteration); - self.deallocate_single_addr(step); + self.codegen_for_loop(None, iteration_count, None, on_iteration); } /// This codegen will issue an if-then branch that will check if the condition is true diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs index 81c1c3847b1..d20f736ee6d 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs @@ -112,6 +112,50 @@ impl BrilligContext { self.deallocate_register(index_of_element_in_memory); } + pub(crate) fn codegen_store_variable_in_array( + &mut self, + array_pointer: MemoryAddress, + index: SingleAddrVariable, + value_variable: BrilligVariable, + ) { + assert!(index.bit_size == BRILLIG_MEMORY_ADDRESSING_BIT_SIZE); + let final_pointer_register = self.allocate_register(); + self.memory_op_instruction( + array_pointer, + index.address, + final_pointer_register, + BrilligBinaryOp::Add, + ); + self.codegen_store_variable_in_pointer(final_pointer_register, value_variable); + self.deallocate_register(final_pointer_register); + } + + pub(crate) fn codegen_store_variable_in_pointer( + &mut self, + destination_pointer: MemoryAddress, + value_variable: BrilligVariable, + ) { + match value_variable { + BrilligVariable::SingleAddr(value_variable) => { + self.store_instruction(destination_pointer, value_variable.address); + } + BrilligVariable::BrilligArray(_) => { + let reference: MemoryAddress = self.allocate_register(); + self.codegen_allocate_array_reference(reference); + self.codegen_store_variable(reference, value_variable); + self.store_instruction(destination_pointer, reference); + self.deallocate_register(reference); + } + BrilligVariable::BrilligVector(_) => { + let reference = self.allocate_register(); + self.codegen_allocate_vector_reference(reference); + self.codegen_store_variable(reference, value_variable); + self.store_instruction(destination_pointer, reference); + self.deallocate_register(reference); + } + } + } + /// Copies the values of an array pointed by source with length stored in `num_elements_register` /// Into the array pointed by destination pub(crate) fn codegen_copy_array( From 0e6739d2d3ffef7d724cdadec80f0811e47e7eae Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 31 Jul 2024 02:04:00 +0000 Subject: [PATCH 11/35] git subrepo push --branch=master barretenberg subrepo: subdir: "barretenberg" merged: "c90da1e3b7" upstream: origin: "https://github.com/AztecProtocol/barretenberg" branch: "master" commit: "c90da1e3b7" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- barretenberg/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index bde308e1a62..110cc633364 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = 172dafd81d1a38fc7c05b7765b186b4620efaa5e - parent = e16452ab7640169e1235b91d598e3d90ba4ce57e + commit = c90da1e3b7eae0c5328081443fdfa8bfe1296445 + parent = dff2ffb81c8dab33567c1263cf412aacce89af66 method = merge cmdver = 0.4.6 From 7e36deb4d15a83b402c1d9a4efe29049e5597f36 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 31 Jul 2024 02:04:32 +0000 Subject: [PATCH 12/35] chore: replace relative paths to noir-protocol-circuits --- noir-projects/aztec-nr/aztec/Nargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/aztec/Nargo.toml b/noir-projects/aztec-nr/aztec/Nargo.toml index 7a1f1af5863..fb16331b042 100644 --- a/noir-projects/aztec-nr/aztec/Nargo.toml +++ b/noir-projects/aztec-nr/aztec/Nargo.toml @@ -5,4 +5,4 @@ compiler_version = ">=0.18.0" type = "lib" [dependencies] -protocol_types = { path = "../../noir-protocol-circuits/crates/types" } +protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.47.1", directory="noir-projects/noir-protocol-circuits/crates/types" } From 197a474590bde744b4cd66713bf2a8e8055a78dd Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 31 Jul 2024 02:04:32 +0000 Subject: [PATCH 13/35] git_subrepo.sh: Fix parent in .gitrepo file. [skip ci] --- noir-projects/aztec-nr/.gitrepo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index 0882445c0ba..5bf0d434c20 100644 --- a/noir-projects/aztec-nr/.gitrepo +++ b/noir-projects/aztec-nr/.gitrepo @@ -9,4 +9,4 @@ remote = https://github.com/AztecProtocol/aztec-nr commit = a5617c013fe4d27b1e49225474d0d1479993b618 method = merge cmdver = 0.4.6 - parent = 9f9f650bee89f25a20c78eb0dac96ebbf6d963db + parent = 69186245bcb0ccc5276f1ba7a5f6491778a3f18f From fee7efd7b21c406cd6e0816ed30a47161e368d13 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 31 Jul 2024 02:04:36 +0000 Subject: [PATCH 14/35] git subrepo push --branch=master noir-projects/aztec-nr subrepo: subdir: "noir-projects/aztec-nr" merged: "9a14f77b33" upstream: origin: "https://github.com/AztecProtocol/aztec-nr" branch: "master" commit: "9a14f77b33" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- noir-projects/aztec-nr/.gitrepo | 4 ++-- noir-projects/aztec-nr/aztec/Nargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index 5bf0d434c20..491a394e259 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 = a5617c013fe4d27b1e49225474d0d1479993b618 + commit = 9a14f77b330bb363b6d6661f229b858246eccebb method = merge cmdver = 0.4.6 - parent = 69186245bcb0ccc5276f1ba7a5f6491778a3f18f + parent = b5380c7e174c4724366cf0553b36674e0c904404 diff --git a/noir-projects/aztec-nr/aztec/Nargo.toml b/noir-projects/aztec-nr/aztec/Nargo.toml index fb16331b042..7a1f1af5863 100644 --- a/noir-projects/aztec-nr/aztec/Nargo.toml +++ b/noir-projects/aztec-nr/aztec/Nargo.toml @@ -5,4 +5,4 @@ compiler_version = ">=0.18.0" type = "lib" [dependencies] -protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.47.1", directory="noir-projects/noir-protocol-circuits/crates/types" } +protocol_types = { path = "../../noir-protocol-circuits/crates/types" } From f35786a34659a2691d9810517fa4e4e89b99111a Mon Sep 17 00:00:00 2001 From: ludamad Date: Wed, 31 Jul 2024 11:59:56 +0400 Subject: [PATCH 15/35] chore: lldb bb debugging helper script (#7627) Pretty-print tricky to debug field types --- barretenberg/README.md | 12 +++++++ barretenberg/cpp/scripts/lldb_format.py | 45 +++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 barretenberg/cpp/scripts/lldb_format.py diff --git a/barretenberg/README.md b/barretenberg/README.md index 916a39915d1..20280e991c8 100644 --- a/barretenberg/README.md +++ b/barretenberg/README.md @@ -349,3 +349,15 @@ Stack trace (most recent call last): 25: blocks.arithmetic.q_2().emplace_back(in.b_scaling); gate number4 ``` + + +### Improving LLDB Debugging + +It can be quite hard to make sense of field_t circuit values that indirectly reference their contents, and even plain field values that are typically in montgomery form. +In command-line LLDB or VSCode debug console, run: + +``` +command script import ~/aztec-packages/barretenberg/cpp/scripts/lldb_format.py +``` + +Now when you `print` things with e.g. `print bigfield_t.get_value()` or inspect in VSCode (if you opened the debug console and put in these commands) then you will get pretty-printing of these types. This can be expanded fairly easily with more types if needed. diff --git a/barretenberg/cpp/scripts/lldb_format.py b/barretenberg/cpp/scripts/lldb_format.py new file mode 100644 index 00000000000..f13f6323f3b --- /dev/null +++ b/barretenberg/cpp/scripts/lldb_format.py @@ -0,0 +1,45 @@ +import lldb + +# Define the bn254 modulus +N = 21888242871839275222246405745257275088548364400416034343698204186575808495617 + +# Define R as a power of 2 such that R > N (commonly used R for bn254 is 2^256) +R = 2**256 + +# Compute R inverse modulo N +R_inv = pow(R, -1, N) + +def montgomery_to_standard(montgomery_value): + # Convert from Montgomery form to standard representation + standard_value = (montgomery_value * R_inv) % N + return standard_value + +def montgomery_summary(valobj, internal_dict): + try: + data = valobj.GetChildMemberWithName('data') + data_0 = data.GetChildAtIndex(0).GetValueAsUnsigned() + data_1 = data.GetChildAtIndex(1).GetValueAsUnsigned() + data_2 = data.GetChildAtIndex(2).GetValueAsUnsigned() + data_3 = data.GetChildAtIndex(3).GetValueAsUnsigned() + + montgomery_value = ( + data_0 + + (data_1 << 64) + + (data_2 << 128) + + (data_3 << 192) + ) + + standard_value = montgomery_to_standard(montgomery_value) + return hex(standard_value) + except Exception as e: + return f"Error: {e}" + + +def montgomery_summary2(valobj, internal_dict): + return montgomery_summary(valobj.EvaluateExpression("get_value()"), internal_dict) + + +def __lldb_init_module(debugger, internal_dict): + debugger.HandleCommand("type summary add --python-function lldb_format.montgomery_summary bb::fr") + debugger.HandleCommand("type summary add --python-function lldb_format.montgomery_summary2 -x \"bb::stdlib::field_t.*\"") + print('The "formatter" command has been installed!') From 547874714ecf2693f147921afa8d72a3d2bd5e36 Mon Sep 17 00:00:00 2001 From: Lasse Herskind <16536249+LHerskind@users.noreply.github.com> Date: Wed, 31 Jul 2024 10:05:34 +0100 Subject: [PATCH 16/35] feat: Add log of blocks proposed and split pending/proven (#7635) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #7615. Adds a list of "BlockLog"s what we have within the 🐢 team talked about just as log for more generic consensus notation, and then have two values to address whereto the pending and the proven is accounted for. Add extra requirements to the `submitProof` function to ensure that proofs are actually linked to the blocks that are in the pending log. If all constraints are passed, will mark the block as proven (but not instantly move the tip forward). Introduce a `progressState` function which we execute at every proof submission that will try to progress the proven tip as far as possible (as long as the next block is proven we continue). This allow us to deal with non-sequential proving. - Also renames the fixtures to be block 1 and 2 instead of 0, 1 as it makes it much easier to reason about when the genesis block is actually already in the chain. - Changed a few wrongly ordered error messages. --- l1-contracts/foundry.toml | 4 +- l1-contracts/src/core/Rollup.sol | 125 ++++++++++++++-- l1-contracts/src/core/interfaces/IRollup.sol | 1 + l1-contracts/src/core/libraries/Errors.sol | 3 + l1-contracts/src/core/libraries/HeaderLib.sol | 4 +- l1-contracts/test/Rollup.t.sol | 134 ++++++++++++++--- l1-contracts/test/decoders/Decoders.t.sol | 4 +- l1-contracts/test/fixtures/empty_block_1.json | 22 +-- ...{empty_block_0.json => empty_block_2.json} | 22 +-- l1-contracts/test/fixtures/mixed_block_0.json | 112 --------------- l1-contracts/test/fixtures/mixed_block_1.json | 136 +++++++++--------- l1-contracts/test/fixtures/mixed_block_2.json | 112 +++++++++++++++ l1-contracts/test/sparta/Sparta.t.sol | 12 +- .../aztec.js/src/utils/cheat_codes.ts | 4 +- .../composed/integration_l1_publisher.test.ts | 4 +- 15 files changed, 453 insertions(+), 246 deletions(-) rename l1-contracts/test/fixtures/{empty_block_0.json => empty_block_2.json} (70%) delete mode 100644 l1-contracts/test/fixtures/mixed_block_0.json create mode 100644 l1-contracts/test/fixtures/mixed_block_2.json diff --git a/l1-contracts/foundry.toml b/l1-contracts/foundry.toml index ff36d4ac7bf..012bcf9cf06 100644 --- a/l1-contracts/foundry.toml +++ b/l1-contracts/foundry.toml @@ -11,10 +11,10 @@ remappings = [ # See more config options https://github.com/foundry-rs/foundry/tree/master/config fs_permissions = [ - {access = "read", path = "./test/fixtures/mixed_block_0.json"}, {access = "read", path = "./test/fixtures/mixed_block_1.json"}, - {access = "read", path = "./test/fixtures/empty_block_0.json"}, + {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"}, ] [fmt] diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index d6e7cd65559..d535d58c140 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -32,6 +32,11 @@ import {Leonidas} from "./sequencer_selection/Leonidas.sol"; * not giving a damn about gas costs. */ contract Rollup is Leonidas, IRollup { + struct BlockLog { + bytes32 archive; + bool isProven; + } + IRegistry public immutable REGISTRY; IAvailabilityOracle public immutable AVAILABILITY_ORACLE; IInbox public immutable INBOX; @@ -40,12 +45,22 @@ contract Rollup is Leonidas, IRollup { IERC20 public immutable GAS_TOKEN; IVerifier public verifier; - bytes32 public archive; // Root of the archive tree + uint256 public lastBlockTs; // Tracks the last time time was warped on L2 ("warp" is the testing cheatcode). // See https://github.com/AztecProtocol/aztec-packages/issues/1614 uint256 public lastWarpedBlockTs; + uint256 public pendingBlockCount; + uint256 public provenBlockCount; + + // @todo Validate assumption: + // Currently we assume that the archive root following a block is specific to the block + // e.g., changing any values in the block or header should in the end make its way to the archive + // + // More direct approach would be storing keccak256(header) as well + mapping(uint256 blockNumber => BlockLog log) public blocks; + bytes32 public vkTreeRoot; constructor( @@ -62,6 +77,11 @@ contract Rollup is Leonidas, IRollup { OUTBOX = new Outbox(address(this)); vkTreeRoot = _vkTreeRoot; VERSION = 1; + + // Genesis block + blocks[0] = BlockLog(bytes32(0), true); + pendingBlockCount = 1; + provenBlockCount = 1; } function setVerifier(address _verifier) external override(IRollup) { @@ -73,6 +93,18 @@ contract Rollup is Leonidas, IRollup { vkTreeRoot = _vkTreeRoot; } + function archive() public view returns (bytes32) { + return blocks[pendingBlockCount - 1].archive; + } + + function isBlockProven(uint256 _blockNumber) public view returns (bool) { + return blocks[_blockNumber].isProven; + } + + function archiveAt(uint256 _blockNumber) public view returns (bytes32) { + return blocks[_blockNumber].archive; + } + /** * @notice Process an incoming L2 block and progress the state * @param _header - The L2 block header @@ -88,14 +120,21 @@ contract Rollup is Leonidas, IRollup { // Decode and validate header HeaderLib.Header memory header = HeaderLib.decode(_header); - HeaderLib.validate(header, VERSION, lastBlockTs, archive); + HeaderLib.validate(header, VERSION, lastBlockTs, archive()); + + if (header.globalVariables.blockNumber != pendingBlockCount) { + revert Errors.Rollup__InvalidBlockNumber( + pendingBlockCount, header.globalVariables.blockNumber + ); + } // Check if the data is available using availability oracle (change availability oracle if you want a different DA layer) if (!AVAILABILITY_ORACLE.isAvailable(header.contentCommitment.txsEffectsHash)) { revert Errors.Rollup__UnavailableTxs(header.contentCommitment.txsEffectsHash); } - archive = _archive; + blocks[pendingBlockCount++] = BlockLog(_archive, false); + lastBlockTs = block.timestamp; bytes32 inHash = INBOX.consume(); @@ -124,6 +163,30 @@ contract Rollup is Leonidas, IRollup { process(_header, _archive, emptySignatures); } + /** + * @notice Submit a proof for a block in the pending chain + * + * @dev Will call `_progressState` to update the proven chain. Notice this have potentially + * unbounded gas consumption. + * + * @dev Will emit `L2ProofVerified` if the proof is valid + * + * @dev Will throw if: + * - The block number is past the pending chain + * - The last archive root of the header does not match the archive root of parent block + * - The archive root of the header does not match the archive root of the proposed block + * - The proof is invalid + * + * @dev We provide the `_archive` even if it could be read from storage itself because it allow for + * better error messages. Without passing it, we would just have a proof verification failure. + * + * @dev Following the `BlockLog` struct assumption + * + * @param _header - The header of the block (should match the block in the pending chain) + * @param _archive - The archive root of the block (should match the block in the pending chain) + * @param _aggregationObject - The aggregation object for the proof + * @param _proof - The proof to verify + */ function submitProof( bytes calldata _header, bytes32 _archive, @@ -133,6 +196,23 @@ contract Rollup is Leonidas, IRollup { ) external override(IRollup) { HeaderLib.Header memory header = HeaderLib.decode(_header); + if (header.globalVariables.blockNumber >= pendingBlockCount) { + revert Errors.Rollup__TryingToProveNonExistingBlock(); + } + + bytes32 expectedLastArchive = blocks[header.globalVariables.blockNumber - 1].archive; + bytes32 expectedArchive = blocks[header.globalVariables.blockNumber].archive; + + // We do it this way to provide better error messages than passing along the storage values + // TODO(#4148) Proper genesis state. If the state is empty, we allow anything for now. + if (expectedLastArchive != bytes32(0) && header.lastArchive.root != expectedLastArchive) { + revert Errors.Rollup__InvalidArchive(expectedLastArchive, header.lastArchive.root); + } + + if (_archive != expectedArchive) { + revert Errors.Rollup__InvalidProposedArchive(expectedArchive, _archive); + } + bytes32[] memory publicInputs = new bytes32[](4 + Constants.HEADER_LENGTH + Constants.AGGREGATION_OBJECT_LENGTH); // the archive tree root @@ -167,14 +247,41 @@ contract Rollup is Leonidas, IRollup { revert Errors.Rollup__InvalidProof(); } + blocks[header.globalVariables.blockNumber].isProven = true; + + _progressState(); + emit L2ProofVerified(header.globalVariables.blockNumber, _proverId); } - function _computePublicInputHash(bytes calldata _header, bytes32 _archive) - internal - pure - returns (bytes32) - { - return Hash.sha256ToField(bytes.concat(_header, _archive)); + /** + * @notice Progresses the state of the proven chain as far as possible + * + * @dev Emits `ProgressedState` if the state is progressed + * + * @dev Will continue along the pending chain as long as the blocks are proven + * stops at the first unproven block. + * + * @dev Have a potentially unbounded gas usage. @todo Will need a bounded version, such that it cannot be + * used as a DOS vector. + */ + function _progressState() internal { + if (pendingBlockCount == provenBlockCount) { + // We are already up to date + return; + } + + uint256 cachedProvenBlockCount = provenBlockCount; + + for (; cachedProvenBlockCount < pendingBlockCount; cachedProvenBlockCount++) { + if (!blocks[cachedProvenBlockCount].isProven) { + break; + } + } + + if (cachedProvenBlockCount > provenBlockCount) { + provenBlockCount = cachedProvenBlockCount; + emit ProgressedState(provenBlockCount, pendingBlockCount); + } } } diff --git a/l1-contracts/src/core/interfaces/IRollup.sol b/l1-contracts/src/core/interfaces/IRollup.sol index ff66b2efd6b..5186bf993cf 100644 --- a/l1-contracts/src/core/interfaces/IRollup.sol +++ b/l1-contracts/src/core/interfaces/IRollup.sol @@ -5,6 +5,7 @@ pragma solidity >=0.8.18; interface IRollup { event L2BlockProcessed(uint256 indexed blockNumber); event L2ProofVerified(uint256 indexed blockNumber, bytes32 indexed proverId); + event ProgressedState(uint256 provenBlockCount, uint256 pendingBlockCount); function process(bytes calldata _header, bytes32 _archive) external; diff --git a/l1-contracts/src/core/libraries/Errors.sol b/l1-contracts/src/core/libraries/Errors.sol index 8dd9e9ee114..4dbe4cec8d8 100644 --- a/l1-contracts/src/core/libraries/Errors.sol +++ b/l1-contracts/src/core/libraries/Errors.sol @@ -39,6 +39,9 @@ library Errors { // Rollup error Rollup__InvalidArchive(bytes32 expected, bytes32 actual); // 0xb682a40e + error Rollup__InvalidProposedArchive(bytes32 expected, bytes32 actual); // 0x32532e73 + error Rollup__InvalidBlockNumber(uint256 expected, uint256 actual); // 0xe5edf847 + error Rollup__TryingToProveNonExistingBlock(); // 0x34ef4954 error Rollup__InvalidInHash(bytes32 expected, bytes32 actual); // 0xcd6f4233 error Rollup__InvalidProof(); // 0xa5b2ba17 error Rollup__InvalidChainId(uint256 expected, uint256 actual); // 0x37b5bc12 diff --git a/l1-contracts/src/core/libraries/HeaderLib.sol b/l1-contracts/src/core/libraries/HeaderLib.sol index e461b1381f1..db2838d41af 100644 --- a/l1-contracts/src/core/libraries/HeaderLib.sol +++ b/l1-contracts/src/core/libraries/HeaderLib.sol @@ -118,11 +118,11 @@ library HeaderLib { view { if (block.chainid != _header.globalVariables.chainId) { - revert Errors.Rollup__InvalidChainId(_header.globalVariables.chainId, block.chainid); + revert Errors.Rollup__InvalidChainId(block.chainid, _header.globalVariables.chainId); } if (_header.globalVariables.version != _version) { - revert Errors.Rollup__InvalidVersion(_header.globalVariables.version, _version); + revert Errors.Rollup__InvalidVersion(_version, _header.globalVariables.version); } // block number already constrained by archive root check diff --git a/l1-contracts/test/Rollup.t.sol b/l1-contracts/test/Rollup.t.sol index a78e5da1a12..98e0ec24a35 100644 --- a/l1-contracts/test/Rollup.t.sol +++ b/l1-contracts/test/Rollup.t.sol @@ -53,26 +53,67 @@ contract RollupTest is DecoderBase { txsHelper = new TxsDecoderHelper(); } - function testMixedBlock() public { - _testBlock("mixed_block_0"); + function testMixedBlock(bool _toProve) public { + _testBlock("mixed_block_1", _toProve); + + assertEq(rollup.pendingBlockCount(), 2, "Invalid pending block count"); + assertEq(rollup.provenBlockCount(), _toProve ? 2 : 1, "Invalid proven block count"); } - function testConsecutiveMixedBlocks() public { - _testBlock("mixed_block_0"); - _testBlock("mixed_block_1"); + function testConsecutiveMixedBlocks(uint256 _blocksToProve) public { + uint256 toProve = bound(_blocksToProve, 0, 2); + + _testBlock("mixed_block_1", toProve > 0); + _testBlock("mixed_block_2", toProve > 1); + + assertEq(rollup.pendingBlockCount(), 3, "Invalid pending block count"); + assertEq(rollup.provenBlockCount(), 1 + toProve, "Invalid proven block count"); } - function testEmptyBlock() public { - _testBlock("empty_block_0"); + function testConsecutiveMixedBlocksNonSequentialProof() public { + _testBlock("mixed_block_1", false); + _testBlock("mixed_block_2", true); + + assertTrue(rollup.isBlockProven(2), "Block 2 is not proven"); + + assertEq(rollup.pendingBlockCount(), 3, "Invalid pending block count"); + assertEq(rollup.provenBlockCount(), 1, "Invalid proven block count"); } - function testConsecutiveEmptyBlocks() public { - _testBlock("empty_block_0"); - _testBlock("empty_block_1"); + function testEmptyBlock(bool _toProve) public { + _testBlock("empty_block_1", _toProve); + assertEq(rollup.pendingBlockCount(), 2, "Invalid pending block count"); + assertEq(rollup.provenBlockCount(), _toProve ? 2 : 1, "Invalid proven block count"); + } + + function testConsecutiveEmptyBlocks(uint256 _blocksToProve) public { + uint256 toProve = bound(_blocksToProve, 0, 2); + _testBlock("empty_block_1", toProve > 0); + _testBlock("empty_block_2", toProve > 1); + + assertEq(rollup.pendingBlockCount(), 3, "Invalid pending block count"); + assertEq(rollup.provenBlockCount(), 1 + toProve, "Invalid proven block count"); + } + + function testRevertInvalidBlockNumber() public { + DecoderBase.Data memory data = load("empty_block_1").block; + bytes memory header = data.header; + bytes32 archive = data.archive; + bytes memory body = data.body; + + assembly { + // TODO: Hardcoding offsets in the middle of tests is annoying to say the least. + mstore(add(header, add(0x20, 0x0174)), 0x420) + } + + availabilityOracle.publish(body); + + vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidBlockNumber.selector, 1, 0x420)); + rollup.process(header, archive); } function testRevertInvalidChainId() public { - DecoderBase.Data memory data = load("empty_block_0").block; + DecoderBase.Data memory data = load("empty_block_1").block; bytes memory header = data.header; bytes32 archive = data.archive; bytes memory body = data.body; @@ -84,12 +125,12 @@ contract RollupTest is DecoderBase { availabilityOracle.publish(body); - vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidChainId.selector, 0x420, 31337)); + vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidChainId.selector, 31337, 0x420)); rollup.process(header, archive); } function testRevertInvalidVersion() public { - DecoderBase.Data memory data = load("empty_block_0").block; + DecoderBase.Data memory data = load("empty_block_1").block; bytes memory header = data.header; bytes32 archive = data.archive; bytes memory body = data.body; @@ -100,12 +141,12 @@ contract RollupTest is DecoderBase { availabilityOracle.publish(body); - vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidVersion.selector, 0x420, 1)); + vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidVersion.selector, 1, 0x420)); rollup.process(header, archive); } function testRevertTimestampInFuture() public { - DecoderBase.Data memory data = load("empty_block_0").block; + DecoderBase.Data memory data = load("empty_block_1").block; bytes memory header = data.header; bytes32 archive = data.archive; bytes memory body = data.body; @@ -122,14 +163,14 @@ contract RollupTest is DecoderBase { } function testRevertTimestampTooOld() public { - DecoderBase.Data memory data = load("empty_block_0").block; + DecoderBase.Data memory data = load("empty_block_1").block; bytes memory header = data.header; bytes32 archive = data.archive; bytes memory body = data.body; // Beware of the store slot below, if the test is failing might be because of the slot // We overwrite `lastBlockTs` in the rollup - vm.store(address(rollup), bytes32(uint256(7)), bytes32(uint256(block.timestamp))); + vm.store(address(rollup), bytes32(uint256(6)), bytes32(uint256(block.timestamp))); availabilityOracle.publish(body); @@ -137,7 +178,54 @@ contract RollupTest is DecoderBase { rollup.process(header, archive); } - function _testBlock(string memory name) public { + function testSubmitProofNonExistantBlock() public { + DecoderBase.Data memory data = load("empty_block_1").block; + bytes memory header = data.header; + bytes32 archive = data.archive; + + vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__TryingToProveNonExistingBlock.selector)); + rollup.submitProof(header, archive, bytes32(0), "", ""); + } + + function testSubmitProofInvalidArchive() public { + _testBlock("empty_block_1", false); + _testBlock("empty_block_2", false); + + DecoderBase.Data memory data = load("empty_block_2").block; + bytes memory header = data.header; + bytes32 archive = data.archive; + + // Update the lastArchive value in the header and then submit a proof + assembly { + mstore(add(header, add(0x20, 0x00)), 0xdeadbeef) + } + + vm.expectRevert( + abi.encodeWithSelector( + Errors.Rollup__InvalidArchive.selector, rollup.archiveAt(1), 0xdeadbeef + ) + ); + rollup.submitProof(header, archive, bytes32(0), "", ""); + } + + function testSubmitProofInvalidProposedArchive() public { + DecoderBase.Data memory data = load("empty_block_1").block; + bytes memory header = data.header; + bytes32 archive = data.archive; + bytes memory body = data.body; + + availabilityOracle.publish(body); + rollup.process(header, archive); + + bytes32 badArchive = keccak256(abi.encode(archive)); + + vm.expectRevert( + abi.encodeWithSelector(Errors.Rollup__InvalidProposedArchive.selector, archive, badArchive) + ); + rollup.submitProof(header, badArchive, bytes32(0), "", ""); + } + + function _testBlock(string memory name, bool _submitProof) public { DecoderBase.Full memory full = load(name); bytes memory header = full.block.header; bytes32 archive = full.block.archive; @@ -153,9 +241,17 @@ contract RollupTest is DecoderBase { uint256 toConsume = inbox.toConsume(); - vm.record(); rollup.process(header, archive); + if (_submitProof) { + rollup.submitProof(header, archive, bytes32(0), "", ""); + + assertTrue( + rollup.isBlockProven(full.block.decodedHeader.globalVariables.blockNumber), + "Block not proven" + ); + } + assertEq(inbox.toConsume(), toConsume + 1, "Message subtree not consumed"); bytes32 l2ToL1MessageTreeRoot; diff --git a/l1-contracts/test/decoders/Decoders.t.sol b/l1-contracts/test/decoders/Decoders.t.sol index a3f6c3958ca..b82f368aeb9 100644 --- a/l1-contracts/test/decoders/Decoders.t.sol +++ b/l1-contracts/test/decoders/Decoders.t.sol @@ -27,10 +27,10 @@ contract DecodersTest is DecoderBase { } function testDecodeBlocks() public { - _testDecodeBlock("mixed_block_0"); _testDecodeBlock("mixed_block_1"); - _testDecodeBlock("empty_block_0"); + _testDecodeBlock("mixed_block_2"); _testDecodeBlock("empty_block_1"); + _testDecodeBlock("empty_block_2"); } function _testDecodeBlock(string memory name) public virtual { diff --git a/l1-contracts/test/fixtures/empty_block_1.json b/l1-contracts/test/fixtures/empty_block_1.json index a0706e4b24f..8698dda56e8 100644 --- a/l1-contracts/test/fixtures/empty_block_1.json +++ b/l1-contracts/test/fixtures/empty_block_1.json @@ -8,7 +8,7 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x0f049707f5cee10d833aea2adf93e1e3462eaa5b328576342fbea7837195c91a", + "archive": "0x062d0b928c3e1fa5529032c8c663c4b3b1a359d03943f20667b02d87bf71a7ad", "body": "0x00000000", "txsEffectsHash": "0x00d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf2", "decodedHeader": { @@ -19,9 +19,9 @@ "txsEffectsHash": "0x00d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf2" }, "globalVariables": { - "blockNumber": 2, + "blockNumber": 1, "chainId": 31337, - "timestamp": 1719332523, + "timestamp": 0, "version": 1, "coinbase": "0x6adca08f06cc255a12c609d284c5861c1cad740c", "feeRecipient": "0x09d7dc61a2ee0c764bc8f5954500c7b43d5422958e67d20144b3e738b04dfc07", @@ -31,32 +31,32 @@ } }, "lastArchive": { - "nextAvailableLeafIndex": 2, - "root": "0x062d0b928c3e1fa5529032c8c663c4b3b1a359d03943f20667b02d87bf71a7ad" + "nextAvailableLeafIndex": 1, + "root": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b6" }, "stateReference": { "l1ToL2MessageTree": { - "nextAvailableLeafIndex": 32, + "nextAvailableLeafIndex": 16, "root": "0x1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80" }, "partialStateReference": { "noteHashTree": { - "nextAvailableLeafIndex": 256, + "nextAvailableLeafIndex": 128, "root": "0x16642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb" }, "nullifierTree": { - "nextAvailableLeafIndex": 384, + "nextAvailableLeafIndex": 256, "root": "0x0bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278" }, "publicDataTree": { - "nextAvailableLeafIndex": 384, + "nextAvailableLeafIndex": 256, "root": "0x021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4" } } } }, - "header": "0x062d0b928c3e1fa5529032c8c663c4b3b1a359d03943f20667b02d87bf71a7ad00000002000000000000000000000000000000000000000000000000000000000000000200d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000180021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000667aeeab6adca08f06cc255a12c609d284c5861c1cad740c09d7dc61a2ee0c764bc8f5954500c7b43d5422958e67d20144b3e738b04dfc07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00d8e0d4aa3b09294fa37c11ca7f356dc35c160e2ec9a95363a07dca826e1397", + "header": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b600000001000000000000000000000000000000000000000000000000000000000000000200d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000100021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006adca08f06cc255a12c609d284c5861c1cad740c09d7dc61a2ee0c764bc8f5954500c7b43d5422958e67d20144b3e738b04dfc07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x002aa4bb5409ae75e705b167d45ba569055b2ae62c67c1608f4cf17ac5129ad6", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/empty_block_0.json b/l1-contracts/test/fixtures/empty_block_2.json similarity index 70% rename from l1-contracts/test/fixtures/empty_block_0.json rename to l1-contracts/test/fixtures/empty_block_2.json index 8698dda56e8..a0706e4b24f 100644 --- a/l1-contracts/test/fixtures/empty_block_0.json +++ b/l1-contracts/test/fixtures/empty_block_2.json @@ -8,7 +8,7 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x062d0b928c3e1fa5529032c8c663c4b3b1a359d03943f20667b02d87bf71a7ad", + "archive": "0x0f049707f5cee10d833aea2adf93e1e3462eaa5b328576342fbea7837195c91a", "body": "0x00000000", "txsEffectsHash": "0x00d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf2", "decodedHeader": { @@ -19,9 +19,9 @@ "txsEffectsHash": "0x00d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf2" }, "globalVariables": { - "blockNumber": 1, + "blockNumber": 2, "chainId": 31337, - "timestamp": 0, + "timestamp": 1719332523, "version": 1, "coinbase": "0x6adca08f06cc255a12c609d284c5861c1cad740c", "feeRecipient": "0x09d7dc61a2ee0c764bc8f5954500c7b43d5422958e67d20144b3e738b04dfc07", @@ -31,32 +31,32 @@ } }, "lastArchive": { - "nextAvailableLeafIndex": 1, - "root": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b6" + "nextAvailableLeafIndex": 2, + "root": "0x062d0b928c3e1fa5529032c8c663c4b3b1a359d03943f20667b02d87bf71a7ad" }, "stateReference": { "l1ToL2MessageTree": { - "nextAvailableLeafIndex": 16, + "nextAvailableLeafIndex": 32, "root": "0x1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80" }, "partialStateReference": { "noteHashTree": { - "nextAvailableLeafIndex": 128, + "nextAvailableLeafIndex": 256, "root": "0x16642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb" }, "nullifierTree": { - "nextAvailableLeafIndex": 256, + "nextAvailableLeafIndex": 384, "root": "0x0bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278" }, "publicDataTree": { - "nextAvailableLeafIndex": 256, + "nextAvailableLeafIndex": 384, "root": "0x021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4" } } } }, - "header": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b600000001000000000000000000000000000000000000000000000000000000000000000200d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000100021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006adca08f06cc255a12c609d284c5861c1cad740c09d7dc61a2ee0c764bc8f5954500c7b43d5422958e67d20144b3e738b04dfc07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x002aa4bb5409ae75e705b167d45ba569055b2ae62c67c1608f4cf17ac5129ad6", + "header": "0x062d0b928c3e1fa5529032c8c663c4b3b1a359d03943f20667b02d87bf71a7ad00000002000000000000000000000000000000000000000000000000000000000000000200d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000180021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000667aeeab6adca08f06cc255a12c609d284c5861c1cad740c09d7dc61a2ee0c764bc8f5954500c7b43d5422958e67d20144b3e738b04dfc07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00d8e0d4aa3b09294fa37c11ca7f356dc35c160e2ec9a95363a07dca826e1397", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_0.json b/l1-contracts/test/fixtures/mixed_block_0.json deleted file mode 100644 index f9b76ee0dec..00000000000 --- a/l1-contracts/test/fixtures/mixed_block_0.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "populate": { - "l1ToL2Content": [ - "0x0000000000000000000000000000000000000000000000000000000000000401", - "0x0000000000000000000000000000000000000000000000000000000000000402", - "0x0000000000000000000000000000000000000000000000000000000000000403", - "0x0000000000000000000000000000000000000000000000000000000000000404", - "0x0000000000000000000000000000000000000000000000000000000000000405", - "0x0000000000000000000000000000000000000000000000000000000000000406", - "0x0000000000000000000000000000000000000000000000000000000000000407", - "0x0000000000000000000000000000000000000000000000000000000000000408", - "0x0000000000000000000000000000000000000000000000000000000000000409", - "0x000000000000000000000000000000000000000000000000000000000000040a", - "0x000000000000000000000000000000000000000000000000000000000000040b", - "0x000000000000000000000000000000000000000000000000000000000000040c", - "0x000000000000000000000000000000000000000000000000000000000000040d", - "0x000000000000000000000000000000000000000000000000000000000000040e", - "0x000000000000000000000000000000000000000000000000000000000000040f", - "0x0000000000000000000000000000000000000000000000000000000000000410" - ], - "recipient": "0x1647b194c649f5dd01d7c832f89b0f496043c9150797923ea89e93d5ac619a93", - "sender": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc" - }, - "messages": { - "l2ToL1Messages": [ - "0x0000000000000000000000000000000000000000000000000000000000000340", - "0x0000000000000000000000000000000000000000000000000000000000000341", - "0x0000000000000000000000000000000000000000000000000000000000000342", - "0x0000000000000000000000000000000000000000000000000000000000000343", - "0x0000000000000000000000000000000000000000000000000000000000000344", - "0x0000000000000000000000000000000000000000000000000000000000000345", - "0x0000000000000000000000000000000000000000000000000000000000000346", - "0x0000000000000000000000000000000000000000000000000000000000000347", - "0x0000000000000000000000000000000000000000000000000000000000000380", - "0x0000000000000000000000000000000000000000000000000000000000000381", - "0x0000000000000000000000000000000000000000000000000000000000000382", - "0x0000000000000000000000000000000000000000000000000000000000000383", - "0x0000000000000000000000000000000000000000000000000000000000000384", - "0x0000000000000000000000000000000000000000000000000000000000000385", - "0x0000000000000000000000000000000000000000000000000000000000000386", - "0x0000000000000000000000000000000000000000000000000000000000000387", - "0x00000000000000000000000000000000000000000000000000000000000003c0", - "0x00000000000000000000000000000000000000000000000000000000000003c1", - "0x00000000000000000000000000000000000000000000000000000000000003c2", - "0x00000000000000000000000000000000000000000000000000000000000003c3", - "0x00000000000000000000000000000000000000000000000000000000000003c4", - "0x00000000000000000000000000000000000000000000000000000000000003c5", - "0x00000000000000000000000000000000000000000000000000000000000003c6", - "0x00000000000000000000000000000000000000000000000000000000000003c7", - "0x0000000000000000000000000000000000000000000000000000000000000400", - "0x0000000000000000000000000000000000000000000000000000000000000401", - "0x0000000000000000000000000000000000000000000000000000000000000402", - "0x0000000000000000000000000000000000000000000000000000000000000403", - "0x0000000000000000000000000000000000000000000000000000000000000404", - "0x0000000000000000000000000000000000000000000000000000000000000405", - "0x0000000000000000000000000000000000000000000000000000000000000406", - "0x0000000000000000000000000000000000000000000000000000000000000407" - ] - }, - "block": { - "archive": "0x1caafe747155b2a72a6f44744dc68fa9d6c3b605e5dc661383c5a202dd7ee7c8", - "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f3f0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e08000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003410000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000034300000000000000000000000000000000000000000000000000000000000003440000000000000000000000000000000000000000000000000000000000000345000000000000000000000000000000000000000000000000000000000000034600000000000000000000000000000000000000000000000000000000000003473f0000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000551000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000552000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005560000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000055700000000000000000000000000000000000000000000000000000000000005610000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000056200000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000566000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000567000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000561000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000562000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005660000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000056700000000000000000000000000000000000000000000000000000000000005710000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000057200000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000576000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000577000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000571000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000572000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000057f00000000000000000000000000000000000000000000000000000000000005760000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000057700000000000000000000000000000000000000000000000000000000000005810000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000058200000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000586000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000587000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001bf3f0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be08000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003810000000000000000000000000000000000000000000000000000000000000382000000000000000000000000000000000000000000000000000000000000038300000000000000000000000000000000000000000000000000000000000003840000000000000000000000000000000000000000000000000000000000000385000000000000000000000000000000000000000000000000000000000000038600000000000000000000000000000000000000000000000000000000000003873f0000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005990000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000059a0000000000000000000000000000000000000000000000000000000000000591000000000000000000000000000000000000000000000000000000000000059b0000000000000000000000000000000000000000000000000000000000000592000000000000000000000000000000000000000000000000000000000000059c0000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000059d0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000059e0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000059f000000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000059700000000000000000000000000000000000000000000000000000000000005a1000000000000000000000000000000000000000000000000000000000000059800000000000000000000000000000000000000000000000000000000000005a2000000000000000000000000000000000000000000000000000000000000059900000000000000000000000000000000000000000000000000000000000005a3000000000000000000000000000000000000000000000000000000000000059a00000000000000000000000000000000000000000000000000000000000005a4000000000000000000000000000000000000000000000000000000000000059b00000000000000000000000000000000000000000000000000000000000005a5000000000000000000000000000000000000000000000000000000000000059c00000000000000000000000000000000000000000000000000000000000005a6000000000000000000000000000000000000000000000000000000000000059d00000000000000000000000000000000000000000000000000000000000005a7000000000000000000000000000000000000000000000000000000000000059e00000000000000000000000000000000000000000000000000000000000005a8000000000000000000000000000000000000000000000000000000000000059f00000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005a100000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005a200000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005a300000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005a400000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005a500000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005a600000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005a700000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005a800000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005bf00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001ff3f00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe0800000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c73f00000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005f600000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005f700000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005f800000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005f900000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005fa00000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005fb00000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005fc00000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005fd00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005fe00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ff00000000000000000000000000000000000000000000000000000000000005f6000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005f7000000000000000000000000000000000000000000000000000000000000060100000000000000000000000000000000000000000000000000000000000005f8000000000000000000000000000000000000000000000000000000000000060200000000000000000000000000000000000000000000000000000000000005f9000000000000000000000000000000000000000000000000000000000000060300000000000000000000000000000000000000000000000000000000000005fa000000000000000000000000000000000000000000000000000000000000060400000000000000000000000000000000000000000000000000000000000005fb000000000000000000000000000000000000000000000000000000000000060500000000000000000000000000000000000000000000000000000000000005fc000000000000000000000000000000000000000000000000000000000000060600000000000000000000000000000000000000000000000000000000000005fd000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000005fe0000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002320000000000000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002350000000000000000000000000000000000000000000000000000000000000236000000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002380000000000000000000000000000000000000000000000000000000000000239000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023f3f0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e08000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004010000000000000000000000000000000000000000000000000000000000000402000000000000000000000000000000000000000000000000000000000000040300000000000000000000000000000000000000000000000000000000000004040000000000000000000000000000000000000000000000000000000000000405000000000000000000000000000000000000000000000000000000000000040600000000000000000000000000000000000000000000000000000000000004073f0000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000611000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000612000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006160000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061700000000000000000000000000000000000000000000000000000000000006210000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000062200000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000626000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000621000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000622000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006260000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062700000000000000000000000000000000000000000000000000000000000006310000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000063200000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000636000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000637000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000631000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000632000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000063f00000000000000000000000000000000000000000000000000000000000006360000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000063700000000000000000000000000000000000000000000000000000000000006410000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000064200000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000646000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000647000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "txsEffectsHash": "0x006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a3", - "decodedHeader": { - "contentCommitment": { - "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", - "outHash": "0x0071556a0e9f403540d572c98a081d21b325e7c802b8b3baf54f3d56fecb2230", - "numTxs": 4, - "txsEffectsHash": "0x006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a3" - }, - "globalVariables": { - "blockNumber": 1, - "chainId": 31337, - "timestamp": 0, - "version": 1, - "coinbase": "0x38e74ed15dd5ab05fff041b5037372cce88aa7e9", - "feeRecipient": "0x1bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be", - "gasFees": { - "feePerDaGas": 0, - "feePerL2Gas": 0 - } - }, - "lastArchive": { - "nextAvailableLeafIndex": 1, - "root": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b6" - }, - "stateReference": { - "l1ToL2MessageTree": { - "nextAvailableLeafIndex": 16, - "root": "0x1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80" - }, - "partialStateReference": { - "noteHashTree": { - "nextAvailableLeafIndex": 256, - "root": "0x0d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e" - }, - "nullifierTree": { - "nextAvailableLeafIndex": 384, - "root": "0x01c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a2" - }, - "publicDataTree": { - "nextAvailableLeafIndex": 384, - "root": "0x2f72d4fe80aa0b43708532e4fb05cdf574bfd36c8c6bba1ff4ec3c6e0ffc9b3a" - } - } - } - }, - "header": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b6000000010000000000000000000000000000000000000000000000000000000000000004006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a300089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0071556a0e9f403540d572c98a081d21b325e7c802b8b3baf54f3d56fecb22301864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000100d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e0000010001c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a2000001802f72d4fe80aa0b43708532e4fb05cdf574bfd36c8c6bba1ff4ec3c6e0ffc9b3a000001800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000038e74ed15dd5ab05fff041b5037372cce88aa7e91bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x0086d49b8b947a0b784ea6e86697292895d7f54a547fa954ab820140274340d4", - "numTxs": 4 - } -} \ 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 b3d023bdcda..f9b76ee0dec 100644 --- a/l1-contracts/test/fixtures/mixed_block_1.json +++ b/l1-contracts/test/fixtures/mixed_block_1.json @@ -1,77 +1,77 @@ { "populate": { "l1ToL2Content": [ - "0x0000000000000000000000000000000000000000000000000000000000000481", - "0x0000000000000000000000000000000000000000000000000000000000000482", - "0x0000000000000000000000000000000000000000000000000000000000000483", - "0x0000000000000000000000000000000000000000000000000000000000000484", - "0x0000000000000000000000000000000000000000000000000000000000000485", - "0x0000000000000000000000000000000000000000000000000000000000000486", - "0x0000000000000000000000000000000000000000000000000000000000000487", - "0x0000000000000000000000000000000000000000000000000000000000000488", - "0x0000000000000000000000000000000000000000000000000000000000000489", - "0x000000000000000000000000000000000000000000000000000000000000048a", - "0x000000000000000000000000000000000000000000000000000000000000048b", - "0x000000000000000000000000000000000000000000000000000000000000048c", - "0x000000000000000000000000000000000000000000000000000000000000048d", - "0x000000000000000000000000000000000000000000000000000000000000048e", - "0x000000000000000000000000000000000000000000000000000000000000048f", - "0x0000000000000000000000000000000000000000000000000000000000000490" + "0x0000000000000000000000000000000000000000000000000000000000000401", + "0x0000000000000000000000000000000000000000000000000000000000000402", + "0x0000000000000000000000000000000000000000000000000000000000000403", + "0x0000000000000000000000000000000000000000000000000000000000000404", + "0x0000000000000000000000000000000000000000000000000000000000000405", + "0x0000000000000000000000000000000000000000000000000000000000000406", + "0x0000000000000000000000000000000000000000000000000000000000000407", + "0x0000000000000000000000000000000000000000000000000000000000000408", + "0x0000000000000000000000000000000000000000000000000000000000000409", + "0x000000000000000000000000000000000000000000000000000000000000040a", + "0x000000000000000000000000000000000000000000000000000000000000040b", + "0x000000000000000000000000000000000000000000000000000000000000040c", + "0x000000000000000000000000000000000000000000000000000000000000040d", + "0x000000000000000000000000000000000000000000000000000000000000040e", + "0x000000000000000000000000000000000000000000000000000000000000040f", + "0x0000000000000000000000000000000000000000000000000000000000000410" ], "recipient": "0x1647b194c649f5dd01d7c832f89b0f496043c9150797923ea89e93d5ac619a93", "sender": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc" }, "messages": { "l2ToL1Messages": [ - "0x0000000000000000000000000000000000000000000000000000000000000440", - "0x0000000000000000000000000000000000000000000000000000000000000441", - "0x0000000000000000000000000000000000000000000000000000000000000442", - "0x0000000000000000000000000000000000000000000000000000000000000443", - "0x0000000000000000000000000000000000000000000000000000000000000444", - "0x0000000000000000000000000000000000000000000000000000000000000445", - "0x0000000000000000000000000000000000000000000000000000000000000446", - "0x0000000000000000000000000000000000000000000000000000000000000447", - "0x0000000000000000000000000000000000000000000000000000000000000480", - "0x0000000000000000000000000000000000000000000000000000000000000481", - "0x0000000000000000000000000000000000000000000000000000000000000482", - "0x0000000000000000000000000000000000000000000000000000000000000483", - "0x0000000000000000000000000000000000000000000000000000000000000484", - "0x0000000000000000000000000000000000000000000000000000000000000485", - "0x0000000000000000000000000000000000000000000000000000000000000486", - "0x0000000000000000000000000000000000000000000000000000000000000487", - "0x00000000000000000000000000000000000000000000000000000000000004c0", - "0x00000000000000000000000000000000000000000000000000000000000004c1", - "0x00000000000000000000000000000000000000000000000000000000000004c2", - "0x00000000000000000000000000000000000000000000000000000000000004c3", - "0x00000000000000000000000000000000000000000000000000000000000004c4", - "0x00000000000000000000000000000000000000000000000000000000000004c5", - "0x00000000000000000000000000000000000000000000000000000000000004c6", - "0x00000000000000000000000000000000000000000000000000000000000004c7", - "0x0000000000000000000000000000000000000000000000000000000000000500", - "0x0000000000000000000000000000000000000000000000000000000000000501", - "0x0000000000000000000000000000000000000000000000000000000000000502", - "0x0000000000000000000000000000000000000000000000000000000000000503", - "0x0000000000000000000000000000000000000000000000000000000000000504", - "0x0000000000000000000000000000000000000000000000000000000000000505", - "0x0000000000000000000000000000000000000000000000000000000000000506", - "0x0000000000000000000000000000000000000000000000000000000000000507" + "0x0000000000000000000000000000000000000000000000000000000000000340", + "0x0000000000000000000000000000000000000000000000000000000000000341", + "0x0000000000000000000000000000000000000000000000000000000000000342", + "0x0000000000000000000000000000000000000000000000000000000000000343", + "0x0000000000000000000000000000000000000000000000000000000000000344", + "0x0000000000000000000000000000000000000000000000000000000000000345", + "0x0000000000000000000000000000000000000000000000000000000000000346", + "0x0000000000000000000000000000000000000000000000000000000000000347", + "0x0000000000000000000000000000000000000000000000000000000000000380", + "0x0000000000000000000000000000000000000000000000000000000000000381", + "0x0000000000000000000000000000000000000000000000000000000000000382", + "0x0000000000000000000000000000000000000000000000000000000000000383", + "0x0000000000000000000000000000000000000000000000000000000000000384", + "0x0000000000000000000000000000000000000000000000000000000000000385", + "0x0000000000000000000000000000000000000000000000000000000000000386", + "0x0000000000000000000000000000000000000000000000000000000000000387", + "0x00000000000000000000000000000000000000000000000000000000000003c0", + "0x00000000000000000000000000000000000000000000000000000000000003c1", + "0x00000000000000000000000000000000000000000000000000000000000003c2", + "0x00000000000000000000000000000000000000000000000000000000000003c3", + "0x00000000000000000000000000000000000000000000000000000000000003c4", + "0x00000000000000000000000000000000000000000000000000000000000003c5", + "0x00000000000000000000000000000000000000000000000000000000000003c6", + "0x00000000000000000000000000000000000000000000000000000000000003c7", + "0x0000000000000000000000000000000000000000000000000000000000000400", + "0x0000000000000000000000000000000000000000000000000000000000000401", + "0x0000000000000000000000000000000000000000000000000000000000000402", + "0x0000000000000000000000000000000000000000000000000000000000000403", + "0x0000000000000000000000000000000000000000000000000000000000000404", + "0x0000000000000000000000000000000000000000000000000000000000000405", + "0x0000000000000000000000000000000000000000000000000000000000000406", + "0x0000000000000000000000000000000000000000000000000000000000000407" ] }, "block": { - "archive": "0x0796e4e2dcd2e9d783732a42084fd8fd79acd7bbc7e9d511f5d0c59d4de6aa80", - "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027f3f0000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f0000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003720000000000000000000000000000000000000000000000000000000000000373000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003750000000000000000000000000000000000000000000000000000000000000376000000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003780000000000000000000000000000000000000000000000000000000000000379000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037e08000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004410000000000000000000000000000000000000000000000000000000000000442000000000000000000000000000000000000000000000000000000000000044300000000000000000000000000000000000000000000000000000000000004440000000000000000000000000000000000000000000000000000000000000445000000000000000000000000000000000000000000000000000000000000044600000000000000000000000000000000000000000000000000000000000004473f0000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000651000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000652000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006560000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000065700000000000000000000000000000000000000000000000000000000000006610000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000066200000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000666000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000667000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000661000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000662000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006660000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000066700000000000000000000000000000000000000000000000000000000000006710000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000067200000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000676000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000677000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000671000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000672000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000067f00000000000000000000000000000000000000000000000000000000000006760000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000067700000000000000000000000000000000000000000000000000000000000006810000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000068200000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000686000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000687000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002bf3f0000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003be08000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000004810000000000000000000000000000000000000000000000000000000000000482000000000000000000000000000000000000000000000000000000000000048300000000000000000000000000000000000000000000000000000000000004840000000000000000000000000000000000000000000000000000000000000485000000000000000000000000000000000000000000000000000000000000048600000000000000000000000000000000000000000000000000000000000004873f0000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006990000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000069a0000000000000000000000000000000000000000000000000000000000000691000000000000000000000000000000000000000000000000000000000000069b0000000000000000000000000000000000000000000000000000000000000692000000000000000000000000000000000000000000000000000000000000069c0000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000069d0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000069e0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000069f000000000000000000000000000000000000000000000000000000000000069600000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000069700000000000000000000000000000000000000000000000000000000000006a1000000000000000000000000000000000000000000000000000000000000069800000000000000000000000000000000000000000000000000000000000006a2000000000000000000000000000000000000000000000000000000000000069900000000000000000000000000000000000000000000000000000000000006a3000000000000000000000000000000000000000000000000000000000000069a00000000000000000000000000000000000000000000000000000000000006a4000000000000000000000000000000000000000000000000000000000000069b00000000000000000000000000000000000000000000000000000000000006a5000000000000000000000000000000000000000000000000000000000000069c00000000000000000000000000000000000000000000000000000000000006a6000000000000000000000000000000000000000000000000000000000000069d00000000000000000000000000000000000000000000000000000000000006a7000000000000000000000000000000000000000000000000000000000000069e00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000069f00000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006a100000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006a200000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006a300000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006a400000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006a500000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006a600000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006a700000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006a800000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006bf00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002ff3f00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f700000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003f900000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fb00000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fd00000000000000000000000000000000000000000000000000000000000003fe0800000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c100000000000000000000000000000000000000000000000000000000000004c200000000000000000000000000000000000000000000000000000000000004c300000000000000000000000000000000000000000000000000000000000004c400000000000000000000000000000000000000000000000000000000000004c500000000000000000000000000000000000000000000000000000000000004c600000000000000000000000000000000000000000000000000000000000004c73f00000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006f600000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006f700000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006f800000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006f900000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006fa00000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006fb00000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006fc00000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006fd00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006fe00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ff00000000000000000000000000000000000000000000000000000000000006f6000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000006f7000000000000000000000000000000000000000000000000000000000000070100000000000000000000000000000000000000000000000000000000000006f8000000000000000000000000000000000000000000000000000000000000070200000000000000000000000000000000000000000000000000000000000006f9000000000000000000000000000000000000000000000000000000000000070300000000000000000000000000000000000000000000000000000000000006fa000000000000000000000000000000000000000000000000000000000000070400000000000000000000000000000000000000000000000000000000000006fb000000000000000000000000000000000000000000000000000000000000070500000000000000000000000000000000000000000000000000000000000006fc000000000000000000000000000000000000000000000000000000000000070600000000000000000000000000000000000000000000000000000000000006fd000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000006fe0000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033f3f0000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f0000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000043100000000000000000000000000000000000000000000000000000000000004320000000000000000000000000000000000000000000000000000000000000433000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004350000000000000000000000000000000000000000000000000000000000000436000000000000000000000000000000000000000000000000000000000000043700000000000000000000000000000000000000000000000000000000000004380000000000000000000000000000000000000000000000000000000000000439000000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043b000000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043d000000000000000000000000000000000000000000000000000000000000043e08000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005010000000000000000000000000000000000000000000000000000000000000502000000000000000000000000000000000000000000000000000000000000050300000000000000000000000000000000000000000000000000000000000005040000000000000000000000000000000000000000000000000000000000000505000000000000000000000000000000000000000000000000000000000000050600000000000000000000000000000000000000000000000000000000000005073f0000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000711000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000712000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007160000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000071700000000000000000000000000000000000000000000000000000000000007210000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000072200000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000726000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000721000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000722000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007260000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000072700000000000000000000000000000000000000000000000000000000000007310000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000073200000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000736000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000737000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000731000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000732000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000073f00000000000000000000000000000000000000000000000000000000000007360000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000073700000000000000000000000000000000000000000000000000000000000007410000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000074200000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000743000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000744000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000745000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000746000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000747000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000748000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "txsEffectsHash": "0x00c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b", + "archive": "0x1caafe747155b2a72a6f44744dc68fa9d6c3b605e5dc661383c5a202dd7ee7c8", + "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f3f0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e08000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003410000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000034300000000000000000000000000000000000000000000000000000000000003440000000000000000000000000000000000000000000000000000000000000345000000000000000000000000000000000000000000000000000000000000034600000000000000000000000000000000000000000000000000000000000003473f0000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000551000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000552000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005560000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000055700000000000000000000000000000000000000000000000000000000000005610000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000056200000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000566000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000567000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000561000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000562000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005660000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000056700000000000000000000000000000000000000000000000000000000000005710000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000057200000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000576000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000577000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000571000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000572000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000057f00000000000000000000000000000000000000000000000000000000000005760000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000057700000000000000000000000000000000000000000000000000000000000005810000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000058200000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000586000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000587000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001bf3f0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be08000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003810000000000000000000000000000000000000000000000000000000000000382000000000000000000000000000000000000000000000000000000000000038300000000000000000000000000000000000000000000000000000000000003840000000000000000000000000000000000000000000000000000000000000385000000000000000000000000000000000000000000000000000000000000038600000000000000000000000000000000000000000000000000000000000003873f0000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005990000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000059a0000000000000000000000000000000000000000000000000000000000000591000000000000000000000000000000000000000000000000000000000000059b0000000000000000000000000000000000000000000000000000000000000592000000000000000000000000000000000000000000000000000000000000059c0000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000059d0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000059e0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000059f000000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000059700000000000000000000000000000000000000000000000000000000000005a1000000000000000000000000000000000000000000000000000000000000059800000000000000000000000000000000000000000000000000000000000005a2000000000000000000000000000000000000000000000000000000000000059900000000000000000000000000000000000000000000000000000000000005a3000000000000000000000000000000000000000000000000000000000000059a00000000000000000000000000000000000000000000000000000000000005a4000000000000000000000000000000000000000000000000000000000000059b00000000000000000000000000000000000000000000000000000000000005a5000000000000000000000000000000000000000000000000000000000000059c00000000000000000000000000000000000000000000000000000000000005a6000000000000000000000000000000000000000000000000000000000000059d00000000000000000000000000000000000000000000000000000000000005a7000000000000000000000000000000000000000000000000000000000000059e00000000000000000000000000000000000000000000000000000000000005a8000000000000000000000000000000000000000000000000000000000000059f00000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005a100000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005a200000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005a300000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005a400000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005a500000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005a600000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005a700000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005a800000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005bf00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001ff3f00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe0800000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c73f00000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005f600000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005f700000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005f800000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005f900000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005fa00000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005fb00000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005fc00000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005fd00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005fe00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ff00000000000000000000000000000000000000000000000000000000000005f6000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005f7000000000000000000000000000000000000000000000000000000000000060100000000000000000000000000000000000000000000000000000000000005f8000000000000000000000000000000000000000000000000000000000000060200000000000000000000000000000000000000000000000000000000000005f9000000000000000000000000000000000000000000000000000000000000060300000000000000000000000000000000000000000000000000000000000005fa000000000000000000000000000000000000000000000000000000000000060400000000000000000000000000000000000000000000000000000000000005fb000000000000000000000000000000000000000000000000000000000000060500000000000000000000000000000000000000000000000000000000000005fc000000000000000000000000000000000000000000000000000000000000060600000000000000000000000000000000000000000000000000000000000005fd000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000005fe0000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002320000000000000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002350000000000000000000000000000000000000000000000000000000000000236000000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002380000000000000000000000000000000000000000000000000000000000000239000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023f3f0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e08000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004010000000000000000000000000000000000000000000000000000000000000402000000000000000000000000000000000000000000000000000000000000040300000000000000000000000000000000000000000000000000000000000004040000000000000000000000000000000000000000000000000000000000000405000000000000000000000000000000000000000000000000000000000000040600000000000000000000000000000000000000000000000000000000000004073f0000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000611000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000612000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006160000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061700000000000000000000000000000000000000000000000000000000000006210000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000062200000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000626000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000621000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000622000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006260000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062700000000000000000000000000000000000000000000000000000000000006310000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000063200000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000636000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000637000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000631000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000632000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000063f00000000000000000000000000000000000000000000000000000000000006360000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000063700000000000000000000000000000000000000000000000000000000000006410000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000064200000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000646000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000647000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "txsEffectsHash": "0x006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a3", "decodedHeader": { "contentCommitment": { - "inHash": "0x00212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb891937", - "outHash": "0x008bb57ba402f4917a5169c695e37af3fa10ae64220de709573dbf127d9955e8", + "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", + "outHash": "0x0071556a0e9f403540d572c98a081d21b325e7c802b8b3baf54f3d56fecb2230", "numTxs": 4, - "txsEffectsHash": "0x00c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b" + "txsEffectsHash": "0x006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a3" }, "globalVariables": { - "blockNumber": 2, + "blockNumber": 1, "chainId": 31337, - "timestamp": 1719332461, + "timestamp": 0, "version": 1, "coinbase": "0x38e74ed15dd5ab05fff041b5037372cce88aa7e9", "feeRecipient": "0x1bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be", @@ -81,32 +81,32 @@ } }, "lastArchive": { - "nextAvailableLeafIndex": 2, - "root": "0x1caafe747155b2a72a6f44744dc68fa9d6c3b605e5dc661383c5a202dd7ee7c8" + "nextAvailableLeafIndex": 1, + "root": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b6" }, "stateReference": { "l1ToL2MessageTree": { - "nextAvailableLeafIndex": 32, - "root": "0x2e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d" + "nextAvailableLeafIndex": 16, + "root": "0x1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80" }, "partialStateReference": { "noteHashTree": { - "nextAvailableLeafIndex": 512, - "root": "0x24c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f96" + "nextAvailableLeafIndex": 256, + "root": "0x0d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e" }, "nullifierTree": { - "nextAvailableLeafIndex": 640, - "root": "0x268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e" + "nextAvailableLeafIndex": 384, + "root": "0x01c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a2" }, "publicDataTree": { - "nextAvailableLeafIndex": 640, - "root": "0x2f1b0fefdce35aa5d17156a75b5df1128daa19c74dd56455e4545054d6a48eff" + "nextAvailableLeafIndex": 384, + "root": "0x2f72d4fe80aa0b43708532e4fb05cdf574bfd36c8c6bba1ff4ec3c6e0ffc9b3a" } } } }, - "header": "0x1caafe747155b2a72a6f44744dc68fa9d6c3b605e5dc661383c5a202dd7ee7c800000002000000000000000000000000000000000000000000000000000000000000000400c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b00212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb891937008bb57ba402f4917a5169c695e37af3fa10ae64220de709573dbf127d9955e82e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d0000002024c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f9600000200268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e000002802f1b0fefdce35aa5d17156a75b5df1128daa19c74dd56455e4545054d6a48eff000002800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000667aee6d38e74ed15dd5ab05fff041b5037372cce88aa7e91bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x006abc0437c6efc01d8f9e20d9bc15d8181ffcbf03c5869276d004c087bc117a", + "header": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b6000000010000000000000000000000000000000000000000000000000000000000000004006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a300089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0071556a0e9f403540d572c98a081d21b325e7c802b8b3baf54f3d56fecb22301864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000100d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e0000010001c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a2000001802f72d4fe80aa0b43708532e4fb05cdf574bfd36c8c6bba1ff4ec3c6e0ffc9b3a000001800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000038e74ed15dd5ab05fff041b5037372cce88aa7e91bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x0086d49b8b947a0b784ea6e86697292895d7f54a547fa954ab820140274340d4", "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 new file mode 100644 index 00000000000..b3d023bdcda --- /dev/null +++ b/l1-contracts/test/fixtures/mixed_block_2.json @@ -0,0 +1,112 @@ +{ + "populate": { + "l1ToL2Content": [ + "0x0000000000000000000000000000000000000000000000000000000000000481", + "0x0000000000000000000000000000000000000000000000000000000000000482", + "0x0000000000000000000000000000000000000000000000000000000000000483", + "0x0000000000000000000000000000000000000000000000000000000000000484", + "0x0000000000000000000000000000000000000000000000000000000000000485", + "0x0000000000000000000000000000000000000000000000000000000000000486", + "0x0000000000000000000000000000000000000000000000000000000000000487", + "0x0000000000000000000000000000000000000000000000000000000000000488", + "0x0000000000000000000000000000000000000000000000000000000000000489", + "0x000000000000000000000000000000000000000000000000000000000000048a", + "0x000000000000000000000000000000000000000000000000000000000000048b", + "0x000000000000000000000000000000000000000000000000000000000000048c", + "0x000000000000000000000000000000000000000000000000000000000000048d", + "0x000000000000000000000000000000000000000000000000000000000000048e", + "0x000000000000000000000000000000000000000000000000000000000000048f", + "0x0000000000000000000000000000000000000000000000000000000000000490" + ], + "recipient": "0x1647b194c649f5dd01d7c832f89b0f496043c9150797923ea89e93d5ac619a93", + "sender": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc" + }, + "messages": { + "l2ToL1Messages": [ + "0x0000000000000000000000000000000000000000000000000000000000000440", + "0x0000000000000000000000000000000000000000000000000000000000000441", + "0x0000000000000000000000000000000000000000000000000000000000000442", + "0x0000000000000000000000000000000000000000000000000000000000000443", + "0x0000000000000000000000000000000000000000000000000000000000000444", + "0x0000000000000000000000000000000000000000000000000000000000000445", + "0x0000000000000000000000000000000000000000000000000000000000000446", + "0x0000000000000000000000000000000000000000000000000000000000000447", + "0x0000000000000000000000000000000000000000000000000000000000000480", + "0x0000000000000000000000000000000000000000000000000000000000000481", + "0x0000000000000000000000000000000000000000000000000000000000000482", + "0x0000000000000000000000000000000000000000000000000000000000000483", + "0x0000000000000000000000000000000000000000000000000000000000000484", + "0x0000000000000000000000000000000000000000000000000000000000000485", + "0x0000000000000000000000000000000000000000000000000000000000000486", + "0x0000000000000000000000000000000000000000000000000000000000000487", + "0x00000000000000000000000000000000000000000000000000000000000004c0", + "0x00000000000000000000000000000000000000000000000000000000000004c1", + "0x00000000000000000000000000000000000000000000000000000000000004c2", + "0x00000000000000000000000000000000000000000000000000000000000004c3", + "0x00000000000000000000000000000000000000000000000000000000000004c4", + "0x00000000000000000000000000000000000000000000000000000000000004c5", + "0x00000000000000000000000000000000000000000000000000000000000004c6", + "0x00000000000000000000000000000000000000000000000000000000000004c7", + "0x0000000000000000000000000000000000000000000000000000000000000500", + "0x0000000000000000000000000000000000000000000000000000000000000501", + "0x0000000000000000000000000000000000000000000000000000000000000502", + "0x0000000000000000000000000000000000000000000000000000000000000503", + "0x0000000000000000000000000000000000000000000000000000000000000504", + "0x0000000000000000000000000000000000000000000000000000000000000505", + "0x0000000000000000000000000000000000000000000000000000000000000506", + "0x0000000000000000000000000000000000000000000000000000000000000507" + ] + }, + "block": { + "archive": "0x0796e4e2dcd2e9d783732a42084fd8fd79acd7bbc7e9d511f5d0c59d4de6aa80", + "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027f3f0000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f0000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003720000000000000000000000000000000000000000000000000000000000000373000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003750000000000000000000000000000000000000000000000000000000000000376000000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003780000000000000000000000000000000000000000000000000000000000000379000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037e08000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004410000000000000000000000000000000000000000000000000000000000000442000000000000000000000000000000000000000000000000000000000000044300000000000000000000000000000000000000000000000000000000000004440000000000000000000000000000000000000000000000000000000000000445000000000000000000000000000000000000000000000000000000000000044600000000000000000000000000000000000000000000000000000000000004473f0000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000651000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000652000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006560000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000065700000000000000000000000000000000000000000000000000000000000006610000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000066200000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000666000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000667000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000661000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000662000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006660000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000066700000000000000000000000000000000000000000000000000000000000006710000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000067200000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000676000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000677000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000671000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000672000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000067f00000000000000000000000000000000000000000000000000000000000006760000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000067700000000000000000000000000000000000000000000000000000000000006810000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000068200000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000686000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000687000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002bf3f0000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003be08000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000004810000000000000000000000000000000000000000000000000000000000000482000000000000000000000000000000000000000000000000000000000000048300000000000000000000000000000000000000000000000000000000000004840000000000000000000000000000000000000000000000000000000000000485000000000000000000000000000000000000000000000000000000000000048600000000000000000000000000000000000000000000000000000000000004873f0000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006990000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000069a0000000000000000000000000000000000000000000000000000000000000691000000000000000000000000000000000000000000000000000000000000069b0000000000000000000000000000000000000000000000000000000000000692000000000000000000000000000000000000000000000000000000000000069c0000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000069d0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000069e0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000069f000000000000000000000000000000000000000000000000000000000000069600000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000069700000000000000000000000000000000000000000000000000000000000006a1000000000000000000000000000000000000000000000000000000000000069800000000000000000000000000000000000000000000000000000000000006a2000000000000000000000000000000000000000000000000000000000000069900000000000000000000000000000000000000000000000000000000000006a3000000000000000000000000000000000000000000000000000000000000069a00000000000000000000000000000000000000000000000000000000000006a4000000000000000000000000000000000000000000000000000000000000069b00000000000000000000000000000000000000000000000000000000000006a5000000000000000000000000000000000000000000000000000000000000069c00000000000000000000000000000000000000000000000000000000000006a6000000000000000000000000000000000000000000000000000000000000069d00000000000000000000000000000000000000000000000000000000000006a7000000000000000000000000000000000000000000000000000000000000069e00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000069f00000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006a100000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006a200000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006a300000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006a400000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006a500000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006a600000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006a700000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006a800000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006bf00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002ff3f00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f700000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003f900000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fb00000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fd00000000000000000000000000000000000000000000000000000000000003fe0800000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c100000000000000000000000000000000000000000000000000000000000004c200000000000000000000000000000000000000000000000000000000000004c300000000000000000000000000000000000000000000000000000000000004c400000000000000000000000000000000000000000000000000000000000004c500000000000000000000000000000000000000000000000000000000000004c600000000000000000000000000000000000000000000000000000000000004c73f00000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006f600000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006f700000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006f800000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006f900000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006fa00000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006fb00000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006fc00000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006fd00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006fe00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ff00000000000000000000000000000000000000000000000000000000000006f6000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000006f7000000000000000000000000000000000000000000000000000000000000070100000000000000000000000000000000000000000000000000000000000006f8000000000000000000000000000000000000000000000000000000000000070200000000000000000000000000000000000000000000000000000000000006f9000000000000000000000000000000000000000000000000000000000000070300000000000000000000000000000000000000000000000000000000000006fa000000000000000000000000000000000000000000000000000000000000070400000000000000000000000000000000000000000000000000000000000006fb000000000000000000000000000000000000000000000000000000000000070500000000000000000000000000000000000000000000000000000000000006fc000000000000000000000000000000000000000000000000000000000000070600000000000000000000000000000000000000000000000000000000000006fd000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000006fe0000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033f3f0000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f0000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000043100000000000000000000000000000000000000000000000000000000000004320000000000000000000000000000000000000000000000000000000000000433000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004350000000000000000000000000000000000000000000000000000000000000436000000000000000000000000000000000000000000000000000000000000043700000000000000000000000000000000000000000000000000000000000004380000000000000000000000000000000000000000000000000000000000000439000000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043b000000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043d000000000000000000000000000000000000000000000000000000000000043e08000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005010000000000000000000000000000000000000000000000000000000000000502000000000000000000000000000000000000000000000000000000000000050300000000000000000000000000000000000000000000000000000000000005040000000000000000000000000000000000000000000000000000000000000505000000000000000000000000000000000000000000000000000000000000050600000000000000000000000000000000000000000000000000000000000005073f0000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000711000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000712000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007160000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000071700000000000000000000000000000000000000000000000000000000000007210000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000072200000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000726000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000721000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000722000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007260000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000072700000000000000000000000000000000000000000000000000000000000007310000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000073200000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000736000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000737000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000731000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000732000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000073f00000000000000000000000000000000000000000000000000000000000007360000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000073700000000000000000000000000000000000000000000000000000000000007410000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000074200000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000743000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000744000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000745000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000746000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000747000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000748000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "txsEffectsHash": "0x00c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b", + "decodedHeader": { + "contentCommitment": { + "inHash": "0x00212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb891937", + "outHash": "0x008bb57ba402f4917a5169c695e37af3fa10ae64220de709573dbf127d9955e8", + "numTxs": 4, + "txsEffectsHash": "0x00c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b" + }, + "globalVariables": { + "blockNumber": 2, + "chainId": 31337, + "timestamp": 1719332461, + "version": 1, + "coinbase": "0x38e74ed15dd5ab05fff041b5037372cce88aa7e9", + "feeRecipient": "0x1bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be", + "gasFees": { + "feePerDaGas": 0, + "feePerL2Gas": 0 + } + }, + "lastArchive": { + "nextAvailableLeafIndex": 2, + "root": "0x1caafe747155b2a72a6f44744dc68fa9d6c3b605e5dc661383c5a202dd7ee7c8" + }, + "stateReference": { + "l1ToL2MessageTree": { + "nextAvailableLeafIndex": 32, + "root": "0x2e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d" + }, + "partialStateReference": { + "noteHashTree": { + "nextAvailableLeafIndex": 512, + "root": "0x24c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f96" + }, + "nullifierTree": { + "nextAvailableLeafIndex": 640, + "root": "0x268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e" + }, + "publicDataTree": { + "nextAvailableLeafIndex": 640, + "root": "0x2f1b0fefdce35aa5d17156a75b5df1128daa19c74dd56455e4545054d6a48eff" + } + } + } + }, + "header": "0x1caafe747155b2a72a6f44744dc68fa9d6c3b605e5dc661383c5a202dd7ee7c800000002000000000000000000000000000000000000000000000000000000000000000400c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b00212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb891937008bb57ba402f4917a5169c695e37af3fa10ae64220de709573dbf127d9955e82e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d0000002024c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f9600000200268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e000002802f1b0fefdce35aa5d17156a75b5df1128daa19c74dd56455e4545054d6a48eff000002800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000667aee6d38e74ed15dd5ab05fff041b5037372cce88aa7e91bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x006abc0437c6efc01d8f9e20d9bc15d8181ffcbf03c5869276d004c087bc117a", + "numTxs": 4 + } +} \ No newline at end of file diff --git a/l1-contracts/test/sparta/Sparta.t.sol b/l1-contracts/test/sparta/Sparta.t.sol index f3d9dc7662b..b57b3546af1 100644 --- a/l1-contracts/test/sparta/Sparta.t.sol +++ b/l1-contracts/test/sparta/Sparta.t.sol @@ -73,18 +73,18 @@ contract SpartaTest is DecoderBase { } function testHappyPath() public { - _testBlock("mixed_block_0", 0, false); // We run a block before the epoch with validators - _testBlock("mixed_block_1", 3, false); // We need signatures! + _testBlock("mixed_block_1", 0, false); // We run a block before the epoch with validators + _testBlock("mixed_block_2", 3, false); // We need signatures! } function testInvalidProposer() public { - _testBlock("mixed_block_0", 0, false); // We run a block before the epoch with validators - _testBlock("mixed_block_1", 3, true); // We need signatures! + _testBlock("mixed_block_1", 0, false); // We run a block before the epoch with validators + _testBlock("mixed_block_2", 3, true); // We need signatures! } function testInsufficientSigs() public { - _testBlock("mixed_block_0", 0, false); // We run a block before the epoch with validators - _testBlock("mixed_block_1", 2, false); // We need signatures! + _testBlock("mixed_block_1", 0, false); // We run a block before the epoch with validators + _testBlock("mixed_block_2", 2, false); // We need signatures! } struct StructToAvoidDeepStacks { diff --git a/yarn-project/aztec.js/src/utils/cheat_codes.ts b/yarn-project/aztec.js/src/utils/cheat_codes.ts index 08055d90130..95cceaf0e39 100644 --- a/yarn-project/aztec.js/src/utils/cheat_codes.ts +++ b/yarn-project/aztec.js/src/utils/cheat_codes.ts @@ -267,9 +267,9 @@ export class AztecCheatCodes { await this.eth.setNextBlockTimestamp(to); // also store this time on the rollup contract (slot 2 tracks `lastBlockTs`). // This is because when the sequencer executes public functions, it uses the timestamp stored in the rollup contract. - await this.eth.store(rollupContract, 7n, BigInt(to)); + await this.eth.store(rollupContract, 6n, BigInt(to)); // also store this on slot of the rollup contract (`lastWarpedBlockTs`) which tracks the last time warp was used. - await this.eth.store(rollupContract, 8n, BigInt(to)); + await this.eth.store(rollupContract, 7n, BigInt(to)); } /** diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 2d6127b601d..7c91e138813 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -366,7 +366,7 @@ describe('L1Publisher integration', () => { // Check that we have not yet written a root to this blocknumber expect(BigInt(emptyRoot)).toStrictEqual(0n); - writeJson(`mixed_block_${i}`, block, l1ToL2Content, recipientAddress, deployerAccount.address); + writeJson(`mixed_block_${block.number}`, block, l1ToL2Content, recipientAddress, deployerAccount.address); await publisher.processL2Block(block); @@ -451,7 +451,7 @@ describe('L1Publisher integration', () => { blockSource.getL1ToL2Messages.mockResolvedValueOnce(l1ToL2Messages); blockSource.getBlocks.mockResolvedValueOnce([block]); - writeJson(`empty_block_${i}`, block, [], AztecAddress.ZERO, deployerAccount.address); + writeJson(`empty_block_${block.number}`, block, [], AztecAddress.ZERO, deployerAccount.address); await publisher.processL2Block(block); From cfb4aa8602c316003d018bf3192e2a13e36cacad Mon Sep 17 00:00:00 2001 From: Sarkoxed <75146596+Sarkoxed@users.noreply.github.com> Date: Wed, 31 Jul 2024 13:07:15 +0400 Subject: [PATCH 17/35] feat: extend SMT Utils (#7126) This pr resolves several issues with Symbolic Circuits and adds new functionality to smt_util ## CircuitBase / StandardCircuit / UltraCircuit `bool optimizations` -> `bool enable_optimizations` ## STerm Added comment about an origin of the division result name ## smt_util.cpp - new function `bb::fr string_to_fr(std::string number, int base, size_t step = 0)` allows to convert string values of an arbitrary base(but most importantly 2, 10 and 16) to `bb::fr`. Need this because of the huge witnesses, provided by the solver, that cause segfaults during ordinary import. - `default_model` and `default_model_single` now export the `msgpack`'d version of a witness too. - `import_witness`, `import_witness_single` imports the packed witness from file ## README added all this to README.md file ## Standard Symbolic Circuit Fixed an issue that caused merging of two consecutive xors into one while applying an optimization. It thought that two consecutive 32 bit xors is one 64 bit xor. Now it's not. + added the test to check this behavior ## Ultra Symbolic Circuit Moved lookup table initialization to the separate method. Added xor and and tables detection with further optimizations. Added two tests that check that everything is fine. --- .../smt_verification/CMakeLists.txt | 2 +- .../barretenberg/smt_verification/README.md | 11 +- .../smt_verification/circuit/circuit_base.cpp | 4 +- .../smt_verification/circuit/circuit_base.hpp | 4 +- .../circuit/standard_circuit.cpp | 59 ++++-- .../circuit/standard_circuit.hpp | 6 +- .../circuit/standard_circuit.test.cpp | 20 ++ .../circuit/ultra_circuit.cpp | 94 +++++++--- .../circuit/ultra_circuit.hpp | 10 +- .../circuit/ultra_circuit.test.cpp | 64 ++++++- .../smt_verification/solver/solver.cpp | 4 +- .../smt_verification/terms/term.cpp | 2 + .../smt_verification/util/smt_util.cpp | 177 +++++++++++++++--- .../smt_verification/util/smt_util.hpp | 11 +- 14 files changed, 373 insertions(+), 95 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/smt_verification/CMakeLists.txt index 265a64887e6..35ce5bcd48d 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/smt_verification/CMakeLists.txt @@ -12,7 +12,7 @@ ExternalProject_Add( GIT_REPOSITORY "https://github.com/cvc5/cvc5.git" GIT_TAG main BUILD_IN_SOURCE YES - CONFIGURE_COMMAND ${SHELL} ./configure.sh production --auto-download --cocoa --cryptominisat --kissat -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ --prefix=${CVC5_BUILD} + CONFIGURE_COMMAND ${SHELL} ./configure.sh production --gpl --auto-download --cocoa --cryptominisat --kissat -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ --prefix=${CVC5_BUILD} BUILD_COMMAND make -C build INSTALL_COMMAND make -C build install UPDATE_COMMAND "" # No update step diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/README.md b/barretenberg/cpp/src/barretenberg/smt_verification/README.md index aa12cccf666..2db78c3853b 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/README.md +++ b/barretenberg/cpp/src/barretenberg/smt_verification/README.md @@ -184,11 +184,17 @@ Now you have the values of the specified terms, which resulted into `true` resul **!Note that the return values are decimal strings/binary strings**, so if you want to use them later you should use `FFConst` with base 10, etc. Also, there is a header file "barretenberg/smt_verification/utl/smt_util.hpp" that contains two useful functions: -- `default_model(verctor special_names, circuit1, circuit2, *solver, fname="witness.out")` -- `default_model_single(vector special_names, circuit, *solver, fname="witness.out)` +- `default_model(verctor special_names, circuit1, circuit2, *solver, fname="witness.out", bool pack = true)` +- `default_model_single(vector special_names, circuit, *solver, fname="witness.out, bool pack = true)` These functions will write witness variables in c-like array format into file named `fname`. The vector of `special_names` is the values that you want ot see in stdout. +`pack` argument tells this function to save an `msgpack` buffer of the witness on disk. Name of the file will be `fname`.pack + +You can then import the saved witness using one of the following functions: + +- `vec> import_witness(str fname)` +- `vec import_witness_single(str fname)` ## 4. Automated verification of a unique witness There's a static member of `StandardCircuit` and `UltraCircuit` @@ -211,6 +217,7 @@ Besides already mentioned `smt_timer`, `default_model` and `default_model_single - `pair, vector> base4(uint32_t el)` - that will return base4 accumulators - `void fix_range_lists(UltraCircuitBuilder& builder)` - Since we are not using the part of the witness, that contains range lists, they are set to 0 by the solver. We need to overwrite them to check the witness obtained by the solver. +- `bb::fr string_to_fr(str num, int base, size_t step)` - converts string of an arbitrary base into `bb::fr` value. $\max_{step}(base^{step} \le 2^{64})$ ```c++ UltraCircuitBuilder builder; diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit_base.cpp b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit_base.cpp index b4c6d1c872b..edde7e005cf 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit_base.cpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit_base.cpp @@ -11,14 +11,14 @@ CircuitBase::CircuitBase(std::unordered_map& variable_nam Solver* solver, TermType type, const std::string& tag, - bool optimizations) + bool enable_optimizations) : variables(variables) , public_inps(public_inps) , variable_names(variable_names) , real_variable_index(real_variable_index) , real_variable_tags(real_variable_tags) , range_tags(range_tags) - , optimizations(optimizations) + , enable_optimizations(enable_optimizations) , solver(solver) , type(type) , tag(tag) diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit_base.hpp b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit_base.hpp index 5d551406a4c..e39d46a88e0 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit_base.hpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/circuit_base.hpp @@ -37,7 +37,7 @@ class CircuitBase { std::unordered_map range_tags; // ranges associated with a certain tag std::unordered_map optimized; // keeps track of the variables that were excluded from symbolic // circuit during optimizations - bool optimizations; // flags to turn on circuit optimizations + bool enable_optimizations; // flags to turn on circuit optimizations std::unordered_map> cached_subcircuits; // caches subcircuits during optimization // No need to recompute them each time @@ -58,7 +58,7 @@ class CircuitBase { Solver* solver, TermType type, const std::string& tag = "", - bool optimizations = true); + bool enable_optimizations = true); STerm operator[](const std::string& name); STerm operator[](const uint32_t& idx) { return this->symbolic_vars[this->real_variable_index[idx]]; }; diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/standard_circuit.cpp b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/standard_circuit.cpp index 1365618b02c..6d68d93333d 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/standard_circuit.cpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/standard_circuit.cpp @@ -10,7 +10,7 @@ namespace smt_circuit { * @param tag tag of the circuit. Empty by default. */ StandardCircuit::StandardCircuit( - CircuitSchema& circuit_info, Solver* solver, TermType type, const std::string& tag, bool optimizations) + CircuitSchema& circuit_info, Solver* solver, TermType type, const std::string& tag, bool enable_optimizations) : CircuitBase(circuit_info.vars_of_interest, circuit_info.variables, circuit_info.public_inps, @@ -20,7 +20,7 @@ StandardCircuit::StandardCircuit( solver, type, tag, - optimizations) + enable_optimizations) , selectors(circuit_info.selectors[0]) , wires_idxs(circuit_info.wires[0]) { @@ -46,34 +46,34 @@ StandardCircuit::StandardCircuit( */ size_t StandardCircuit::prepare_gates(size_t cursor) { - if (this->type == TermType::BVTerm && this->optimizations) { + if (this->type == TermType::BVTerm && this->enable_optimizations) { size_t res = handle_logic_constraint(cursor); if (res != static_cast(-1)) { return res; } } - if ((this->type == TermType::BVTerm || this->type == TermType::FFITerm) && this->optimizations) { + if ((this->type == TermType::BVTerm || this->type == TermType::FFITerm) && this->enable_optimizations) { size_t res = handle_range_constraint(cursor); if (res != static_cast(-1)) { return res; } } - if ((this->type == TermType::BVTerm) && this->optimizations) { + if ((this->type == TermType::BVTerm) && this->enable_optimizations) { size_t res = handle_ror_constraint(cursor); if (res != static_cast(-1)) { return res; } } - if ((this->type == TermType::BVTerm) && this->optimizations) { + if ((this->type == TermType::BVTerm) && this->enable_optimizations) { size_t res = handle_shl_constraint(cursor); if (res != static_cast(-1)) { return res; } } - if ((this->type == TermType::BVTerm) && this->optimizations) { + if ((this->type == TermType::BVTerm) && this->enable_optimizations) { size_t res = handle_shr_constraint(cursor); if (res != static_cast(-1)) { return res; @@ -182,6 +182,7 @@ void StandardCircuit::handle_univariate_constraint( } } +// TODO(alex): Optimized out variables should be filled with proper values... /** * @brief Relaxes logic constraints(AND/XOR). * @details This function is needed when we use bitwise compatible @@ -252,6 +253,20 @@ size_t StandardCircuit::handle_logic_constraint(size_t cursor) xor_flag &= xor_circuit.selectors[0][j + xor_props.start_gate] == this->selectors[cursor + j]; and_flag &= and_circuit.selectors[0][j + and_props.start_gate] == this->selectors[cursor + j]; + // Before this fix this routine simplified two consecutive n bit xors(ands) into one 2n bit xor(and) + // Now it checks out_accumulator_idx and new_out_accumulator_idx match + // 14 here is a size of one iteration of logic_gate for loop in term of gates + // 13 is the accumulator index relative to the beginning of the iteration + + size_t single_iteration_size = 14; + size_t relative_acc_idx = 13; + xor_flag &= + (j % single_iteration_size != relative_acc_idx) || (j == relative_acc_idx) || + (this->wires_idxs[j + cursor][0] == this->wires_idxs[j + cursor - single_iteration_size][2]); + and_flag &= + (j % single_iteration_size != relative_acc_index) || (j == relative_acc_index) || + (this->wires_idxs[j + cursor][0] == this->wires_idxs[j + cursor - single_iteration_size][2]); + if (!xor_flag && !and_flag) { // Won't match at any bit length if (j == 0) { @@ -411,6 +426,10 @@ size_t StandardCircuit::handle_range_constraint(size_t cursor) // preserving shifted values // we need this because even right shifts do not create // any additional gates and therefore are undetectible + + // TODO(alex): I think I should simulate the whole subcircuit at that point + // Otherwise optimized out variables are not correct in the final witness + // And I can't fix them by hand each time size_t num_accs = range_props.gate_idxs.size() - 1; for (size_t j = 1; j < num_accs + 1 && (this->type == TermType::BVTerm); j++) { size_t acc_gate = range_props.gate_idxs[j]; @@ -418,10 +437,9 @@ size_t StandardCircuit::handle_range_constraint(size_t cursor) uint32_t acc_idx = this->real_variable_index[this->wires_idxs[cursor + acc_gate][acc_gate_idx]]; - // TODO(alex): Is it better? Can't come up with why not right now - // STerm acc = this->symbolic_vars[acc_idx]; - // acc == (left >> static_cast(2 * j)); - this->symbolic_vars[acc_idx] = (left >> static_cast(2 * j)); + this->symbolic_vars[acc_idx] == (left >> static_cast(2 * j)); + // I think the following is worse. The name of the variable is lost after that + // this->symbolic_vars[acc_idx] = (left >> static_cast(2 * j)); } left <= (bb::fr(2).pow(res) - 1); @@ -812,10 +830,10 @@ std::pair StandardCircuit::unique_witness_ext( const std::vector& not_equal, const std::vector& equal_at_the_same_time, const std::vector& not_equal_at_the_same_time, - bool optimizations) + bool enable_optimizations) { - StandardCircuit c1(circuit_info, s, type, "circuit1", optimizations); - StandardCircuit c2(circuit_info, s, type, "circuit2", optimizations); + StandardCircuit c1(circuit_info, s, type, "circuit1", enable_optimizations); + StandardCircuit c2(circuit_info, s, type, "circuit2", enable_optimizations); for (const auto& term : equal) { c1[term] == c2[term]; @@ -863,11 +881,14 @@ std::pair StandardCircuit::unique_witness_ext( * @param equal The list of names of variables which should be equal in both circuits(each is equal) * @return std::pair */ -std::pair StandardCircuit::unique_witness( - CircuitSchema& circuit_info, Solver* s, TermType type, const std::vector& equal, bool optimizations) +std::pair StandardCircuit::unique_witness(CircuitSchema& circuit_info, + Solver* s, + TermType type, + const std::vector& equal, + bool enable_optimizations) { - StandardCircuit c1(circuit_info, s, type, "circuit1", optimizations); - StandardCircuit c2(circuit_info, s, type, "circuit2", optimizations); + StandardCircuit c1(circuit_info, s, type, "circuit1", enable_optimizations); + StandardCircuit c2(circuit_info, s, type, "circuit2", enable_optimizations); for (const auto& term : equal) { c1[term] == c2[term]; @@ -893,4 +914,4 @@ std::pair StandardCircuit::unique_witness( } return { c1, c2 }; } -}; // namespace smt_circuit \ No newline at end of file +}; // namespace smt_circuit diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/standard_circuit.hpp b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/standard_circuit.hpp index 03d0a4393f1..967c7ffdad8 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/standard_circuit.hpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/standard_circuit.hpp @@ -18,7 +18,7 @@ class StandardCircuit : public CircuitBase { Solver* solver, TermType type = TermType::FFTerm, const std::string& tag = "", - bool optimizations = true); + bool enable_optimizations = true); inline size_t get_num_gates() const { return selectors.size(); }; @@ -40,12 +40,12 @@ class StandardCircuit : public CircuitBase { const std::vector& not_equal = {}, const std::vector& equal_at_the_same_time = {}, const std::vector& not_equal_at_the_same_time = {}, - bool optimizations = false); + bool enable_optimizations = false); static std::pair unique_witness(CircuitSchema& circuit_info, Solver* s, TermType type, const std::vector& equal = {}, - bool optimizations = false); + bool enable_optimizations = false); }; }; // namespace smt_circuit \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/standard_circuit.test.cpp b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/standard_circuit.test.cpp index 4c885ba6cd3..ffded6864dd 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/standard_circuit.test.cpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/standard_circuit.test.cpp @@ -356,3 +356,23 @@ TEST(standard_circuit, shr_relaxation) StandardCircuit circuit(circuit_info, &s, TermType::BVTerm); } } + +TEST(standard_circuit, check_double_xor_bug) +{ + StandardCircuitBuilder builder; + uint_ct a = witness_t(&builder, 10); + uint_ct b = witness_t(&builder, 10); + + uint_ct c = a ^ b; + uint_ct d = a ^ b; + d = d ^ c; + + c = a & b; + d = a & b; + d = d & c; + + auto buf = builder.export_circuit(); + CircuitSchema circuit_info = unpack_from_buffer(buf); + Solver s(circuit_info.modulus, default_solver_config, 16, 64); + StandardCircuit circuit(circuit_info, &s, TermType::BVTerm); +} diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/ultra_circuit.cpp b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/ultra_circuit.cpp index c469ead82fc..01cb3728524 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/ultra_circuit.cpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/ultra_circuit.cpp @@ -138,6 +138,38 @@ size_t UltraCircuit::handle_arithmetic_relation(size_t cursor, size_t idx) return cursor + 1; } +void UltraCircuit::process_new_table(uint32_t table_idx) +{ + std::vector> new_table; + bool is_xor = true; + bool is_and = true; + + for (auto table_entry : this->lookup_tables[table_idx]) { + std::vector tmp_entry = { + STerm(table_entry[0], this->solver, this->type), + STerm(table_entry[1], this->solver, this->type), + STerm(table_entry[2], this->solver, this->type), + }; + new_table.push_back(tmp_entry); + + is_xor &= (static_cast(table_entry[0]) ^ static_cast(table_entry[1])) == + static_cast(table_entry[2]); + is_and &= (static_cast(table_entry[0]) & static_cast(table_entry[1])) == + static_cast(table_entry[2]); + } + this->cached_symbolic_tables.insert({ table_idx, this->solver->create_lookup_table(new_table) }); + if (is_xor) { + this->tables_types.insert({ table_idx, TableType::XOR }); + info("Encountered a XOR table"); + } else if (is_and) { + this->tables_types.insert({ table_idx, TableType::AND }); + info("Encountered an AND table"); + } else { + this->tables_types.insert({ table_idx, TableType::UNKNOWN }); + info("Encountered an UNKNOWN table"); + } +} + /** * @brief Adds all the lookup gate constraints to the solver. * Relaxes constraint system for non-ff solver engines @@ -175,31 +207,36 @@ size_t UltraCircuit::handle_lookup_relation(size_t cursor, size_t idx) auto table_idx = static_cast(q_o); if (!this->cached_symbolic_tables.contains(table_idx)) { - std::vector> new_table; - for (auto table_entry : this->lookup_tables[table_idx]) { - std::vector tmp_entry = { - STerm(table_entry[0], this->solver, this->type), - STerm(table_entry[1], this->solver, this->type), - STerm(table_entry[2], this->solver, this->type), - }; - new_table.push_back(tmp_entry); - } - this->cached_symbolic_tables.insert({ table_idx, this->solver->create_lookup_table(new_table) }); - } - - // Sort of an optimization. - // However if we don't do this, solver will find a unique witness that corresponds to overflowed value. - if (this->type == TermType::BVTerm && q_r == -64 && q_m == -64 && q_c == -64) { - this->symbolic_vars[w_l_shift_idx] = this->symbolic_vars[w_l_idx] >> 6; - this->symbolic_vars[w_r_shift_idx] = this->symbolic_vars[w_r_idx] >> 6; - this->symbolic_vars[w_o_shift_idx] = this->symbolic_vars[w_o_idx] >> 6; + this->process_new_table(table_idx); } STerm first_entry = this->symbolic_vars[w_l_idx] + q_r * this->symbolic_vars[w_l_shift_idx]; STerm second_entry = this->symbolic_vars[w_r_idx] + q_m * this->symbolic_vars[w_r_shift_idx]; STerm third_entry = this->symbolic_vars[w_o_idx] + q_c * this->symbolic_vars[w_o_shift_idx]; - std::vector entries = { first_entry, second_entry, third_entry }; + + if (this->type == TermType::BVTerm && this->enable_optimizations) { + // Sort of an optimization. + // However if we don't do this, solver will find a unique witness that corresponds to overflowed value. + if (q_r == -64 && q_m == -64 && q_c == -64) { + this->symbolic_vars[w_l_shift_idx] = this->symbolic_vars[w_l_idx] >> 6; + this->symbolic_vars[w_r_shift_idx] = this->symbolic_vars[w_r_idx] >> 6; + this->symbolic_vars[w_o_shift_idx] = this->symbolic_vars[w_o_idx] >> 6; + } + switch (this->tables_types[table_idx]) { + case TableType::XOR: + info("XOR optimization"); + (first_entry ^ second_entry) == third_entry; + return cursor + 1; + case TableType::AND: + info("AND optimization"); + (first_entry & second_entry) == third_entry; + return cursor + 1; + case TableType::UNKNOWN: + break; + } + } + info("Unknown Table"); STerm::in_table(entries, this->cached_symbolic_tables[table_idx]); return cursor + 1; } @@ -341,7 +378,7 @@ void UltraCircuit::handle_range_constraints() uint32_t tag = this->real_variable_tags[this->real_variable_index[i]]; if (tag != 0 && this->range_tags.contains(tag)) { uint64_t range = this->range_tags[tag]; - if (this->type == TermType::FFTerm || !this->optimizations) { + if (this->type == TermType::FFTerm || !this->enable_optimizations) { if (!this->cached_range_tables.contains(range)) { std::vector new_range_table; for (size_t entry = 0; entry < range; entry++) { @@ -401,10 +438,10 @@ std::pair UltraCircuit::unique_witness_ext( const std::vector& not_equal, const std::vector& equal_at_the_same_time, const std::vector& not_equal_at_the_same_time, - bool optimizations) + bool enable_optimizations) { - UltraCircuit c1(circuit_info, s, type, "circuit1", optimizations); - UltraCircuit c2(circuit_info, s, type, "circuit2", optimizations); + UltraCircuit c1(circuit_info, s, type, "circuit1", enable_optimizations); + UltraCircuit c2(circuit_info, s, type, "circuit2", enable_optimizations); for (const auto& term : equal) { c1[term] == c2[term]; @@ -452,11 +489,14 @@ std::pair UltraCircuit::unique_witness_ext( * @param equal The list of names of variables which should be equal in both circuits(each is equal) * @return std::pair */ -std::pair UltraCircuit::unique_witness( - CircuitSchema& circuit_info, Solver* s, TermType type, const std::vector& equal, bool optimizations) +std::pair UltraCircuit::unique_witness(CircuitSchema& circuit_info, + Solver* s, + TermType type, + const std::vector& equal, + bool enable_optimizations) { - UltraCircuit c1(circuit_info, s, type, "circuit1", optimizations); - UltraCircuit c2(circuit_info, s, type, "circuit2", optimizations); + UltraCircuit c1(circuit_info, s, type, "circuit1", enable_optimizations); + UltraCircuit c2(circuit_info, s, type, "circuit2", enable_optimizations); for (const auto& term : equal) { c1[term] == c2[term]; diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/ultra_circuit.hpp b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/ultra_circuit.hpp index c6ec07a849e..5fd3be1fd4d 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/ultra_circuit.hpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/ultra_circuit.hpp @@ -3,6 +3,8 @@ namespace smt_circuit { +enum class TableType : int32_t { XOR, AND, UNKNOWN }; + /** * @brief Symbolic Circuit class for Standard Circuit Builder. * @@ -22,13 +24,14 @@ class UltraCircuit : public CircuitBase { std::vector>> lookup_tables; std::unordered_map cached_symbolic_tables; + std::unordered_map tables_types; std::unordered_map cached_range_tables; explicit UltraCircuit(CircuitSchema& circuit_info, Solver* solver, TermType type = TermType::FFTerm, const std::string& tag = "", - bool optimizations = true); + bool enable_optimizations = true); UltraCircuit(const UltraCircuit& other) = default; UltraCircuit(UltraCircuit&& other) = default; UltraCircuit& operator=(const UltraCircuit& other) = default; @@ -42,6 +45,7 @@ class UltraCircuit : public CircuitBase { }; bool simulate_circuit_eval(std::vector& witness) const override; + void process_new_table(uint32_t table_idx); size_t handle_arithmetic_relation(size_t cursor, size_t idx); size_t handle_lookup_relation(size_t cursor, size_t idx); @@ -57,11 +61,11 @@ class UltraCircuit : public CircuitBase { const std::vector& not_equal = {}, const std::vector& equal_at_the_same_time = {}, const std::vector& not_equal_at_the_same_time = {}, - bool optimizations = false); + bool enable_optimizations = false); static std::pair unique_witness(CircuitSchema& circuit_info, Solver* s, TermType type, const std::vector& equal = {}, - bool optimizations = false); + bool enable_optimizations = false); }; }; // namespace smt_circuit \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/ultra_circuit.test.cpp b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/ultra_circuit.test.cpp index bdff9b10774..3c7912f116c 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/circuit/ultra_circuit.test.cpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/circuit/ultra_circuit.test.cpp @@ -239,4 +239,66 @@ TEST(ultra_circuit, lookup_tables) std::string c_solver_val = s.getValue(cir["c"]).getBitVectorValue(); std::string c_builder_val = STerm(c.get_value(), &s, TermType::BVTerm).term.getBitVectorValue(); ASSERT_EQ(c_solver_val, c_builder_val); -} \ No newline at end of file +} + +TEST(ultra_circuit, xor_optimization) +{ + UltraCircuitBuilder builder; + uint_t a(witness_t(&builder, static_cast(bb::fr::random_element()))); + builder.set_variable_name(a.get_witness_index(), "a"); + uint_t b(witness_t(&builder, static_cast(bb::fr::random_element()))); + builder.set_variable_name(b.get_witness_index(), "b"); + uint_t c = a ^ b; + builder.set_variable_name(c.get_witness_index(), "c"); + + CircuitSchema circuit_info = unpack_from_buffer(builder.export_circuit()); + uint32_t modulus_base = 16; + uint32_t bvsize = 35; + Solver s(circuit_info.modulus, ultra_solver_config, modulus_base, bvsize); + + UltraCircuit circuit(circuit_info, &s, TermType::BVTerm); + + circuit["a"] == a.get_value(); + circuit["b"] == b.get_value(); + + s.print_assertions(); + + bool res = smt_timer(&s); + ASSERT_TRUE(res); + std::vector to_model = { circuit["c"] }; + std::unordered_map model = s.model(to_model); + + bb::fr c_sym = string_to_fr(model["c"], 2); + ASSERT_EQ(c_sym, c.get_value()); +} + +TEST(ultra_circuit, and_optimization) +{ + UltraCircuitBuilder builder; + uint_t a(witness_t(&builder, static_cast(bb::fr::random_element()))); + builder.set_variable_name(a.get_witness_index(), "a"); + uint_t b(witness_t(&builder, static_cast(bb::fr::random_element()))); + builder.set_variable_name(b.get_witness_index(), "b"); + uint_t c = a & b; + builder.set_variable_name(c.get_witness_index(), "c"); + + CircuitSchema circuit_info = unpack_from_buffer(builder.export_circuit()); + uint32_t modulus_base = 16; + uint32_t bvsize = 35; + Solver s(circuit_info.modulus, ultra_solver_config, modulus_base, bvsize); + + UltraCircuit circuit(circuit_info, &s, TermType::BVTerm); + + circuit["a"] == a.get_value(); + circuit["b"] == b.get_value(); + + s.print_assertions(); + + bool res = smt_timer(&s); + ASSERT_TRUE(res); + std::vector to_model = { circuit["c"] }; + std::unordered_map model = s.model(to_model); + + bb::fr c_sym = string_to_fr(model["c"], 2); + ASSERT_EQ(c_sym, c.get_value()); +} diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/solver/solver.cpp b/barretenberg/cpp/src/barretenberg/smt_verification/solver/solver.cpp index acd855ad69d..2219a05b0d4 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/solver/solver.cpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/solver/solver.cpp @@ -48,7 +48,7 @@ std::unordered_map Solver::model(std::unordered_map Solver::model(std::vectortype == TermType::FFTerm || this->type == TermType::FFITerm) { other != bb::fr(0); + // Random value added to the name to prevent collisions. This value is MD5('Aztec') STerm res = Var("df8b586e3fa7a1224ec95a886e17a7da_div_" + static_cast(*this) + "_" + static_cast(other), this->solver, @@ -176,6 +177,7 @@ void STerm::operator/=(const STerm& other) } if (this->type == TermType::FFTerm || this->type == TermType::FFITerm) { other != bb::fr(0); + // Random value added to the name to prevent collisions. This value is MD5('Aztec') STerm res = Var("df8b586e3fa7a1224ec95a886e17a7da_div_" + static_cast(*this) + "_" + static_cast(other), this->solver, diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/util/smt_util.cpp b/barretenberg/cpp/src/barretenberg/smt_verification/util/smt_util.cpp index 91a59608f5f..2a2ec75c54b 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/util/smt_util.cpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/util/smt_util.cpp @@ -1,5 +1,41 @@ #include "smt_util.hpp" +/** + * @brief Converts a string of an arbitrary base to fr. + * Note: there should be no prefix + * + * @param number string to be converted + * @param base base representation of the string + * @param step power n such that base^n <= 2^64. If base = 2, 10, 16. May remain undeclared. + * @return bb::fr + */ +bb::fr string_to_fr(const std::string& number, int base, size_t step) +{ + bb::fr res = 0; + char* ptr = nullptr; + if (base == 2) { + step = 64; + } else if (base == 16) { + step = 4; + } else if (base == 10) { + step = 19; + } else if (step == 0) { + info("Step should be non zero"); + return 0; + } + + size_t i = number[0] == '-' ? 1 : 0; + bb::fr step_power = bb::fr(base).pow(step); + for (; i < number.size(); i += step) { + std::string slice = number.substr(i, step); + bb::fr cur_power = i + step > number.size() ? bb::fr(base).pow(number.size() - i) : step_power; + res *= cur_power; + res += std::strtoull(slice.data(), &ptr, base); + } + res = number[0] == '-' ? -res : res; + return res; +} + /** * @brief Get pretty formatted result of the solver work * @@ -13,11 +49,13 @@ * @param c2 the copy of the first circuit with changed tag * @param s solver * @param fname file to store the resulting witness if succeded + * @param pack flags out to pack the resulting witness using msgpack */ void default_model(const std::vector& special, smt_circuit::CircuitBase& c1, smt_circuit::CircuitBase& c2, - const std::string& fname) + const std::string& fname, + bool pack) { std::vector vterms1; std::vector vterms2; @@ -35,38 +73,42 @@ void default_model(const std::vector& special, std::fstream myfile; myfile.open(fname, std::ios::out | std::ios::trunc | std::ios::binary); myfile << "w12 = {" << std::endl; + + std::vector> packed_witness; + packed_witness.reserve(c1.get_num_vars()); + int base = c1.type == smt_terms::TermType::BVTerm ? 2 : 10; + for (uint32_t i = 0; i < c1.get_num_vars(); i++) { std::string vname1 = vterms1[i].toString(); std::string vname2 = vterms2[i].toString(); - if (c1.real_variable_index[i] == i) { - myfile << "{" << mmap1[vname1] << ", " << mmap2[vname2] << "}"; - myfile << ", // " << vname1 << ", " << vname2 << std::endl; - if (mmap1[vname1] != mmap2[vname2]) { - info(RED, "{", mmap1[vname1], ", ", mmap2[vname2], "}", ", // ", vname1, ", ", vname2, RESET); - } - } else { - myfile << "{" << mmap1[vname1] << ", " + mmap2[vname2] << "}"; - myfile << ", // " << vname1 << " ," << vname2 << " -> " << c1.real_variable_index[i] << std::endl; - if (mmap1[vname1] != mmap2[vname2]) { - info(RED, - "{", - mmap1[vname1], - ", ", - mmap2[vname2], - "}", - ", // ", - vname1, - ", ", - vname2, - " -> ", - c1.real_variable_index[i], - RESET); - } + std::string new_line = "{" + mmap1[vname1] + ", " + mmap2[vname2] + "}, // " + vname1 + ", " + vname2; + + if (c1.real_variable_index[i] != i) { + new_line += " -> " + std::to_string(c1.real_variable_index[i]); + } + + if (mmap1[vname1] != mmap2[vname2]) { + info(RED, new_line, RESET); } + myfile << new_line << std::endl; + ; + + packed_witness.push_back({ string_to_fr(mmap1[vname1], base), string_to_fr(mmap2[vname2], base) }); } myfile << "};"; myfile.close(); + if (pack) { + msgpack::sbuffer buffer; + msgpack::pack(buffer, packed_witness); + + std::fstream myfile; + myfile.open(fname + ".pack", std::ios::out | std::ios::trunc | std::ios::binary); + + myfile.write(buffer.data(), static_cast(buffer.size())); + myfile.close(); + } + std::unordered_map vterms; for (const auto& vname : special) { vterms.insert({ vname + "_1", c1[vname] }); @@ -91,10 +133,12 @@ void default_model(const std::vector& special, * @param c first circuit * @param s solver * @param fname file to store the resulting witness if succeded + * @param pack flags out to pack the resulting witness using msgpack */ void default_model_single(const std::vector& special, smt_circuit::CircuitBase& c, - const std::string& fname) + const std::string& fname, + bool pack) { std::vector vterms; vterms.reserve(c.get_num_vars()); @@ -108,17 +152,34 @@ void default_model_single(const std::vector& special, std::fstream myfile; myfile.open(fname, std::ios::out | std::ios::trunc | std::ios::binary); myfile << "w = {" << std::endl; + + std::vector packed_witness; + packed_witness.reserve(c.get_num_vars()); + int base = c.type == smt_terms::TermType::BVTerm ? 2 : 10; + for (size_t i = 0; i < c.get_num_vars(); i++) { std::string vname = vterms[i].toString(); - if (c.real_variable_index[i] == i) { - myfile << mmap[vname] << ", // " << vname << std::endl; - } else { - myfile << mmap[vname] << ", // " << vname << " -> " << c.real_variable_index[i] << std::endl; + std::string new_line = mmap[vname] + ", // " + vname; + if (c.real_variable_index[i] != i) { + new_line += " -> " + std::to_string(c.real_variable_index[i]); } + myfile << new_line << std::endl; + packed_witness.push_back(string_to_fr(mmap[vname], base)); } myfile << "};"; myfile.close(); + if (pack) { + msgpack::sbuffer buffer; + msgpack::pack(buffer, packed_witness); + + std::fstream myfile; + myfile.open(fname + ".pack", std::ios::out | std::ios::trunc | std::ios::binary); + + myfile.write(buffer.data(), static_cast(buffer.size())); + myfile.close(); + } + std::unordered_map vterms1; for (const auto& vname : special) { vterms1.insert({ vname, c[vname] }); @@ -130,6 +191,62 @@ void default_model_single(const std::vector& special, } } +/** + * @brief Import witness, obtained by solver, from file. + * @details Imports the witness, that was packed by default_model function + * + * @param fname + * @return std::vector> + */ +std::vector> import_witness(const std::string& fname) +{ + std::ifstream fin; + fin.open(fname, std::ios::ate | std::ios::binary); + if (!fin.is_open()) { + throw std::invalid_argument("file not found"); + } + if (fin.tellg() == -1) { + throw std::invalid_argument("something went wrong"); + } + + uint64_t fsize = static_cast(fin.tellg()); + fin.seekg(0, std::ios_base::beg); + + std::vector> res; + char* encoded_data = new char[fsize]; + fin.read(encoded_data, static_cast(fsize)); + msgpack::unpack(encoded_data, fsize).get().convert(res); + return res; +} + +/** + * @brief Import witness, obtained by solver, from file. + * @details Imports the witness, that was packed by default_model_single function + * + * @param fname + * @return std::vector> + */ +std::vector import_witness_single(const std::string& fname) +{ + std::ifstream fin; + fin.open(fname, std::ios::ate | std::ios::binary); + if (!fin.is_open()) { + throw std::invalid_argument("file not found"); + } + if (fin.tellg() == -1) { + throw std::invalid_argument("something went wrong"); + } + + uint64_t fsize = static_cast(fin.tellg()); + fin.seekg(0, std::ios_base::beg); + + std::vector res; + char* encoded_data = new char[fsize]; + fin.read(encoded_data, static_cast(fsize)); + msgpack::unpack(encoded_data, fsize).get().convert(res); + return res; +} + /** * @brief Get the solver result and amount of time * that it took to solve. diff --git a/barretenberg/cpp/src/barretenberg/smt_verification/util/smt_util.hpp b/barretenberg/cpp/src/barretenberg/smt_verification/util/smt_util.hpp index cf0521b88f0..dcf08418028 100644 --- a/barretenberg/cpp/src/barretenberg/smt_verification/util/smt_util.hpp +++ b/barretenberg/cpp/src/barretenberg/smt_verification/util/smt_util.hpp @@ -9,11 +9,16 @@ void default_model(const std::vector& special, smt_circuit::CircuitBase& c1, smt_circuit::CircuitBase& c2, - const std::string& fname = "witness.out"); + const std::string& fname = "witness.out", + bool pack = true); void default_model_single(const std::vector& special, smt_circuit::CircuitBase& c, - const std::string& fname = "witness.out"); + const std::string& fname = "witness.out", + bool pack = true); bool smt_timer(smt_solver::Solver* s); std::pair, std::vector> base4(uint32_t el); -void fix_range_lists(bb::UltraCircuitBuilder& builder); \ No newline at end of file +void fix_range_lists(bb::UltraCircuitBuilder& builder); +bb::fr string_to_fr(const std::string& number, int base, size_t step = 0); +std::vector> import_witness(const std::string& fname); +std::vector import_witness_single(const std::string& fname); \ No newline at end of file From 6c19c7eb91acc47106549fa7943f59d2dca3e0ce Mon Sep 17 00:00:00 2001 From: guipublic <47281315+guipublic@users.noreply.github.com> Date: Wed, 31 Jul 2024 12:57:07 +0200 Subject: [PATCH 18/35] fix: handle properly invalid witness assignment in ec add (#7690) Apply the strategy added used for MSM in PR #7653 in regard to invalid witness assignment for grumpking points with constant or witness input, also for ec add. --- .../dsl/acir_format/ec_operations.cpp | 38 ++------------- .../dsl/acir_format/multi_scalar_mul.cpp | 43 +++-------------- .../dsl/acir_format/witness_constant.cpp | 48 +++++++++++++++++++ .../dsl/acir_format/witness_constant.hpp | 9 ++++ 4 files changed, 67 insertions(+), 71 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/dsl/acir_format/witness_constant.cpp diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.cpp index cd05eb150ac..9083e8eb044 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ec_operations.cpp @@ -12,42 +12,12 @@ void create_ec_add_constraint(Builder& builder, const EcAdd& input, bool has_val { // Input to cycle_group points using cycle_group_ct = bb::stdlib::cycle_group; - using bool_ct = bb::stdlib::bool_t; - auto x1 = to_field_ct(input.input1_x, builder); - auto y1 = to_field_ct(input.input1_y, builder); - auto x2 = to_field_ct(input.input2_x, builder); + auto input1_point = to_grumpkin_point( + input.input1_x, input.input1_y, input.input1_infinite, has_valid_witness_assignments, builder); + auto input2_point = to_grumpkin_point( + input.input2_x, input.input2_y, input.input2_infinite, has_valid_witness_assignments, builder); - auto y2 = to_field_ct(input.input2_y, builder); - - auto infinite1 = bool_ct(to_field_ct(input.input1_infinite, builder)); - - auto infinite2 = bool_ct(to_field_ct(input.input2_infinite, builder)); - - if (!has_valid_witness_assignments) { - auto g1 = bb::grumpkin::g1::affine_one; - // We need to have correct values representing points on the curve - if (!x1.is_constant()) { - builder.variables[x1.witness_index] = g1.x; - } - if (!y1.is_constant()) { - builder.variables[y1.witness_index] = g1.y; - } - if (!infinite1.is_constant()) { - builder.variables[infinite1.witness_index] = bb::fr(0); - } - if (!x2.is_constant()) { - builder.variables[x2.witness_index] = g1.x; - } - if (!y2.is_constant()) { - builder.variables[y2.witness_index] = g1.y; - } - if (!infinite2.is_constant()) { - builder.variables[infinite2.witness_index] = bb::fr(0); - } - } - cycle_group_ct input1_point(x1, y1, infinite1); - cycle_group_ct input2_point(x2, y2, infinite2); // Addition cycle_group_ct result = input1_point + input2_point; cycle_group_ct standard_result = result.get_standard_form(); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.cpp index 776baf67227..ef7e5c6b606 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/multi_scalar_mul.cpp @@ -18,50 +18,18 @@ void create_multi_scalar_mul_constraint(Builder& builder, using cycle_group_ct = stdlib::cycle_group; using cycle_scalar_ct = typename stdlib::cycle_group::cycle_scalar; using field_ct = stdlib::field_t; - using bool_ct = stdlib::bool_t; std::vector points; std::vector scalars; for (size_t i = 0; i < input.points.size(); i += 3) { // Instantiate the input point/variable base as `cycle_group_ct` - field_ct point_x; - field_ct point_y; - bool_ct infinite; + cycle_group_ct input_point = to_grumpkin_point( + input.points[i], input.points[i + 1], input.points[i + 2], has_valid_witness_assignments, builder); - point_x = to_field_ct(input.points[i], builder); - point_y = to_field_ct(input.points[i + 1], builder); - infinite = bool_ct(to_field_ct(input.points[i + 2], builder)); - - // When we do not have the witness assignments, we set is_infinite value to true if it is not constant - // else default values would give a point which is not on the curve and this will fail verification - if (!has_valid_witness_assignments) { - if (!input.points[i + 2].is_constant) { - builder.variables[input.points[i + 2].index] = fr(1); - } else if (input.points[i + 2].value == fr::zero() && - !(input.points[i].is_constant || input.points[i + 1].is_constant)) { - // else, if is_infinite is false, but the coordinates (x, y) are witness - // then we set their value so to a curve point. - auto g1 = bb::grumpkin::g1::affine_one; - builder.variables[input.points[i].index] = g1.x; - builder.variables[input.points[i + 1].index] = g1.y; - } - } - - cycle_group_ct input_point(point_x, point_y, infinite); - // Reconstruct the scalar from the low and high limbs - field_ct scalar_low_as_field; - field_ct scalar_high_as_field; - if (input.scalars[2 * (i / 3)].is_constant) { - scalar_low_as_field = field_ct(input.scalars[2 * (i / 3)].value); - } else { - scalar_low_as_field = field_ct::from_witness_index(&builder, input.scalars[2 * (i / 3)].index); - } - if (input.scalars[2 * (i / 3) + 1].is_constant) { - scalar_high_as_field = field_ct(input.scalars[2 * (i / 3) + 1].value); - } else { - scalar_high_as_field = field_ct::from_witness_index(&builder, input.scalars[2 * (i / 3) + 1].index); - } + // Reconstruct the scalar from the low and high limbs + field_ct scalar_low_as_field = to_field_ct(input.scalars[2 * (i / 3)], builder); + field_ct scalar_high_as_field = to_field_ct(input.scalars[2 * (i / 3) + 1], builder); cycle_scalar_ct scalar(scalar_low_as_field, scalar_high_as_field); // Add the point and scalar to the vectors @@ -70,6 +38,7 @@ void create_multi_scalar_mul_constraint(Builder& builder, } // Call batch_mul to multiply the points and scalars and sum the results auto output_point = cycle_group_ct::batch_mul(points, scalars).get_standard_form(); + // Add the constraints and handle constant values if (output_point.is_point_at_infinity().is_constant()) { builder.fix_witness(input.out_point_is_infinite, output_point.is_point_at_infinity().get_value()); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/witness_constant.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/witness_constant.cpp new file mode 100644 index 00000000000..d199eeb62f8 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/witness_constant.cpp @@ -0,0 +1,48 @@ +#include "witness_constant.hpp" +#include "barretenberg/ecc/curves/bn254/fr.hpp" + +namespace acir_format { + +using namespace bb; +using namespace bb::stdlib; +template +bb::stdlib::cycle_group to_grumpkin_point(const WitnessOrConstant& input_x, + const WitnessOrConstant& input_y, + const WitnessOrConstant& input_infinite, + bool has_valid_witness_assignments, + Builder& builder) +{ + using bool_ct = bb::stdlib::bool_t; + auto point_x = to_field_ct(input_x, builder); + auto point_y = to_field_ct(input_y, builder); + auto infinite = bool_ct(to_field_ct(input_infinite, builder)); + + // When we do not have the witness assignments, we set is_infinite value to true if it is not constant + // else default values would give a point which is not on the curve and this will fail verification + if (!has_valid_witness_assignments) { + if (!input_infinite.is_constant) { + builder.variables[input_infinite.index] = fr(1); + } else if (input_infinite.value == fr::zero() && !(input_x.is_constant || input_y.is_constant)) { + // else, if is_infinite is false, but the coordinates (x, y) are witness (and not constant) + // then we set their value to an arbitrary valid curve point (in our case G1). + auto g1 = bb::grumpkin::g1::affine_one; + builder.variables[input_x.index] = g1.x; + builder.variables[input_y.index] = g1.y; + } + } + cycle_group input_point(point_x, point_y, infinite); + return input_point; +} + +template bb::stdlib::cycle_group to_grumpkin_point(const WitnessOrConstant& input_x, + const WitnessOrConstant& input_y, + const WitnessOrConstant& input_infinite, + bool has_valid_witness_assignments, + UltraCircuitBuilder& builder); +template bb::stdlib::cycle_group to_grumpkin_point(const WitnessOrConstant& input_x, + const WitnessOrConstant& input_y, + const WitnessOrConstant& input_infinite, + bool has_valid_witness_assignments, + MegaCircuitBuilder& builder); + +} // namespace acir_format \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/witness_constant.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/witness_constant.hpp index 554c8ddf657..bb60a754d59 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/witness_constant.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/witness_constant.hpp @@ -1,6 +1,8 @@ #pragma once +#include "barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp" #include "barretenberg/serialize/msgpack.hpp" #include "barretenberg/stdlib/primitives/field/field.hpp" +#include "barretenberg/stdlib/primitives/group/cycle_group.hpp" namespace acir_format { template struct WitnessOrConstant { @@ -30,4 +32,11 @@ bb::stdlib::field_t to_field_ct(const WitnessOrConstant& input, Bui return field_ct::from_witness_index(&builder, input.index); } +template +bb::stdlib::cycle_group to_grumpkin_point(const WitnessOrConstant& input_x, + const WitnessOrConstant& input_y, + const WitnessOrConstant& input_infinite, + bool has_valid_witness_assignments, + Builder& builder); + } // namespace acir_format \ No newline at end of file From 8ed8f925a83c7f9e2a73c6377e8e2154a3b6ef36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Wed, 31 Jul 2024 13:48:32 +0200 Subject: [PATCH 19/35] feat: note hashes as points (#7618) --- .../functions/inner_workings.md | 10 +-- .../storage/storage_slots.md | 28 ++++---- .../aztec/src/encrypted_logs/header.nr | 10 +-- .../aztec/src/encrypted_logs/incoming_body.nr | 43 +++++++----- .../aztec/src/encrypted_logs/outgoing_body.nr | 16 +++-- .../aztec/src/encrypted_logs/payload.nr | 67 +++++++++---------- .../aztec-nr/aztec/src/generators.nr | 17 ++++- .../aztec/src/history/public_storage.nr | 10 +-- .../aztec/src/keys/point_to_symmetric_key.nr | 13 ++-- .../aztec-nr/aztec/src/note/lifecycle.nr | 12 ++-- .../aztec-nr/aztec/src/note/note_header.nr | 15 +++-- .../aztec-nr/aztec/src/note/note_interface.nr | 3 +- .../aztec-nr/aztec/src/note/utils.nr | 57 ++++++++-------- .../src/oracle/get_public_data_witness.nr | 6 +- .../aztec-nr/aztec/src/oracle/notes.nr | 12 ++-- .../aztec/src/test/helpers/cheatcodes.nr | 6 +- .../src/test/helpers/test_environment.nr | 6 +- .../aztec/src/test/mocks/mock_note.nr | 7 +- .../aztec-nr/aztec/src/utils/point.nr | 4 +- .../aztec-nr/value-note/src/value_note.nr | 4 ++ .../pending_note_hashes_contract/src/main.nr | 2 +- .../private_token_contract/src/main.nr | 18 ++--- .../private_token_contract/src/test/utils.nr | 1 - .../src/types/token_note.nr | 24 +++---- .../src/note_hash_read_request_reset.nr | 18 ++--- .../crates/types/src/constants.nr | 5 +- .../crates/types/src/hash.nr | 4 +- .../crates/types/src/storage/map.nr | 17 +++++ .../src/transforms/note_interface.rs | 26 ++++--- noir/noir-repo/noir_stdlib/src/hash/mod.nr | 2 +- .../aztec.js/src/utils/cheat_codes.ts | 11 ++- .../logs/l1_payload/encrypt_buffer.test.ts | 2 +- .../l1_payload/encrypted_log_header.test.ts | 2 +- .../encrypted_event_log_incoming_body.test.ts | 2 +- .../encrypted_note_log_incoming_body.test.ts | 4 +- .../encrypted_log_outgoing_body.test.ts | 2 +- .../src/logs/l1_payload/tagged_log.test.ts | 5 +- yarn-project/circuits.js/src/constants.gen.ts | 5 +- .../circuits.js/src/hash/hash.test.ts | 4 +- yarn-project/circuits.js/src/hash/hash.ts | 29 ++------ yarn-project/circuits.js/src/hash/index.ts | 1 + .../circuits.js/src/hash/map_slot.test.ts | 25 +++++++ yarn-project/circuits.js/src/hash/map_slot.ts | 18 +++++ ...build_note_hash_read_request_hints.test.ts | 8 +-- .../src/composed/e2e_aztec_js_browser.test.ts | 10 ++- .../end-to-end/src/e2e_block_building.test.ts | 2 +- .../e2e_pending_note_hashes_contract.test.ts | 2 +- yarn-project/foundation/src/fields/point.ts | 13 ---- .../src/database/incoming_note_dao.test.ts | 4 +- .../pxe/src/database/incoming_note_dao.ts | 10 +-- .../src/database/outgoing_note_dao.test.ts | 4 +- .../pxe/src/database/outgoing_note_dao.ts | 10 +-- .../src/note_processor/note_processor.test.ts | 2 +- .../src/note_processor/produce_note_dao.ts | 16 ++--- .../pxe/src/pxe_service/pxe_service.ts | 8 +-- .../pxe/src/simulator_oracle/index.ts | 4 +- .../simulator/src/acvm/oracle/oracle.ts | 8 +-- .../simulator/src/acvm/oracle/typed_oracle.ts | 8 +-- .../src/client/client_execution_context.ts | 16 ++--- .../simulator/src/client/db_oracle.ts | 4 +- .../src/client/execution_note_cache.ts | 16 ++--- .../src/client/private_execution.test.ts | 65 +++++++++--------- .../simulator/src/client/simulator.test.ts | 16 ++--- .../simulator/src/client/simulator.ts | 12 ++-- .../simulator/src/client/test_utils.ts | 35 ++++++++++ .../client/unconstrained_execution.test.ts | 2 +- yarn-project/simulator/src/index.ts | 1 - .../simulator/src/public/fee_payment.ts | 6 +- yarn-project/simulator/src/utils.ts | 18 ----- yarn-project/txe/src/oracle/txe_oracle.ts | 16 ++--- .../txe/src/txe_service/txe_service.ts | 12 ++-- 71 files changed, 497 insertions(+), 404 deletions(-) create mode 100644 yarn-project/circuits.js/src/hash/map_slot.test.ts create mode 100644 yarn-project/circuits.js/src/hash/map_slot.ts create mode 100644 yarn-project/simulator/src/client/test_utils.ts delete mode 100644 yarn-project/simulator/src/utils.ts diff --git a/docs/docs/aztec/concepts/smart_contracts/functions/inner_workings.md b/docs/docs/aztec/concepts/smart_contracts/functions/inner_workings.md index 8b01fa45062..02e5b0a5984 100644 --- a/docs/docs/aztec/concepts/smart_contracts/functions/inner_workings.md +++ b/docs/docs/aztec/concepts/smart_contracts/functions/inner_workings.md @@ -192,7 +192,7 @@ When a struct is annotated with `#[aztec(note)]`, the Aztec macro applies a seri - `serialize_content` and `deserialize_content` - `get_header` and `set_header` - `get_note_type_id` - - `compute_note_content_hash` + - `compute_note_hiding_point` - `to_be_bytes` - A `properties` method in the note's implementation @@ -219,7 +219,7 @@ struct CustomNote { } ``` -### After expansaion +### After expansion ```rust impl CustomNote { @@ -248,10 +248,10 @@ impl CustomNote { self.header = header; } - fn compute_note_content_hash(self: CustomNote) -> Field { - aztec::hash::pedersen_hash( + fn compute_note_hiding_point(self: CustomNote) -> Point { + aztec::hash::pedersen_commitment( self.serialize_content(), - aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH + aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_HIDING_POINT ) } diff --git a/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md b/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md index 6c40b6a681b..35f384bdd25 100644 --- a/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md +++ b/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md @@ -8,7 +8,7 @@ For the case of the example, we will look at what is inserted into the note hash #include_code increase_private_balance noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust -This function is creating a new note and inserting it into the balance set of the recipient `to`. Recall that to ensure privacy, only the note commitment is really inserted into the note hashes tree. To share the contents of the note with `to` the contract can emit an encrypted log (which this one does), or it can require an out-of-band data transfer sharing the information. Below, we will walk through the steps of how the note commitment is computed and inserted into the tree. For this, we don't care about the encrypted log, so we are going to ignore that part of the function call for now. +This function is creating a new note and inserting it into the balance set of the recipient `to`. Recall that to ensure privacy, only the note hash is really inserted into the note hashes tree. To share the contents of the note with `to` the contract can emit an encrypted log (which this one does), or it can require an out-of-band data transfer sharing the information. Below, we will walk through the steps of how the note hash is computed and inserted into the tree. For this, we don't care about the encrypted log, so we are going to ignore that part of the function call for now. Outlining it in more detail below as a sequence diagram, we can see how the calls make their way down the stack. In the end a siloed note hash is computed in the kernel. @@ -30,25 +30,27 @@ sequenceDiagram BalanceSet->>Set: insert(note) Set->>LifeCycle: create_note(derived_slot, note) LifeCycle->>LifeCycle: note.header = NoteHeader { contract_address,
storage_slot: derived_slot, nonce: 0, note_hash_counter } - LifeCycle->>Utils: compute_inner_note_hash(note) - Utils->>TokenNote: note.compute_note_content_hash() - TokenNote->>Utils: note_hash = H(amount, to, randomness) - Utils->>NoteHash: compute_inner_hash(derived_slot, note_hash) - NoteHash->>LifeCycle: inner_note_hash = H(derived_slot, note_hash) - LifeCycle->>Context: push_note_hash(inner_note_hash) + LifeCycle->>Utils: compute_slotted_note_hash(note) + Utils->>TokenNote: note.compute_note_hiding_point() + TokenNote->>Utils: note_hiding_point = MSM([G_amt, G_to, G_rand], [amount, to, randomness]) + Utils->>NoteHash: compute_slotted_note_hash(derived_slot, note_hiding_point) + NoteHash->>LifeCycle: slotted_note_hash = CURVE_ADD(derived_slot_point, note_hiding_point).x + LifeCycle->>Context: push_note_hash(slotted_note_hash) end - Context->>Kernel: siloed_note_hash = H(contract_address, inner_note_hash) + Context->>Kernel: siloed_note_hash = H(contract_address, slotted_note_hash) ``` -Notice the `siloed_note_hash` at the very end. It's a commitment that will be inserted into the note hashes tree. To clarify what this really is, we "unroll" the values to their simplest components. This gives us a better idea around what is actually inserted into the tree. +Notice the `siloed_note_hash` at the very end. It's a hash that will be inserted into the note hashes tree. To clarify what this really is, we "unroll" the values to their simplest components. This gives us a better idea around what is actually inserted into the tree. ```rust -siloed_note_hash = H(contract_address, inner_note_hash) -siloed_note_hash = H(contract_address, H(derived_slot, note_hash)) -siloed_note_hash = H(contract_address, H(H(map_slot, to), note_hash)) -siloed_note_hash = H(contract_address, H(H(map_slot, to), H(amount, to, randomness))) +siloed_note_hash = H(contract_address, slotted_note_hash) +siloed_note_hash = H(contract_address, CURVE_ADD(derived_slot_point, note_hiding_point).x) +siloed_note_hash = H(contract_address, CURVE_ADD(MSM([G_slot], [derived_slot]), note_hiding_point).x) +siloed_note_hash = H(contract_address, CURVE_ADD(MSM([G_slot], [derived_slot]), MSM([G_amt, G_to, G_rand], [amount, to, randomness])).x) ``` +CURVE_ADD is a point addition and MSM is a multi scalar multiplication on a grumpkin curve and G_* values are generators. + And `to` is the actor who receives the note, `amount` of the note and `randomness` is the randomness used to make the note hiding. Without the `randomness` the note could just as well be plaintext (computational cost of a preimage attack would be trivial in such a case). :::info 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 386e2338a6f..66fa4d22c43 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr @@ -29,7 +29,7 @@ impl EncryptedLogHeader { } #[test] -fn test_encrypted_log_header() { +fn test_encrypted_log_header_matches_noir() { let address = AztecAddress::from_field(0xdeadbeef); let header = EncryptedLogHeader::new(address); let secret = Scalar { @@ -44,9 +44,11 @@ fn test_encrypted_log_header() { let ciphertext = header.compute_ciphertext(secret, point); - let expected_header_ciphertext = [ - 166, 212, 106, 246, 139, 59, 228, 9, 133, 152, 127, 172, 141, 166, 237, 199, 55, 203, 226, 19, 114, 103, 58, 237, 108, 231, 35, 198, 54, 61, 190, 255, 241, 225, 151, 180, 6, 163, 124, 27, 151, 78, 237, 65, 120, 106, 255, 236 + // The following value was generated by `encrypted_log_header.test.ts`. + // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data. + let expected_header_ciphertext_from_typescript = [ + 226, 240, 253, 6, 28, 52, 19, 131, 33, 132, 178, 212, 245, 62, 14, 190, 194, 44, 7, 131, 160, 83, 64, 181, 98, 38, 153, 214, 62, 171, 253, 161, 111, 191, 28, 247, 216, 26, 222, 171, 176, 218, 48, 209, 73, 89, 200, 209 ]; - assert_eq(ciphertext, expected_header_ciphertext); + assert_eq(ciphertext, expected_header_ciphertext_from_typescript); } diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr index 6b25525a7ae..ab96b9d36bc 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr @@ -37,15 +37,14 @@ impl EncryptedLogIncomingBody { } mod test { - use crate::encrypted_logs::incoming_body::EncryptedLogIncomingBody; use dep::protocol_types::{ - address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER, - scalar::Scalar, point::Point, traits::Serialize, abis::event_selector::EventSelector + address::AztecAddress, scalar::Scalar, point::Point, traits::Serialize, + abis::event_selector::EventSelector }; use crate::{ note::{note_header::NoteHeader, note_interface::NoteInterface}, - event::event_interface::EventInterface, oracle::unsafe_rand::unsafe_rand, + encrypted_logs::incoming_body::EncryptedLogIncomingBody, event::event_interface::EventInterface, context::PrivateContext }; @@ -60,7 +59,9 @@ mod test { global ADDRESS_NOTE_BYTES_LEN = 32 * 3 + 64; impl NoteInterface for AddressNote { - fn compute_note_content_hash(_self: Self) -> Field {1} + fn compute_note_hiding_point(self) -> Point { + crate::generators::Ga1 + } fn get_note_type_id() -> Field { 1 @@ -112,7 +113,8 @@ mod test { } #[test] - fn test_encrypted_note_log_incoming_body() { + fn test_encrypted_note_log_incoming_body_matches_typescript() { + // All the values in this test were copied over from `encrypted_note_log_incoming_body.test.ts` let note = AddressNote::new( AztecAddress::from_field(0x1), AztecAddress::from_field(0x2), @@ -131,18 +133,25 @@ mod test { is_infinite: false }; + /// 1. `EncryptedLogIncomingBody::from_note` calls `note.to_be_bytes(storage_slot)` function which serializes + /// the note to bytes - note that in the case of `AddressNote` the `to_be_bytes` function was automatically + /// implemented by Aztec macros. let body = EncryptedLogIncomingBody::from_note(note, storage_slot); + /// 2. `body.compute_ciphertext(...)` function then derives symmetric key from `eph_sk` and `ivpk` and encrypts + // the note plaintext using AES-128. let ciphertext = body.compute_ciphertext(eph_sk, ivpk); - let expected_note_body_ciphertext = [ - 166, 212, 106, 246, 139, 59, 228, 9, 133, 152, 127, 172, 141, 166, 237, 199, 195, 85, 255, 81, 66, 72, 192, 192, 96, 10, 54, 139, 136, 153, 252, 114, 248, 128, 253, 66, 249, 16, 71, 45, 2, 213, 250, 193, 241, 75, 90, 70, 39, 26, 104, 139, 20, 45, 1, 1, 166, 72, 133, 55, 247, 142, 150, 215, 217, 224, 84, 23, 245, 71, 207, 166, 136, 34, 221, 76, 90, 166, 44, 217, 246, 98, 157, 34, 198, 164, 99, 117, 15, 185, 145, 231, 189, 140, 201, 241, 135, 94, 71, 131, 156, 86, 144, 131, 248, 242, 83, 101, 18, 189, 1, 94, 25, 238, 76, 106, 85, 205, 4, 70, 21, 9, 64, 63, 27, 164, 73, 181, 75, 199, 86, 255, 105, 239, 216, 34, 217, 184, 154, 76, 67, 1, 210, 251, 23, 185, 114, 146, 195, 28, 76, 219, 150, 175, 37, 76, 144, 227, 99, 243, 123, 161, 66, 171, 148, 181, 162, 2, 196, 53, 207, 154, 114, 166, 155, 166 + // The following value was generated by `encrypted_note_log_incoming_body.test.ts`. + // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data. + let note_body_ciphertext_from_typescript = [ + 226, 240, 253, 6, 28, 52, 19, 131, 33, 132, 178, 212, 245, 62, 14, 190, 147, 228, 160, 190, 146, 61, 95, 203, 124, 153, 68, 168, 17, 150, 92, 0, 99, 214, 85, 64, 191, 78, 157, 131, 149, 96, 236, 253, 96, 172, 157, 30, 27, 176, 228, 74, 242, 190, 138, 48, 33, 93, 46, 37, 223, 130, 25, 245, 188, 163, 159, 223, 187, 24, 139, 206, 131, 154, 159, 130, 37, 17, 158, 114, 242, 141, 124, 193, 232, 54, 146, 96, 145, 100, 125, 234, 57, 43, 95, 115, 183, 39, 121, 232, 134, 229, 148, 25, 46, 77, 87, 127, 95, 7, 77, 188, 37, 234, 245, 142, 232, 87, 252, 28, 67, 67, 90, 214, 254, 89, 47, 68, 66, 187, 227, 8, 59, 162, 25, 141, 97, 141, 217, 197, 115, 15, 212, 202, 157, 41, 150, 62, 219, 57, 224, 92, 185, 212, 142, 94, 146, 41, 178, 145, 68, 169, 23, 185, 206, 138, 70, 47, 176, 210, 165, 236, 23, 206, 229, 108 ]; - assert_eq(expected_note_body_ciphertext.len(), ciphertext.len()); + assert_eq(note_body_ciphertext_from_typescript.len(), ciphertext.len()); - for i in 0..expected_note_body_ciphertext.len() { - assert_eq(ciphertext[i], expected_note_body_ciphertext[i]); + for i in 0..note_body_ciphertext_from_typescript.len() { + assert_eq(ciphertext[i], note_body_ciphertext_from_typescript[i]); } } @@ -237,14 +246,16 @@ mod test { let ciphertext = body.compute_ciphertext(eph_sk, ivpk); - let expected_event_body_ciphertext = [ - 166, 212, 106, 246, 139, 59, 228, 9, 133, 152, 127, 172, 141, 166, 237, 199, 195, 85, 255, 81, 66, 72, 192, 192, 96, 10, 54, 139, 136, 153, 252, 114, 248, 128, 253, 66, 249, 16, 71, 45, 2, 213, 250, 193, 241, 75, 90, 70, 19, 153, 62, 117, 71, 55, 48, 114, 160, 232, 97, 118, 93, 53, 145, 92, 0, 225, 51, 81, 156, 69, 72, 224, 10, 89, 32, 121, 167, 197, 84, 245, 188, 235, 143, 202, 179, 197, 164, 121, 11, 105, 116, 239, 46, 222, 50, 138, 112, 237, 97, 8, 176, 199, 1, 151, 89, 218, 60, 45, 91, 85, 16, 38, 195, 127, 157, 182, 0, 10, 232, 184, 148, 76, 244, 63, 40, 222, 219, 139, 236, 169, 213, 17, 32, 210, 50, 6, 5, 83, 80, 1, 111, 246, 197, 83, 166, 71, 31, 246, 234, 75, 12, 151, 227, 247, 143, 229, 95, 219, 159, 75, 174, 232, 64, 7, 102, 76, 207, 45, 143, 208, 101, 113, 175, 37, 83, 166 + // The following value was generated by `encrypted_event_log_incoming_body.test.ts` + // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data. + let event_body_ciphertext_from_typescript = [ + 226, 240, 253, 6, 28, 52, 19, 131, 33, 132, 178, 212, 245, 62, 14, 190, 147, 228, 160, 190, 146, 61, 95, 203, 124, 153, 68, 168, 17, 150, 92, 0, 99, 214, 85, 64, 191, 78, 157, 131, 149, 96, 236, 253, 96, 172, 157, 30, 185, 29, 14, 152, 216, 130, 219, 151, 80, 185, 43, 223, 167, 8, 89, 189, 88, 188, 101, 137, 255, 136, 84, 252, 79, 18, 52, 3, 110, 54, 54, 206, 244, 209, 246, 226, 207, 247, 143, 253, 211, 75, 160, 224, 172, 41, 45, 7, 208, 137, 90, 56, 59, 4, 234, 48, 53, 23, 130, 230, 49, 249, 142, 243, 170, 72, 183, 242, 49, 124, 46, 52, 198, 75, 55, 102, 56, 89, 254, 67, 59, 157, 249, 120, 184, 67, 154, 16, 148, 227, 93, 37, 120, 199, 93, 166, 80, 127, 173, 52, 80, 135, 87, 1, 168, 164, 51, 48, 126, 120, 47, 102, 211, 227, 234, 170, 208, 99, 111, 198, 170, 226, 156, 244, 241, 174, 206, 30 ]; - assert_eq(expected_event_body_ciphertext.len(), ciphertext.len()); + assert_eq(event_body_ciphertext_from_typescript.len(), ciphertext.len()); - for i in 0..expected_event_body_ciphertext.len() { - assert_eq(ciphertext[i], expected_event_body_ciphertext[i]); + for i in 0..event_body_ciphertext_from_typescript.len() { + assert_eq(ciphertext[i], event_body_ciphertext_from_typescript[i]); } } } diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr index 59b6268a816..06de95353a4 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr @@ -17,6 +17,8 @@ impl EncryptedLogOutgoingBody { Self { eph_sk, recipient, recipient_ivpk } } + /// Encrypts ephemeral secret key and recipient's ivpk --> with this information the recipient of outgoing will + /// be able to derive the key with which the incoming log can be decrypted. pub fn compute_ciphertext(self, ovsk_app: Scalar, eph_pk: Point) -> [u8; 144] { // Again, we could compute `eph_pk` here, but we keep the interface more similar // and also make it easier to optimise it later as we just pass it along @@ -68,7 +70,7 @@ mod test { use crate::context::PrivateContext; #[test] - fn test_encrypted_log_outgoing_body() { + fn test_encrypted_log_outgoing_body_matches_typescript() { let eph_sk = Scalar { lo: 0x00000000000000000000000000000000d0d302ee245dfaf2807e604eec4715fe, hi: 0x000000000000000000000000000000000f096b423017226a18461115fa8d34bb @@ -91,13 +93,15 @@ mod test { let ciphertext = body.compute_ciphertext(sender_ovsk_app, eph_pk); - let expected_outgoing_body_ciphertext = [ - 127, 84, 96, 176, 101, 107, 236, 57, 68, 8, 53, 202, 138, 74, 186, 54, 74, 193, 245, 7, 109, 59, 218, 33, 1, 31, 205, 225, 241, 209, 64, 222, 94, 245, 4, 150, 47, 241, 187, 64, 152, 20, 102, 158, 200, 217, 213, 82, 1, 240, 170, 185, 51, 80, 27, 109, 63, 231, 235, 120, 174, 44, 133, 248, 10, 97, 60, 40, 222, 190, 147, 76, 187, 48, 91, 206, 48, 106, 56, 118, 38, 127, 82, 4, 182, 188, 44, 224, 31, 129, 47, 107, 134, 252, 20, 25, 249, 193, 215, 137, 195, 43, 98, 42, 54, 96, 254, 89, 134, 31, 103, 142, 16, 43, 92, 211, 145, 113, 217, 253, 161, 240, 121, 205, 146, 200, 168, 160, 221, 32, 229, 116, 26, 216, 86, 189, 78, 120, 10, 224, 85, 52, 40, 244 + // The following value was generated by `encrypted_log_outgoing_body.test.ts` + // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data. + let outgoing_body_ciphertext_from_typescript = [ + 126, 10, 214, 39, 130, 143, 96, 143, 79, 143, 22, 36, 55, 41, 234, 255, 226, 26, 138, 236, 91, 188, 204, 216, 172, 133, 134, 69, 161, 237, 134, 5, 75, 192, 10, 6, 229, 54, 194, 56, 103, 243, 57, 248, 147, 237, 4, 3, 39, 28, 226, 30, 237, 228, 212, 115, 246, 244, 105, 39, 129, 119, 126, 207, 176, 14, 75, 134, 241, 23, 2, 187, 239, 86, 47, 56, 239, 20, 92, 176, 70, 12, 219, 226, 150, 70, 192, 43, 125, 53, 230, 153, 135, 228, 210, 197, 227, 106, 242, 138, 119, 83, 182, 150, 233, 111, 9, 104, 128, 222, 85, 136, 205, 244, 77, 230, 210, 217, 223, 106, 220, 4, 115, 33, 157, 212, 217, 133, 87, 179, 67, 158, 81, 85, 226, 105, 22, 8, 154, 130, 193, 214, 144, 212 ]; - for i in 0..expected_outgoing_body_ciphertext.len() { - assert_eq(ciphertext[i], expected_outgoing_body_ciphertext[i]); + for i in 0..outgoing_body_ciphertext_from_typescript.len() { + assert_eq(ciphertext[i], outgoing_body_ciphertext_from_typescript[i]); } - assert_eq(expected_outgoing_body_ciphertext.len(), ciphertext.len()); + assert_eq(outgoing_body_ciphertext_from_typescript.len(), ciphertext.len()); } } 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 4c7601db80c..5b3583b7fbd 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr @@ -1,19 +1,16 @@ -use dep::protocol_types::{ - address::AztecAddress, scalar::Scalar, point::Point, - constants::{GENERATOR_INDEX__IVSK_M, GENERATOR_INDEX__OVSK_M}, hash::poseidon2_hash +use dep::protocol_types::{address::AztecAddress, scalar::Scalar, point::Point}; +use std::{ + embedded_curve_ops::fixed_base_scalar_mul as derive_public_key, + hash::from_field_unsafe as fr_to_fq_unsafe, field::bn254::decompose }; -use std::embedded_curve_ops::fixed_base_scalar_mul as derive_public_key; -use std::field::bytes32_to_field; -use crate::oracle::unsafe_rand::unsafe_rand; -use crate::utils::point::point_to_bytes; - -use crate::event::event_interface::EventInterface; -use crate::note::note_interface::NoteInterface; - -use crate::encrypted_logs::{ +use crate::{ + event::event_interface::EventInterface, oracle::unsafe_rand::unsafe_rand, + utils::point::point_to_bytes, note::note_interface::NoteInterface, + encrypted_logs::{ header::EncryptedLogHeader, incoming_body::EncryptedLogIncomingBody, outgoing_body::EncryptedLogOutgoingBody +} }; pub fn compute_encrypted_event_log( @@ -25,9 +22,7 @@ pub fn compute_encrypted_event_log recipient: AztecAddress, event: Event ) -> [u8; OB] where Event: EventInterface { - // @todo Need to draw randomness from the full domain of Fq not only Fr - let eph_sk: Scalar = fr_to_fq(unsafe_rand()); - let eph_pk = derive_public_key(eph_sk); + let (eph_sk, eph_pk) = generate_ephemeral_key_pair(); let header = EncryptedLogHeader::new(contract_address); @@ -78,9 +73,7 @@ pub fn compute_encrypted_note_log( recipient: AztecAddress, note: Note ) -> [u8; M] where Note: NoteInterface { - // @todo Need to draw randomness from the full domain of Fq not only Fr - let eph_sk: Scalar = fr_to_fq(unsafe_rand()); - let eph_pk = derive_public_key(eph_sk); + let (eph_sk, eph_pk) = generate_ephemeral_key_pair(); let header = EncryptedLogHeader::new(contract_address); @@ -122,23 +115,22 @@ pub fn compute_encrypted_note_log( encrypted_bytes } -/// Converts a base field elememt to scalar field element. +/// Converts a base field element to scalar field element. /// This is fine because modulus of the base field is smaller than the modulus of the scalar field. fn fr_to_fq(r: Field) -> Scalar { - let r_bytes = r.to_be_bytes(32); + let (lo, hi) = decompose(r); - let mut high_bytes = [0; 32]; - let mut low_bytes = [0; 32]; - - for i in 0..16 { - high_bytes[16 + i] = r_bytes[i]; - low_bytes[16 + i] = r_bytes[i + 16]; - } + Scalar { lo, hi } +} - let lo = bytes32_to_field(low_bytes); - let hi = bytes32_to_field(high_bytes); +fn generate_ephemeral_key_pair() -> (Scalar, Point) { + // @todo Need to draw randomness from the full domain of Fq not only Fr + // We use the unsafe version of `fr_to_fq` because multi_scalar_mul (called by derive_public_key) will constrain + // the scalars. + let eph_sk = fr_to_fq_unsafe(unsafe_rand()); + let eph_pk = derive_public_key(eph_sk); - Scalar { lo, hi } + (eph_sk, eph_pk) } mod test { @@ -147,7 +139,8 @@ mod test { use std::test::OracleMock; #[test] - fn test_compute_encrypted_note_log() { + fn test_encrypted_note_log_matches_typescript() { + // All the values in this test were copied over from `tagged_log.test.ts` let contract_address = AztecAddress::from_field(0x10f48cd9eff7ae5b209c557c70de2e657ee79166868676b787e9417e19260e04); let storage_slot = 0x0fe46be583b71f4ab5b70c2657ff1d05cccf1d292a9369628d1a194f944e6599; let ovsk_app = 0x1b99ba138fa7ef8a2f122a98dd80c8ee70d447218dd780f45e165ac17ca38a5e; @@ -180,12 +173,14 @@ mod test { note ); - let expected_encrypted_note_log = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 70, 12, 14, 67, 77, 132, 110, 193, 234, 40, 110, 64, 144, 235, 86, 55, 111, 242, 123, 221, 193, 170, 202, 225, 216, 86, 84, 159, 112, 31, 167, 159, 53, 114, 117, 237, 57, 131, 19, 111, 150, 50, 83, 173, 155, 234, 225, 71, 187, 141, 79, 245, 43, 111, 83, 219, 149, 124, 68, 12, 244, 253, 216, 0, 62, 108, 232, 118, 80, 87, 140, 215, 185, 111, 48, 128, 236, 110, 92, 46, 205, 7, 226, 131, 66, 205, 0, 103, 83, 217, 90, 60, 138, 6, 172, 246, 129, 92, 172, 69, 73, 77, 65, 147, 18, 231, 20, 35, 217, 180, 253, 72, 242, 32, 57, 45, 11, 2, 235, 24, 96, 244, 224, 33, 61, 151, 225, 136, 173, 178, 40, 2, 125, 229, 20, 220, 82, 28, 191, 147, 133, 137, 1, 45, 243, 229, 140, 115, 165, 150, 154, 96, 22, 120, 223, 237, 213, 182, 252, 192, 8, 132, 43, 21, 56, 243, 116, 144, 182, 75, 16, 30, 222, 222, 60, 205, 147, 214, 53, 41, 62, 53, 16, 147, 117, 72, 169, 220, 125, 208, 210, 45, 65, 233, 40, 87, 88, 140, 237, 200, 161, 9, 86, 82, 128, 191, 51, 4, 195, 243, 100, 102, 240, 54, 129, 176, 116, 139, 73, 27, 98, 222, 1, 243, 199, 72, 238, 213, 66, 91, 159, 183, 143, 36, 103, 94, 5, 62, 50, 13, 217, 161, 79, 30, 231, 41, 228, 109, 139, 243, 119, 166, 54, 37, 250, 193, 6, 67, 29, 148, 185, 153, 58, 64, 210, 164, 219, 165, 80, 35, 75, 109, 177, 14, 168, 136, 105, 21, 235, 62, 159, 71, 61, 245, 193, 234, 169, 100, 165, 8, 222, 157, 239, 41, 221, 223, 67, 80, 61, 252, 54, 27, 100, 1, 104, 2, 121, 62, 41, 23, 132, 15, 124, 120, 21, 198, 113, 151, 172, 42, 161, 64, 240, 166, 205, 80, 169, 58, 191, 111, 130, 55, 58, 141, 26, 97, 118, 114, 216, 69, 207, 212, 227, 250, 199, 21, 72, 144, 85, 43, 76, 213, 28, 132, 134, 16, 221, 105, 112, 82, 238, 114, 61, 36, 144, 179, 178, 68, 198, 162, 212, 85, 100, 116, 186, 131, 232, 33, 229, 101, 251, 5, 251 + // The following value was generated by `tagged_log.test.ts` + // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data. + let encrypted_note_log_from_typescript = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 70, 12, 14, 67, 77, 132, 110, 193, 234, 40, 110, 64, 144, 235, 86, 55, 111, 242, 123, 221, 193, 170, 202, 225, 216, 86, 84, 159, 112, 31, 167, 126, 79, 51, 186, 47, 71, 253, 172, 99, 112, 241, 59, 197, 241, 107, 186, 232, 87, 187, 230, 171, 62, 228, 234, 42, 51, 145, 146, 238, 242, 42, 71, 206, 13, 244, 66, 111, 195, 20, 203, 98, 148, 204, 242, 145, 183, 156, 29, 141, 54, 44, 220, 194, 35, 229, 16, 32, 204, 211, 49, 142, 112, 82, 202, 116, 241, 254, 146, 42, 217, 20, 189, 70, 228, 182, 171, 205, 104, 27, 99, 171, 28, 91, 244, 21, 30, 130, 240, 5, 72, 174, 124, 97, 197, 157, 248, 204, 203, 140, 171, 181, 152, 130, 169, 179, 41, 52, 173, 45, 43, 198, 1, 152, 72, 158, 249, 11, 41, 9, 160, 48, 78, 123, 132, 203, 140, 215, 13, 22, 201, 88, 255, 139, 154, 76, 20, 63, 134, 125, 108, 239, 208, 63, 59, 33, 117, 139, 225, 184, 0, 64, 153, 21, 131, 204, 111, 41, 84, 23, 144, 222, 245, 200, 12, 234, 11, 48, 10, 221, 20, 252, 38, 122, 40, 249, 66, 248, 197, 198, 209, 79, 20, 59, 66, 197, 215, 16, 18, 145, 228, 239, 124, 81, 67, 103, 49, 196, 58, 228, 195, 64, 199, 243, 184, 112, 173, 29, 196, 215, 77, 217, 85, 82, 149, 113, 76, 201, 93, 95, 148, 37, 95, 222, 233, 210, 150, 1, 182, 28, 132, 59, 148, 156, 129, 36, 230, 55, 199, 149, 36, 205, 103, 212, 60, 151, 141, 10, 151, 222, 151, 180, 43, 91, 148, 201, 110, 165, 10, 238, 32, 134, 235, 99, 216, 200, 182, 31, 22, 156, 18, 209, 222, 172, 239, 193, 212, 86, 99, 62, 70, 182, 45, 175, 241, 91, 202, 179, 225, 99, 1, 150, 232, 2, 252, 20, 83, 49, 132, 162, 93, 116, 212, 87, 71, 211, 58, 159, 163, 40, 253, 31, 3, 192, 48, 14, 201, 80, 24, 135, 154, 207, 58, 140, 128, 29, 101, 207, 189, 182, 191, 71, 210, 64, 172, 131, 83, 46, 232, 19, 216, 183, 108, 234, 17, 104, 60, 113, 231, 145, 195, 157, 24 ]; - for i in 0..expected_encrypted_note_log.len() { - assert_eq(log[i], expected_encrypted_note_log[i]); + for i in 0..encrypted_note_log_from_typescript.len() { + assert_eq(log[i], encrypted_note_log_from_typescript[i]); } - assert_eq(expected_encrypted_note_log.len(), log.len()); + assert_eq(encrypted_note_log_from_typescript.len(), log.len()); } } diff --git a/noir-projects/aztec-nr/aztec/src/generators.nr b/noir-projects/aztec-nr/aztec/src/generators.nr index 02eae3307fb..7af58db4602 100644 --- a/noir-projects/aztec-nr/aztec/src/generators.nr +++ b/noir-projects/aztec-nr/aztec/src/generators.nr @@ -4,17 +4,28 @@ use dep::protocol_types::point::Point; global Ga1 = Point { x: 0x30426e64aee30e998c13c8ceecda3a77807dbead52bc2f3bf0eae851b4b710c1, y: 0x113156a068f603023240c96b4da5474667db3b8711c521c748212a15bc034ea6, is_infinite: false }; global Ga2 = Point { x: 0x2825c79cc6a5cbbeef7d6a8f1b6a12b312aa338440aefeb4396148c89147c049, y: 0x129bfd1da54b7062d6b544e7e36b90736350f6fba01228c41c72099509f5701e, is_infinite: false }; global Ga3 = Point { x: 0x0edb1e293c3ce91bfc04e3ceaa50d2c541fa9d091c72eb403efb1cfa2cb3357f, y: 0x1341d675fa030ece3113ad53ca34fd13b19b6e9762046734f414824c4d6ade35, is_infinite: false }; +// If you change this update `G_SLOT` in `yarn-project/simulator/src/client/test_utils.ts` as well +global G_slot = Point { x: 0x041223147b680850dc82e8a55a952d4df20256fe0593d949a9541ca00f0abf15, y: 0x0a8c72e60d0e60f5d804549d48f3044d06140b98ed717a9b532af630c1530791, is_infinite: false }; + +// TODO(#7551): nuke this func - is only temporarily used in note_interface.rs before we get some AVM compatible +// hash func hashing to a point +pub fn field_to_point(slot_preimage: Field) -> Point { + // We use the unsafe version because the multi_scalar_mul will constrain the scalars. + let slot_preimage_scalar = dep::std::hash::from_field_unsafe(slot_preimage); + dep::std::embedded_curve_ops::multi_scalar_mul([G_slot], [slot_preimage_scalar]) +} mod test { - use crate::generators::{Ga1, Ga2, Ga3}; + use crate::generators::{Ga1, Ga2, Ga3, G_slot}; use dep::protocol_types::point::Point; use std::hash::derive_generators; #[test] -fn test_generators() { - let generators: [Point; 3] = derive_generators("aztec_nr_generators".as_bytes(), 0); + fn test_generators() { + let generators: [Point; 4] = derive_generators("aztec_nr_generators".as_bytes(), 0); assert_eq(generators[0], Ga1); assert_eq(generators[1], Ga2); assert_eq(generators[2], Ga3); + assert_eq(generators[3], G_slot); } } diff --git a/noir-projects/aztec-nr/aztec/src/history/public_storage.nr b/noir-projects/aztec-nr/aztec/src/history/public_storage.nr index 6f1922122e7..c07c3d15804 100644 --- a/noir-projects/aztec-nr/aztec/src/history/public_storage.nr +++ b/noir-projects/aztec-nr/aztec/src/history/public_storage.nr @@ -13,7 +13,7 @@ trait PublicStorageHistoricalRead { impl PublicStorageHistoricalRead for Header { fn public_storage_historical_read(self, storage_slot: Field, contract_address: AztecAddress) -> Field { // 1) Compute the leaf slot by siloing the storage slot with the contract address - let public_value_leaf_slot = pedersen_hash( + let public_data_tree_index = pedersen_hash( [contract_address.to_field(), storage_slot], GENERATOR_INDEX__PUBLIC_LEAF_INDEX ); @@ -21,7 +21,7 @@ impl PublicStorageHistoricalRead for Header { // 2) Get the membership witness of the slot let witness = get_public_data_witness( self.global_variables.block_number as u32, - public_value_leaf_slot + public_data_tree_index ); // 3) Extract the value from the witness leaf and check that the storage slot is correct @@ -30,15 +30,15 @@ impl PublicStorageHistoricalRead for Header { // Here we have two cases. Code based on same checks in `validate_public_data_reads` in `base_rollup_inputs` // 1. The value is the same as the one in the witness // 2. The value was never initialized and is zero - let is_less_than_slot = full_field_less_than(preimage.slot, public_value_leaf_slot); - let is_next_greater_than = full_field_less_than(public_value_leaf_slot, preimage.next_slot); + let is_less_than_slot = full_field_less_than(preimage.slot, public_data_tree_index); + let is_next_greater_than = full_field_less_than(public_data_tree_index, preimage.next_slot); let is_max = ((preimage.next_index == 0) & (preimage.next_slot == 0)); let is_in_range = is_less_than_slot & (is_next_greater_than | is_max); let value = if is_in_range { 0 } else { - assert_eq(preimage.slot, public_value_leaf_slot, "Public data slot doesn't match witness"); + assert_eq(preimage.slot, public_data_tree_index, "Public data tree index doesn't match witness"); preimage.value }; diff --git a/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr b/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr index f84dd3fe861..fc27829d578 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr @@ -6,7 +6,6 @@ use std::{hash::sha256, embedded_curve_ops::multi_scalar_mul}; // point is not the only input of the function. Unify naming with TS once we have a better name. pub fn point_to_symmetric_key(secret: Scalar, point: Point) -> [u8; 32] { let shared_secret: Point = multi_scalar_mul([point], [secret]); - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6061): make the func return Point struct directly let shared_secret = point_to_bytes(shared_secret); let mut shared_secret_bytes_with_separator = [0 as u8; 33]; shared_secret_bytes_with_separator = arr_copy_slice(shared_secret, shared_secret_bytes_with_separator, 0); @@ -15,7 +14,7 @@ pub fn point_to_symmetric_key(secret: Scalar, point: Point) -> [u8; 32] { } #[test] -fn check_point_to_symmetric_key() { +fn test_point_to_symmetric_key_matches_noir() { // Value taken from "derive shared secret" test in encrypt_buffer.test.ts let secret = Scalar { lo: 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd, @@ -28,9 +27,11 @@ fn check_point_to_symmetric_key() { }; let key = point_to_symmetric_key(secret, point); - // The following value gets updated when running encrypt_buffer.test.ts with AZTEC_GENERATE_TEST_DATA=1 - let expected_key = [ - 217, 245, 196, 116, 55, 39, 202, 184, 117, 231, 19, 56, 102, 254, 94, 14, 172, 169, 123, 96, 61, 247, 209, 140, 4, 132, 119, 222, 79, 1, 154, 136 + + // The following value was generated by `encrypt_buffer.test.ts`. + // --> Run the test with AZTEC_GENERATE_TEST_DATA=1 flag to update test data. + let key_from_typescript = [ + 251, 232, 177, 34, 2, 174, 35, 92, 165, 118, 168, 3, 153, 140, 46, 210, 203, 154, 184, 158, 236, 33, 95, 77, 93, 120, 72, 88, 190, 209, 64, 159 ]; - assert_eq(key, expected_key); + assert_eq(key, key_from_typescript); } diff --git a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr index 2209157faf9..649d9fe1c54 100644 --- a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr +++ b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr @@ -1,7 +1,7 @@ use crate::context::{PrivateContext, PublicContext}; use crate::note::{ note_header::NoteHeader, note_interface::NoteInterface, - utils::{compute_inner_note_hash, compute_note_hash_for_consumption}, note_emission::NoteEmission + utils::{compute_slotted_note_hash, compute_note_hash_for_consumption}, note_emission::NoteEmission }; use crate::oracle::notes::{notify_created_note, notify_nullified_note}; @@ -15,7 +15,7 @@ pub fn create_note( let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter }; note.set_header(header); - let inner_note_hash = compute_inner_note_hash(*note); + let slotted_note_hash = compute_slotted_note_hash(*note); let serialized_note = Note::serialize_content(*note); assert( @@ -23,13 +23,13 @@ pub fn create_note( storage_slot, Note::get_note_type_id(), serialized_note, - inner_note_hash, + slotted_note_hash, note_hash_counter ) == 0 ); - context.push_note_hash(inner_note_hash); + context.push_note_hash(slotted_note_hash); NoteEmission::new(*note) } @@ -43,9 +43,9 @@ pub fn create_note_hash_from_public( // Public note hashes are transient, but have no side effect counters, so we just need note_hash_counter != 0 let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter: 1 }; note.set_header(header); - let inner_note_hash = compute_inner_note_hash(*note); + let slotted_note_hash = compute_slotted_note_hash(*note); - context.push_note_hash(inner_note_hash); + context.push_note_hash(slotted_note_hash); } pub fn destroy_note( diff --git a/noir-projects/aztec-nr/aztec/src/note/note_header.nr b/noir-projects/aztec-nr/aztec/src/note/note_header.nr index 1cec738dd5c..3db3cc5b62c 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_header.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_header.nr @@ -1,5 +1,6 @@ -use dep::protocol_types::address::AztecAddress; -use dep::protocol_types::traits::{Empty, Eq, Serialize}; +use dep::protocol_types::{address::AztecAddress, traits::{Empty, Eq, Serialize}}; + +global NOTE_HEADER_LENGTH: Field = 4; struct NoteHeader { contract_address: AztecAddress, @@ -31,8 +32,14 @@ impl NoteHeader { } } -impl Serialize<4> for NoteHeader { - fn serialize(self) -> [Field; 4] { +impl Serialize for NoteHeader { + /// The following method is used by implementations of the Serialize trait for notes --> the implementation + // of the Serialize trait for notes needs to be implemented when the note is passed as an argument to a contract + // function --> in that situation the serialize method is called by aztec-nr when computing an arguments hash. + fn serialize(self) -> [Field; NOTE_HEADER_LENGTH] { + // Note: If you change this function don't forget to update implementations of Serialize trait for notes. + // (Serialize trait needs to be implemented for a note when it's passed as an argument to a contract function + // --> then it's used when computing args hash.) [self.contract_address.to_field(), self.nonce, self.storage_slot, self.note_hash_counter as Field] } } diff --git a/noir-projects/aztec-nr/aztec/src/note/note_interface.nr b/noir-projects/aztec-nr/aztec/src/note/note_interface.nr index 317059d90e9..53afa05820c 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_interface.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_interface.nr @@ -1,5 +1,6 @@ use crate::context::PrivateContext; use crate::note::note_header::NoteHeader; +use dep::protocol_types::point::Point; // docs:start:note_interface trait NoteInterface { @@ -14,7 +15,7 @@ trait NoteInterface { fn deserialize_content(fields: [Field; N]) -> Self; // Autogenerated by the #[aztec(note)] macro unless it is overridden by a custom implementation - fn compute_note_content_hash(self) -> Field; + fn compute_note_hiding_point(self) -> Point; // Autogenerated by the #[aztec(note)] macro unless it is overridden by a custom implementation fn get_header(self) -> NoteHeader; diff --git a/noir-projects/aztec-nr/aztec/src/note/utils.nr b/noir-projects/aztec-nr/aztec/src/note/utils.nr index dfe87cc4346..5e8ff069687 100644 --- a/noir-projects/aztec-nr/aztec/src/note/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/note/utils.nr @@ -1,26 +1,32 @@ -use crate::{context::PrivateContext, note::{note_header::NoteHeader, note_interface::NoteInterface}}; +use crate::{ + context::PrivateContext, generators::G_slot, + note::{note_header::NoteHeader, note_interface::NoteInterface} +}; use dep::protocol_types::{ - constants::GENERATOR_INDEX__INNER_NOTE_HASH, hash::{ - pedersen_hash, compute_unique_note_hash, compute_siloed_note_hash as compute_siloed_note_hash, + compute_unique_note_hash, compute_siloed_note_hash as compute_siloed_note_hash, compute_siloed_nullifier as compute_siloed_nullifier_from_preimage }, - utils::arr_copy_slice + point::Point, utils::arr_copy_slice }; +use dep::std::{embedded_curve_ops::multi_scalar_mul, hash::from_field_unsafe}; + +pub fn compute_slotted_note_hash_raw(storage_slot: Field, note_hiding_point: Point) -> Field { + // We use the unsafe version because the multi_scalar_mul will constrain the scalars. + let storage_slot_scalar = from_field_unsafe(storage_slot); + let storage_slot_point = multi_scalar_mul([G_slot], [storage_slot_scalar]); + let slotted_note_hiding_point = storage_slot_point + note_hiding_point; + let slotted_note_hash = slotted_note_hiding_point.x; -pub fn compute_inner_note_hash_from_preimage(storage_slot: Field, note_content_hash: Field) -> Field { - pedersen_hash( - [storage_slot, note_content_hash], - GENERATOR_INDEX__INNER_NOTE_HASH - ) + slotted_note_hash } -pub fn compute_inner_note_hash(note: Note) -> Field where Note: NoteInterface { +pub fn compute_slotted_note_hash(note: Note) -> Field where Note: NoteInterface { let header = note.get_header(); - let note_hash = note.compute_note_content_hash(); + let note_hash = note.compute_note_hiding_point(); - compute_inner_note_hash_from_preimage(header.storage_slot, note_hash) + compute_slotted_note_hash_raw(header.storage_slot, note_hash) } pub fn compute_siloed_nullifier( @@ -33,24 +39,21 @@ pub fn compute_siloed_nullifier( compute_siloed_nullifier_from_preimage(header.contract_address, inner_nullifier) } -fn compute_note_hash_for_read_request_from_innter_and_nonce( - inner_note_hash: Field, - nonce: Field -) -> Field { +fn compute_note_hash_for_read_request_from_slotted_and_nonce(slotted_note_hash: Field, nonce: Field) -> Field { // TODO(#1386): This if-else can be nuked once we have nonces injected from public if (nonce == 0) { // If nonce is zero, that means we are reading a public note. - inner_note_hash + slotted_note_hash } else { - compute_unique_note_hash(nonce, inner_note_hash) + compute_unique_note_hash(nonce, slotted_note_hash) } } pub fn compute_note_hash_for_read_request(note: Note) -> Field where Note: NoteInterface { - let inner_note_hash = compute_inner_note_hash(note); + let slotted_note_hash = compute_slotted_note_hash(note); let nonce = note.get_header().nonce; - compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, nonce) + compute_note_hash_for_read_request_from_slotted_and_nonce(slotted_note_hash, nonce) } pub fn compute_note_hash_for_consumption(note: Note) -> Field where Note: NoteInterface { @@ -60,17 +63,17 @@ pub fn compute_note_hash_for_consumption(note: Not // 2. The note was inserted in a previous transaction, and was inserted in public // 3. The note was inserted in a previous transaction, and was inserted in private - let inner_note_hash = compute_inner_note_hash(note); + let slotted_note_hash = compute_slotted_note_hash(note); if (header.note_hash_counter != 0) { - // If a note is transient, we just read the inner_note_hash (kernel will silo by contract address). - inner_note_hash + // If a note is transient, we just read the slotted_note_hash (kernel will silo by contract address). + slotted_note_hash } else { // If a note is not transient, that means we are reading a settled note (from tree) created in a // previous TX. So we need the siloed_note_hash which has already been hashed with // nonce and then contract address. This hash will match the existing leaf in the note hash // tree, so the kernel can just perform a membership check directly on this hash/leaf. - let unique_note_hash = compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, header.nonce); + let unique_note_hash = compute_note_hash_for_read_request_from_slotted_and_nonce(slotted_note_hash, header.nonce); compute_siloed_note_hash(header.contract_address, unique_note_hash) // IMPORTANT NOTE ON REDUNDANT SILOING BY CONTRACT ADDRESS: The note hash computed above is // "siloed" by contract address. When a note hash is computed solely for the purpose of @@ -92,8 +95,8 @@ pub fn compute_note_hash_and_optionally_a_nullifier [Field; PUBLIC_DATA_WITNESS] {} -unconstrained pub fn get_public_data_witness(block_number: u32, leaf_slot: Field) -> PublicDataWitness { - let fields = get_public_data_witness_oracle(block_number, leaf_slot); +unconstrained pub fn get_public_data_witness(block_number: u32, public_data_tree_index: Field) -> PublicDataWitness { + let fields = get_public_data_witness_oracle(block_number, public_data_tree_index); PublicDataWitness { index: fields[0], leaf_preimage: PublicDataTreeLeafPreimage { slot: fields[1], value: fields[2], next_index: fields[3] as u32, next_slot: fields[4] }, diff --git a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr index 9b7755fd135..5fd6908000a 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr @@ -7,7 +7,7 @@ unconstrained fn notify_created_note_oracle( _storage_slot: Field, _note_type_id: Field, _serialized_note: [Field; N], - _inner_note_hash: Field, + _slotted_note_hash: Field, _counter: u32 ) -> Field {} @@ -15,27 +15,27 @@ unconstrained pub fn notify_created_note( storage_slot: Field, note_type_id: Field, serialized_note: [Field; N], - inner_note_hash: Field, + slotted_note_hash: Field, counter: u32 ) -> Field { notify_created_note_oracle( storage_slot, note_type_id, serialized_note, - inner_note_hash, + slotted_note_hash, counter ) } #[oracle(notifyNullifiedNote)] -unconstrained fn notify_nullified_note_oracle(_nullifier: Field, _inner_note_hash: Field, _counter: u32) -> Field {} +unconstrained fn notify_nullified_note_oracle(_nullifier: Field, _slotted_note_hash: Field, _counter: u32) -> Field {} unconstrained pub fn notify_nullified_note( nullifier: Field, - inner_note_hash: Field, + slotted_note_hash: Field, counter: u32 ) -> Field { - notify_nullified_note_oracle(nullifier, inner_note_hash, counter) + notify_nullified_note_oracle(nullifier, slotted_note_hash, counter) } #[oracle(getNotes)] diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr index e8a03ea7e12..6ce7feabce5 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr @@ -95,8 +95,8 @@ unconstrained pub fn add_nullifiers(contractAddress: AztecAddress, nullifiers: [ oracle_add_nullifiers(contractAddress, nullifiers) } -unconstrained pub fn add_note_hashes(contractAddress: AztecAddress, inner_note_hashes: [Field]) { - oracle_add_note_hashes(contractAddress, inner_note_hashes) +unconstrained pub fn add_note_hashes(contractAddress: AztecAddress, slotted_note_hashes: [Field]) { + oracle_add_note_hashes(contractAddress, slotted_note_hashes) } unconstrained pub fn get_function_selector() -> FunctionSelector { @@ -180,7 +180,7 @@ unconstrained fn oracle_assert_private_call_fails( unconstrained fn oracle_add_nullifiers(contractAddress: AztecAddress, nullifiers: [Field]) {} #[oracle(addNoteHashes)] -unconstrained fn oracle_add_note_hashes(contractAddress: AztecAddress, inner_note_hashes: [Field]) {} +unconstrained fn oracle_add_note_hashes(contractAddress: AztecAddress, slotted_note_hashes: [Field]) {} #[oracle(getFunctionSelector)] unconstrained fn oracle_get_function_selector() -> FunctionSelector {} 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 f5c3436c9fe..923373f2d23 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 @@ -14,7 +14,7 @@ use crate::hash::{hash_args, hash_args_array}; use crate::note::{ note_header::NoteHeader, note_interface::NoteInterface, - utils::{compute_inner_note_hash, compute_note_hash_for_consumption} + utils::{compute_slotted_note_hash, compute_note_hash_for_consumption} }; use crate::oracle::{execution::{get_block_number, get_contract_address}, notes::notify_created_note}; @@ -219,14 +219,14 @@ impl TestEnvironment { let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter }; note.set_header(header); - let inner_note_hash = compute_inner_note_hash(*note); + let slotted_note_hash = compute_slotted_note_hash(*note); let serialized_note = Note::serialize_content(*note); assert( notify_created_note( storage_slot, Note::get_note_type_id(), serialized_note, - inner_note_hash, + slotted_note_hash, note_hash_counter ) == 0 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 f5dd8c400c6..85cc21f9106 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 @@ -1,6 +1,6 @@ use crate::{context::PrivateContext, note::{note_header::NoteHeader, note_interface::NoteInterface}}; -use dep::protocol_types::{address::AztecAddress, traits::Eq}; +use dep::protocol_types::{address::AztecAddress, point::Point, traits::Eq}; global MOCK_NOTE_LENGTH = 1; // MOCK_NOTE_LENGTH * 32 + 32(storage_slot as bytes) + 32(note_type_id as bytes) @@ -23,8 +23,9 @@ impl NoteInterface for MockNote { } } - fn compute_note_content_hash(_self: Self) -> Field { - 0 + fn compute_note_hiding_point(_self: Self) -> Point { + // TODO(#7636): Properly implement these functions. + crate::generators::Ga1 } fn get_header(self) -> NoteHeader { diff --git a/noir-projects/aztec-nr/aztec/src/utils/point.nr b/noir-projects/aztec-nr/aztec/src/utils/point.nr index c2d0d2635d5..20c6af687f8 100644 --- a/noir-projects/aztec-nr/aztec/src/utils/point.nr +++ b/noir-projects/aztec-nr/aztec/src/utils/point.nr @@ -14,7 +14,9 @@ pub fn point_to_bytes(pk: Point) -> [u8; 32] { let mut result = pk.x.to_be_bytes(32); // We store only a "sign" of the y coordinate because the rest can be derived from the x coordinate. To get - // the sign we check if the y coordinate is greater than the curve's order minus 1 divided by 2. + // the sign we check if the y coordinate is less or equal than the curve's order minus 1 divided by 2. + // Ideally we'd do `y <= MOD_DIV_2`, but there's no `lte` function, so instead we do `!(y > MOD_DIV_2)`, which is + // equivalent, and then rewrite that as `!(MOD_DIV_2 < y)`, since we also have no `gt` function. if !BN254_FR_MODULUS_DIV_2.lt(pk.y) { // y is <= (modulus - 1) / 2 so we set the sign bit to 1 // Here we leverage that field fits into 254 bits (log2(Fr.MODULUS) < 254) and given that we serialize Fr to 32 diff --git a/noir-projects/aztec-nr/value-note/src/value_note.nr b/noir-projects/aztec-nr/value-note/src/value_note.nr index 1b135577ec7..5b97967aae1 100644 --- a/noir-projects/aztec-nr/value-note/src/value_note.nr +++ b/noir-projects/aztec-nr/value-note/src/value_note.nr @@ -58,6 +58,10 @@ impl ValueNote { } impl Serialize<7> for ValueNote { + /// The following method needed to be implemented because the note is passed as an argument to a contract function + /// --> the serialize method is called by aztec-nr when computing an arguments hash. + /// Note that when the note is about to be encrypted and emitted as a log the to_be_bytes function auto-implemented + /// by aztec macros is called instead. fn serialize(self) -> [Field; 7] { let header = self.header.serialize(); diff --git a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr index 8c11b8f6986..c6fdf0b9da0 100644 --- a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr @@ -91,7 +91,7 @@ contract PendingNoteHashes { // Nested/inner function to create and insert a note // TESTING: inserts a static randomness value to test notes with - // the same inner note hash are dealt with correctly + // the same slotted note hash are dealt with correctly #[aztec(private)] fn insert_note_static_randomness( amount: Field, diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr index 3692df2c74d..6c0890726d6 100644 --- a/noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr @@ -6,7 +6,7 @@ mod test; contract PrivateToken { use dep::compressed_string::FieldCompressedString; use dep::aztec::{ - note::utils::compute_inner_note_hash_from_preimage, hash::compute_secret_hash, + note::utils::compute_slotted_note_hash_raw, hash::compute_secret_hash, prelude::{NoteGetterOptions, Map, PublicMutable, SharedImmutable, PrivateSet, AztecAddress}, protocol_types::{abis::function_selector::FunctionSelector, point::Point, hash::pedersen_hash}, oracle::unsafe_rand::unsafe_rand, @@ -200,21 +200,21 @@ contract PrivateToken { #[aztec(public)] #[aztec(internal)] fn complete_refund(fee_payer_point: Point, user_point: Point) { - // 1. We get the final note content hashes by calling the `complete_refund` on the note. + // 1. We get the final note hiding points by calling a `complete_refund` function on the note. // We use 1:1 exchange rate between fee juice and token. So using `tx_fee` is enough let tx_fee = context.transaction_fee(); - let (fee_payer_note_content_hash, user_note_content_hash) = TokenNote::complete_refund(fee_payer_point, user_point, tx_fee); + let (fee_payer_note_hiding_point, user_note_hiding_point) = TokenNote::complete_refund(fee_payer_point, user_point, tx_fee); - // 2. Now we "manually" compute the inner note hashes. - let fee_payer_inner_note_hash = compute_inner_note_hash_from_preimage( + // 2. Now we "manually" compute the slotted note hashes. + let fee_payer_slotted_note_hash = compute_slotted_note_hash_raw( PrivateToken::storage().balances.slot, - fee_payer_note_content_hash + fee_payer_note_hiding_point ); - let user_inner_note_hash = compute_inner_note_hash_from_preimage(PrivateToken::storage().balances.slot, user_note_content_hash); + let user_slotted_note_hash = compute_slotted_note_hash_raw(PrivateToken::storage().balances.slot, user_note_hiding_point); // 3. At last we emit the note hashes. - context.push_note_hash(fee_payer_inner_note_hash); - context.push_note_hash(user_inner_note_hash); + context.push_note_hash(fee_payer_slotted_note_hash); + context.push_note_hash(user_slotted_note_hash); // --> Once the tx is settled user and fee recipient can add the notes to their pixies. } diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/test/utils.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/test/utils.nr index 1825f0921d9..f97e2706a79 100644 --- a/noir-projects/noir-contracts/contracts/private_token_contract/src/test/utils.nr +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/test/utils.nr @@ -1,7 +1,6 @@ use dep::aztec::{ hash::compute_secret_hash, prelude::AztecAddress, test::helpers::{cheatcodes, test_environment::TestEnvironment}, - protocol_types::storage::map::derive_storage_slot_in_map, note::{note_getter::{MAX_NOTES_PER_PAGE, view_notes}, note_viewer_options::NoteViewerOptions}, oracle::{execution::get_contract_address, unsafe_rand::unsafe_rand, storage::storage_read}, context::PrivateContext diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr index d2f0ddf2d38..951caecdce9 100644 --- a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr @@ -1,9 +1,9 @@ use dep::aztec::{ + generators::{Ga1 as G_amt, Ga2 as G_npk, Ga3 as G_rnd}, prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, point::Point, scalar::Scalar, hash::poseidon2_hash}, note::utils::compute_note_hash_for_consumption, oracle::unsafe_rand::unsafe_rand, - keys::getters::get_nsk_app, note::note_getter_options::PropertySelector, - generators::{Ga1 as G_amt, Ga2 as G_npk, Ga3 as G_rnd} + keys::getters::get_nsk_app, note::note_getter_options::PropertySelector }; use dep::std::field::bn254::decompose; use dep::std::embedded_curve_ops::multi_scalar_mul; @@ -28,7 +28,7 @@ trait PrivatelyRefundable { incomplete_fee_payer_point: Point, incomplete_user_point: Point, transaction_fee: Field - ) -> (Field, Field); + ) -> (Point, Point); } global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. @@ -71,10 +71,10 @@ impl NoteInterface for TokenNote { - fn compute_note_content_hash(self) -> Field { + fn compute_note_hiding_point(self) -> Point { let (npk_lo, npk_hi) = decompose(self.npk_m_hash); let (random_lo, random_hi) = decompose(self.randomness); - // We compute the note content hash as an x-coordinate of `G_amt * amount + G_npk * npk_m_hash + G_rnd * randomness` instead + // We compute the note hiding point as `G_amt * amount + G_npk * npk_m_hash + G_rnd * randomness` instead // of using pedersen or poseidon2 because it allows us to privately add and subtract from amount in public // by leveraging homomorphism. multi_scalar_mul( @@ -91,7 +91,7 @@ impl NoteInterface for TokenNote { lo: random_lo, hi: random_hi, }] - ).x + ) } } @@ -135,8 +135,7 @@ impl OwnedNote for TokenNote { * * So you can think of these (x, y) points as "partial notes": they encode part of the internals of the notes. * - * This is because the compute_note_content_hash function above defines the content hash to be - * the x-coordinate of a point defined as: + * This is because the compute_note_hiding_point function above defines the hiding point as: * * G_amt * amount + G_npk * npk_m_hash + G_rnd * randomness * @@ -184,7 +183,7 @@ impl OwnedNote for TokenNote { * = (G_amt * funded_amount + G_npk * user_npk + G_rnd + user_randomness) - G_amt * transaction_fee = * = G_amt * (funded_amount - transaction_fee) + G_npk * user_npk + G_rnd + user_randomness * - * The x-coordinate of points above identically matches the note_content_hash of (and therefore *is*) notes like: + * The point above matches the note_hiding_point of (and therefore *is*) notes like: * { * amount: (funded_amount - transaction_fee), * npk_m_hash: user_npk, @@ -209,6 +208,7 @@ impl PrivatelyRefundable for TokenNote { fn generate_refund_points(fee_payer_npk_m_hash: Field, user_npk_m_hash: Field, funded_amount: Field, user_randomness: Field, fee_payer_randomness: Field) -> (Point, Point) { // 1. To be able to multiply generators with randomness and npk_m_hash using barretneberg's (BB) blackbox // function we first need to convert the fields to high and low limbs. + // TODO(#7606): replace decompose with from_field_unsafe let (fee_payer_randomness_lo, fee_payer_randomness_hi) = decompose(fee_payer_randomness); let (fee_payer_npk_m_hash_lo, fee_payer_npk_m_hash_hi) = decompose(fee_payer_npk_m_hash); @@ -253,7 +253,7 @@ impl PrivatelyRefundable for TokenNote { (incomplete_fee_payer_point, incomplete_user_point) } - fn complete_refund(incomplete_fee_payer_point: Point, incomplete_user_point: Point, transaction_fee: Field) -> (Field, Field) { + fn complete_refund(incomplete_fee_payer_point: Point, incomplete_user_point: Point, transaction_fee: Field) -> (Point, Point) { // 1. We convert the transaction fee to high and low limbs to be able to use BB API. let (transaction_fee_lo, transaction_fee_hi) = decompose(transaction_fee); @@ -273,7 +273,7 @@ impl PrivatelyRefundable for TokenNote { assert_eq(user_point.is_infinite, false); - // Finally we return the x-coordinates of the points which are the note content hashes. - (fee_payer_point.x, user_point.x) + // Finally we return the points which represent the note hiding points. + (fee_payer_point, user_point) } } 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 7513a0e3a02..d778c72d504 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 @@ -55,21 +55,21 @@ mod tests { global contract_address = AztecAddress::from_field(123); // Create 4 note hashes. 10 and 11 are settled. 12 and 13 are pending. - global inner_note_hashes = [10, 11, 12, 13]; - global note_hashes = inner_note_hashes.map(|n| compute_siloed_note_hash(contract_address, n)); + global slotted_note_hashes = [10, 11, 12, 13]; + global note_hashes = slotted_note_hashes.map(|n| compute_siloed_note_hash(contract_address, n)); // Create 5 read requests. 0 and 3 are reading settled note hashes. 1, 2 and 4 are reading pending note hashes. global read_requests = [ - ReadRequest { value: inner_note_hashes[1], counter: 11 }.scope(contract_address), // settled - ReadRequest { value: inner_note_hashes[3], counter: 13 }.scope(contract_address), // pending - ReadRequest { value: inner_note_hashes[2], counter: 39 }.scope(contract_address), // pending - ReadRequest { value: inner_note_hashes[0], counter: 46 }.scope(contract_address), // settled - ReadRequest { value: inner_note_hashes[3], counter: 78 }.scope(contract_address), // pending + ReadRequest { value: slotted_note_hashes[1], counter: 11 }.scope(contract_address), // settled + ReadRequest { value: slotted_note_hashes[3], counter: 13 }.scope(contract_address), // pending + ReadRequest { value: slotted_note_hashes[2], counter: 39 }.scope(contract_address), // pending + ReadRequest { value: slotted_note_hashes[0], counter: 46 }.scope(contract_address), // settled + ReadRequest { value: slotted_note_hashes[3], counter: 78 }.scope(contract_address), // pending ]; global pending_values = [ - NoteHash { value: inner_note_hashes[2], counter: 2, }.scope(contract_address), - NoteHash { value: inner_note_hashes[3], counter: 8, }.scope(contract_address), + NoteHash { value: slotted_note_hashes[2], counter: 2, }.scope(contract_address), + NoteHash { value: slotted_note_hashes[3], counter: 8, }.scope(contract_address), ]; global pending_read_hints = [ PendingReadHint { read_request_index: 1, pending_value_index: 1 }, 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 131b6746b7e..b788d2e8cb6 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -339,9 +339,8 @@ global GENERATOR_INDEX__OVSK_M = 50; global GENERATOR_INDEX__TSK_M = 51; global GENERATOR_INDEX__PUBLIC_KEYS_HASH = 52; global GENERATOR_INDEX__NOTE_NULLIFIER = 53; -global GENERATOR_INDEX__INNER_NOTE_HASH = 54; -global GENERATOR_INDEX__NOTE_CONTENT_HASH = 55; -global GENERATOR_INDEX__SYMMETRIC_KEY: u8 = 56; +global GENERATOR_INDEX__NOTE_HIDING_POINT: u32 = 54; +global GENERATOR_INDEX__SYMMETRIC_KEY: u8 = 55; global SENDER_SELECTOR: u32 = 0; // "address" actually does not exist in PublicCircuitPublicInputs, 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 5e98e6f5776..44162202a69 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -45,8 +45,8 @@ fn compute_note_hash_nonce(tx_hash: Field, note_index_in_tx: u32) -> Field { ) } -pub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field { - let inputs = [nonce, inner_note_hash]; +pub fn compute_unique_note_hash(nonce: Field, slotted_note_hash: Field) -> Field { + let inputs = [nonce, slotted_note_hash]; pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH) } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr b/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr index 797cc666bac..13a82bc58b5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr @@ -3,3 +3,20 @@ use crate::{hash::pedersen_hash, traits::ToField}; pub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field where K: ToField { pedersen_hash([storage_slot, key.to_field()], 0) } + +mod test { + use crate::{address::AztecAddress, storage::map::derive_storage_slot_in_map}; + + #[test] + fn test_derive_storage_slot_in_map_matches_typescript() { + let map_slot = 0x132258fb6962c4387ba659d9556521102d227549a386d39f0b22d1890d59c2b5; + let key = AztecAddress::from_field(0x302dbc2f9b50a73283d5fb2f35bc01eae8935615817a0b4219a057b2ba8a5a3f); + + let slot = derive_storage_slot_in_map(map_slot, key); + + // The following value was generated by `map_slot.test.ts` + let slot_from_typescript = 0x2499880e2b1b831785c17286f99a0d5122fee784ce7b1c04e380c4a991da819a; + + assert_eq(slot, slot_from_typescript); + } +} diff --git a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs index 3233e12ab73..251ec46e101 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs @@ -196,10 +196,10 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt trait_impl.items.push(TraitImplItem::Function(get_note_type_id_fn)); } - if !check_trait_method_implemented(trait_impl, "compute_note_content_hash") { - let compute_note_content_hash_fn = - generate_compute_note_content_hash(¬e_type, note_interface_impl_span)?; - trait_impl.items.push(TraitImplItem::Function(compute_note_content_hash_fn)); + if !check_trait_method_implemented(trait_impl, "compute_note_hiding_point") { + let compute_note_hiding_point_fn = + generate_compute_note_hiding_point(¬e_type, note_interface_impl_span)?; + trait_impl.items.push(TraitImplItem::Function(compute_note_hiding_point_fn)); } if !check_trait_method_implemented(trait_impl, "to_be_bytes") { @@ -494,19 +494,23 @@ fn generate_note_properties_fn( Ok(noir_fn) } -// Automatically generate the method to compute the note's content hash as: -// fn compute_note_content_hash(self: NoteType) -> Field { -// aztec::hash::pedersen_hash(self.serialize_content(), aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) +// Automatically generate the method to compute the note's hiding point as: +// fn compute_note_hiding_point(self: NoteType) -> Point { +// aztec::hash::pedersen_commitment(self.serialize_content(), aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_HIDING_POINT) // } // -fn generate_compute_note_content_hash( +fn generate_compute_note_hiding_point( note_type: &String, impl_span: Option, ) -> Result { + // TODO(#7551): Replace the pedersen hash with something that returns a point directly to avoid + // the superfluous call to field_to_point(...). I was trying to use pedersen_commitment for that + // but that is currently not supported by the AVM (but might be soon). let function_source = format!( " - fn compute_note_content_hash(self: {}) -> Field {{ - aztec::hash::pedersen_hash(self.serialize_content(), aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) + fn compute_note_hiding_point(self: {}) -> aztec::protocol_types::point::Point {{ + let h = aztec::hash::pedersen_hash(self.serialize_content(), aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_HIDING_POINT); + aztec::generators::field_to_point(h) }} ", note_type @@ -515,7 +519,7 @@ fn generate_compute_note_content_hash( if !errors.is_empty() { dbg!(errors); return Err(AztecMacroError::CouldNotImplementNoteInterface { - secondary_message: Some("Failed to parse Noir macro code (fn compute_note_content_hash). This is either a bug in the compiler or the Noir macro code".to_string()), + secondary_message: Some("Failed to parse Noir macro code (fn compute_note_hiding_point). This is either a bug in the compiler or the Noir macro code".to_string()), span: impl_span }); } diff --git a/noir/noir-repo/noir_stdlib/src/hash/mod.nr b/noir/noir-repo/noir_stdlib/src/hash/mod.nr index 320b89353d9..cea33a136cb 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/mod.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/mod.nr @@ -49,7 +49,7 @@ fn pedersen_commitment_with_separator(input: [Field; N], separator: fn pedersen_commitment_with_separator_noir(input: [Field; N], separator: u32) -> EmbeddedCurvePoint { let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N]; for i in 0..N { - // we use the unsafe version because the multi_scalar_mul will constraint the scalars. + // we use the unsafe version because the multi_scalar_mul will constrain the scalars. points[i] = from_field_unsafe(input[i]); } let generators = derive_generators("DEFAULT_DOMAIN_SEPARATOR".as_bytes(), separator); diff --git a/yarn-project/aztec.js/src/utils/cheat_codes.ts b/yarn-project/aztec.js/src/utils/cheat_codes.ts index 95cceaf0e39..d05045a8dd2 100644 --- a/yarn-project/aztec.js/src/utils/cheat_codes.ts +++ b/yarn-project/aztec.js/src/utils/cheat_codes.ts @@ -1,7 +1,8 @@ import { type Note, type PXE } from '@aztec/circuit-types'; import { type AztecAddress, type EthAddress, Fr } from '@aztec/circuits.js'; +import { deriveStorageSlotInMap } from '@aztec/circuits.js/hash'; import { toBigIntBE, toHex } from '@aztec/foundation/bigint-buffer'; -import { keccak256, pedersenHash } from '@aztec/foundation/crypto'; +import { keccak256 } from '@aztec/foundation/crypto'; import { createDebugLogger } from '@aztec/foundation/log'; import fs from 'fs'; @@ -239,14 +240,12 @@ export class AztecCheatCodes { /** * Computes the slot value for a given map and key. - * @param baseSlot - The base slot of the map (specified in Aztec.nr contract) + * @param mapSlot - The slot of the map (specified in Aztec.nr contract) * @param key - The key to lookup in the map * @returns The storage slot of the value in the map */ - public computeSlotInMap(baseSlot: Fr | bigint, key: Fr | bigint | AztecAddress): Fr { - // Based on `at` function in - // aztec3-packages/aztec-nr/aztec/src/state_vars/map.nr - return pedersenHash([new Fr(baseSlot), new Fr(key)]); + public computeSlotInMap(mapSlot: Fr | bigint, key: Fr | bigint | AztecAddress): Fr { + return deriveStorageSlotInMap(mapSlot, new Fr(key)); } /** diff --git a/yarn-project/circuit-types/src/logs/l1_payload/encrypt_buffer.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/encrypt_buffer.test.ts index 6f38c689e99..ab318001fa2 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/encrypt_buffer.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/encrypt_buffer.test.ts @@ -32,7 +32,7 @@ describe('encrypt buffer', () => { // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data updateInlineTestData( 'noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr', - 'expected_key', + 'key_from_typescript', byteArrayString, ); }); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_header.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_header.test.ts index bf93841caa5..93df3fee728 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_header.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_header.test.ts @@ -46,7 +46,7 @@ describe('encrypt log header', () => { // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data updateInlineTestData( 'noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr', - 'expected_header_ciphertext', + 'expected_header_ciphertext_from_typescript', byteArrayString, ); }); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_event_log_incoming_body.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_event_log_incoming_body.test.ts index 6e431995d26..fe3e6b752b0 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_event_log_incoming_body.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_event_log_incoming_body.test.ts @@ -55,7 +55,7 @@ describe('encrypt log incoming body', () => { // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data updateInlineTestData( 'noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr', - 'expected_event_body_ciphertext', + 'event_body_ciphertext_from_typescript', byteArrayString, ); }); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_note_log_incoming_body.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_note_log_incoming_body.test.ts index 18613e08e6e..47a33fada1d 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_note_log_incoming_body.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_note_log_incoming_body.test.ts @@ -34,7 +34,7 @@ describe('encrypt log incoming body', () => { }); it('encrypt a note log incoming body, generate input for noir test', () => { - // The following 2 are arbitrary fixed values - fixed in order to test a match with Noir + // All the values in this test were arbitrarily set and copied over to `incoming_body.nr` const ephSecretKey = new GrumpkinScalar(0x23b3127c127b1f29a7adff5cccf8fb06649e7ca01d9de27b21624098b897babdn); const viewingSecretKey = new GrumpkinScalar(0x1fdd0dd8c99b21af8e00d2d130bdc263b36dadcbea84ac5ec9293a0660deca01n); @@ -56,7 +56,7 @@ describe('encrypt log incoming body', () => { // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data updateInlineTestData( 'noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr', - 'expected_note_body_ciphertext', + 'note_body_ciphertext_from_typescript', byteArrayString, ); }); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_outgoing_body.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_outgoing_body.test.ts index e4de515d00b..35b89c559e0 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_outgoing_body.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_outgoing_body.test.ts @@ -56,7 +56,7 @@ describe('encrypt log outgoing body', () => { // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data updateInlineTestData( 'noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr', - 'expected_outgoing_body_ciphertext', + 'outgoing_body_ciphertext_from_typescript', byteArrayString, ); }); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts index af8397ff49d..01000c26e56 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts @@ -57,6 +57,7 @@ describe('L1 Note Payload', () => { }); it('encrypted tagged log matches Noir', () => { + // All the values in this test were arbitrarily set and copied over to `payload.nr` const contract = AztecAddress.fromString('0x10f48cd9eff7ae5b209c557c70de2e657ee79166868676b787e9417e19260e04'); const storageSlot = new Fr(0x0fe46be583b71f4ab5b70c2657ff1d05cccf1d292a9369628d1a194f944e6599n); const noteValue = new Fr(0x301640ceea758391b2e161c92c0513f129020f4125256afdae2646ce31099f5cn); @@ -82,7 +83,7 @@ describe('L1 Note Payload', () => { const encrypted = taggedLog.encrypt(ephSk, recipientAddress, ivpk, ovKeys).toString('hex'); expect(encrypted).toMatchInlineSnapshot( - `"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d460c0e434d846ec1ea286e4090eb56376ff27bddc1aacae1d856549f701fa79f357275ed3983136f963253ad9beae147bb8d4ff52b6f53db957c440cf4fdd8003e6ce87650578cd7b96f3080ec6e5c2ecd07e28342cd006753d95a3c8a06acf6815cac45494d419312e71423d9b4fd48f220392d0b02eb1860f4e0213d97e188adb228027de514dc521cbf938589012df3e58c73a5969a601678dfedd5b6fcc008842b1538f37490b64b101edede3ccd93d635293e3510937548a9dc7dd0d22d41e92857588cedc8a109565280bf3304c3f36466f03681b0748b491b62de01f3c748eed5425b9fb78f24675e053e320dd9a14f1ee729e46d8bf377a63625fac106431d94b9993a40d2a4dba550234b6db10ea8886915eb3e9f473df5c1eaa964a508de9def29dddf43503dfc361b64016802793e2917840f7c7815c67197ac2aa140f0a6cd50a93abf6f82373a8d1a617672d845cfd4e3fac7154890552b4cd51c848610dd697052ee723d2490b3b244c6a2d4556474ba83e821e565fb05fb"`, + `"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d460c0e434d846ec1ea286e4090eb56376ff27bddc1aacae1d856549f701fa77e4f33ba2f47fdac6370f13bc5f16bbae857bbe6ab3ee4ea2a339192eef22a47ce0df4426fc314cb6294ccf291b79c1d8d362cdcc223e51020ccd3318e7052ca74f1fe922ad914bd46e4b6abcd681b63ab1c5bf4151e82f00548ae7c61c59df8cccb8cabb59882a9b32934ad2d2bc60198489ef90b2909a0304e7b84cb8cd70d16c958ff8b9a4c143f867d6cefd03f3b21758be1b80040991583cc6f29541790def5c80cea0b300add14fc267a28f942f8c5c6d14f143b42c5d7101291e4ef7c51436731c43ae4c340c7f3b870ad1dc4d74dd9555295714cc95d5f94255fdee9d29601b61c843b949c8124e637c79524cd67d43c978d0a97de97b42b5b94c96ea50aee2086eb63d8c8b61f169c12d1deacefc1d456633e46b62daff15bcab3e1630196e802fc14533184a25d74d45747d33a9fa328fd1f03c0300ec95018879acf3a8c801d65cfbdb6bf47d240ac83532ee813d8b76cea11683c71e791c39d18"`, ); const byteArrayString = `[${encrypted.match(/.{1,2}/g)!.map(byte => parseInt(byte, 16))}]`; @@ -90,7 +91,7 @@ describe('L1 Note Payload', () => { // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data updateInlineTestData( 'noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr', - 'expected_encrypted_note_log', + 'encrypted_note_log_from_typescript', byteArrayString, ); }); diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 2ecf599ca56..62caab71d9e 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -263,7 +263,6 @@ export enum GeneratorIndex { TSK_M = 51, PUBLIC_KEYS_HASH = 52, NOTE_NULLIFIER = 53, - INNER_NOTE_HASH = 54, - NOTE_CONTENT_HASH = 55, - SYMMETRIC_KEY = 56, + NOTE_HIDING_POINT = 54, + SYMMETRIC_KEY = 55, } diff --git a/yarn-project/circuits.js/src/hash/hash.test.ts b/yarn-project/circuits.js/src/hash/hash.test.ts index 99216b0c0b1..0b688151822 100644 --- a/yarn-project/circuits.js/src/hash/hash.test.ts +++ b/yarn-project/circuits.js/src/hash/hash.test.ts @@ -26,8 +26,8 @@ describe('hash', () => { it('computes unique note hash', () => { const nonce = new Fr(123n); - const innerNoteHash = new Fr(456); - const res = computeUniqueNoteHash(nonce, innerNoteHash); + const slottedNoteHash = new Fr(456); + const res = computeUniqueNoteHash(nonce, slottedNoteHash); expect(res).toMatchSnapshot(); }); diff --git a/yarn-project/circuits.js/src/hash/hash.ts b/yarn-project/circuits.js/src/hash/hash.ts index 3d78b779071..12954c4213f 100644 --- a/yarn-project/circuits.js/src/hash/hash.ts +++ b/yarn-project/circuits.js/src/hash/hash.ts @@ -44,41 +44,22 @@ export function computeNoteHashNonce(nullifierZero: Fr, noteHashIndex: number): * Computes a siloed note hash, given the contract address and the note hash itself. * A siloed note hash effectively namespaces a note hash to a specific contract. * @param contract - The contract address - * @param innerNoteHash - The note hash to silo. + * @param uniqueNoteHash - The unique note hash to silo. * @returns A siloed note hash. */ export function siloNoteHash(contract: AztecAddress, uniqueNoteHash: Fr): Fr { return pedersenHash([contract, uniqueNoteHash], GeneratorIndex.SILOED_NOTE_HASH); } -/** - * Computes a note content hash. - * @param noteContent - The note content (e.g. note.items). - * @returns A note content hash. - */ -export function computeNoteContentHash(noteContent: Fr[]): Fr { - return pedersenHash(noteContent, GeneratorIndex.NOTE_CONTENT_HASH); -} - -/** - * Computes an inner note hash, given a storage slot and a note hash. - * @param storageSlot - The storage slot. - * @param noteHash - The note hash. - * @returns An inner note hash. - */ -export function computeInnerNoteHash(storageSlot: Fr, noteHash: Fr): Fr { - return pedersenHash([storageSlot, noteHash], GeneratorIndex.INNER_NOTE_HASH); -} - /** * Computes a unique note hash. * @dev Includes a nonce which contains data that guarantees the resulting note hash will be unique. - * @param nonce - The contract address. - * @param innerNoteHash - An inner note hash. + * @param nonce - A nonce (typically derived from tx hash and note hash index in the tx). + * @param slottedNoteHash - A slotted note hash. * @returns A unique note hash. */ -export function computeUniqueNoteHash(nonce: Fr, innerNoteHash: Fr): Fr { - return pedersenHash([nonce, innerNoteHash], GeneratorIndex.UNIQUE_NOTE_HASH); +export function computeUniqueNoteHash(nonce: Fr, slottedNoteHash: Fr): Fr { + return pedersenHash([nonce, slottedNoteHash], GeneratorIndex.UNIQUE_NOTE_HASH); } /** diff --git a/yarn-project/circuits.js/src/hash/index.ts b/yarn-project/circuits.js/src/hash/index.ts index c3e9a375b11..b2ddb1d68d3 100644 --- a/yarn-project/circuits.js/src/hash/index.ts +++ b/yarn-project/circuits.js/src/hash/index.ts @@ -1 +1,2 @@ export * from './hash.js'; +export * from './map_slot.js'; diff --git a/yarn-project/circuits.js/src/hash/map_slot.test.ts b/yarn-project/circuits.js/src/hash/map_slot.test.ts new file mode 100644 index 00000000000..e43047d4b2d --- /dev/null +++ b/yarn-project/circuits.js/src/hash/map_slot.test.ts @@ -0,0 +1,25 @@ +import { AztecAddress } from '@aztec/foundation/aztec-address'; +import { Fr } from '@aztec/foundation/fields'; +import { updateInlineTestData } from '@aztec/foundation/testing'; + +import { deriveStorageSlotInMap } from './index.js'; + +describe('Map slot', () => { + it('derived map slot matches Noir', () => { + const mapSlot = new Fr(0x132258fb6962c4387ba659d9556521102d227549a386d39f0b22d1890d59c2b5n); + const key = AztecAddress.fromString('0x302dbc2f9b50a73283d5fb2f35bc01eae8935615817a0b4219a057b2ba8a5a3f'); + + const slot = deriveStorageSlotInMap(mapSlot, key); + + expect(slot.toString()).toMatchInlineSnapshot( + `"0x2499880e2b1b831785c17286f99a0d5122fee784ce7b1c04e380c4a991da819a"`, + ); + + // Run with AZTEC_GENERATE_TEST_DATA=1 to update noir test data + updateInlineTestData( + 'noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr', + 'slot_from_typescript', + slot.toString(), + ); + }); +}); diff --git a/yarn-project/circuits.js/src/hash/map_slot.ts b/yarn-project/circuits.js/src/hash/map_slot.ts new file mode 100644 index 00000000000..d14b85b0ea9 --- /dev/null +++ b/yarn-project/circuits.js/src/hash/map_slot.ts @@ -0,0 +1,18 @@ +import { pedersenHash } from '@aztec/foundation/crypto'; +import { type Fr } from '@aztec/foundation/fields'; + +/** + * Computes the resulting storage slot for an entry in a map. + * @param mapSlot - The slot of the map within state. + * @param key - The key of the map. + * @returns The slot in the contract storage where the value is stored. + */ +export function deriveStorageSlotInMap( + mapSlot: Fr | bigint, + key: { + /** Convert key to a field. */ + toField: () => Fr; + }, +): Fr { + return pedersenHash([mapSlot, key.toField()]); +} diff --git a/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts b/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts index e812f869a4d..59638719276 100644 --- a/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts @@ -39,7 +39,7 @@ describe('buildNoteHashReadRequestHints', () => { let numSettledReads = 0; let futureNoteHashes: ScopedNoteHash[]; - const innerNoteHash = (index: number) => index + 9999; + const slottedNoteHash = (index: number) => index + 9999; const makeReadRequest = (value: number, counter = 2) => new ReadRequest(new Fr(value), counter).scope(contractAddress); @@ -49,7 +49,7 @@ describe('buildNoteHashReadRequestHints', () => { const readPendingNoteHash = (noteHashIndex: number) => { const readRequestIndex = numReadRequests; const hintIndex = numPendingReads; - noteHashReadRequests[readRequestIndex] = makeReadRequest(innerNoteHash(noteHashIndex)); + noteHashReadRequests[readRequestIndex] = makeReadRequest(slottedNoteHash(noteHashIndex)); expectedHints.readRequestStatuses[readRequestIndex] = ReadRequestStatus.pending(hintIndex); expectedHints.pendingReadHints[hintIndex] = new PendingReadHint(readRequestIndex, noteHashIndex); numReadRequests++; @@ -89,7 +89,7 @@ describe('buildNoteHashReadRequestHints', () => { beforeEach(() => { noteHashReadRequests = makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ScopedReadRequest.empty); - noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, i => makeNoteHash(innerNoteHash(i))); + noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, i => makeNoteHash(slottedNoteHash(i))); noteHashLeafIndexMap = new Map(); expectedHints = NoteHashReadRequestHintsBuilder.empty( MAX_NOTE_HASH_READ_REQUESTS_PER_TX, @@ -100,7 +100,7 @@ describe('buildNoteHashReadRequestHints', () => { numSettledReads = 0; futureNoteHashes = new Array(MAX_NOTE_HASHES_PER_TX) .fill(null) - .map((_, i) => makeNoteHash(innerNoteHash(i + MAX_NOTE_HASHES_PER_TX))); + .map((_, i) => makeNoteHash(slottedNoteHash(i + MAX_NOTE_HASHES_PER_TX))); }); it('builds empty hints', async () => { diff --git a/yarn-project/end-to-end/src/composed/e2e_aztec_js_browser.test.ts b/yarn-project/end-to-end/src/composed/e2e_aztec_js_browser.test.ts index 1d465504b8b..6bbd6215923 100644 --- a/yarn-project/end-to-end/src/composed/e2e_aztec_js_browser.test.ts +++ b/yarn-project/end-to-end/src/composed/e2e_aztec_js_browser.test.ts @@ -24,13 +24,17 @@ const pageLogger = createDebugLogger('aztec:e2e_aztec_browser.js:web:page'); * 1) Build the whole repository, * 2) go to `yarn-project/end-to-end` and build the web packed package with `yarn build:web`, * 3) start anvil: `anvil`, - * 4) if you intend to use a remotely running environment then export the URL of your PXE e.g. `export PXE_URL='http://localhost:8080'` + * 4) if you intend to use a remotely running environment then export the URL of your PXE e.g. + * `export PXE_URL='http://localhost:8080'` * 5) go to `yarn-project/end-to-end` and run the test: `yarn test aztec_js_browser` - * 6) If you get dependency error run `apt install libssn3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libxdamage1 libxkbcommon0 libpango-1.0-0 libcairo2`. + * 6) If you get dependency error run `apt install libnss3 libatk1.0-0t64 libatk-bridge2.0-0t64 libcups2t64 libxdamage1 libxkbcommon0 libpango-1.0-0 libcairo2 libasound2t64`. * * NOTE 1: If you see the logs spammed with unexpected logs there is probably a chrome process with a webpage - * unexpectedly running in the background. Kill it with `killall chrome` + * unexpectedly running in the background. Kill it with `killall chrome` * NOTE 2: Don't forget to run `yarn build:web` once you make changes! + * NOTE 3: The test serializes token contract artifact to and from buffer. If you introduce a new type in the artifact + * you have to register it on `TypeRegistry` class, implement fromJSON method just like TypeRegistry requires + * and add a case in `contractArtifactFromBuffer(...)` function. */ const setupApp = async () => { diff --git a/yarn-project/end-to-end/src/e2e_block_building.test.ts b/yarn-project/end-to-end/src/e2e_block_building.test.ts index 206e19e00b4..b1773d71856 100644 --- a/yarn-project/end-to-end/src/e2e_block_building.test.ts +++ b/yarn-project/end-to-end/src/e2e_block_building.test.ts @@ -236,7 +236,7 @@ describe('e2e_block_building', () => { }); describe('logs in nested calls are ordered as expected', () => { - // This test was originally writted for e2e_nested, but it was refactored + // This test was originally written for e2e_nested, but it was refactored // to not use TestContract. let testContract: TestContract; diff --git a/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts b/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts index ba938b63ef2..3c369d8bd59 100644 --- a/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts @@ -188,7 +188,7 @@ describe('e2e_pending_note_hashes_contract', () => { await expectNoteLogsSquashedExcept(1); }); - it('Squash! Aztec.nr function can "create" 2 notes with the same inner note hash and "nullify" 1 in the same TX', async () => { + it('Squash! Aztec.nr function can "create" 2 notes with the same slotted note hash and "nullify" 1 in the same TX', async () => { // Kernel will squash one noteHash and its nullifier, where two notes with the same inner hash exist. // The other note will become persistent! // Realistic way to describe this test is "Mint notes A and B, then burn note A in the same transaction" diff --git a/yarn-project/foundation/src/fields/point.ts b/yarn-project/foundation/src/fields/point.ts index eb443cbf6c0..253173c6a3c 100644 --- a/yarn-project/foundation/src/fields/point.ts +++ b/yarn-project/foundation/src/fields/point.ts @@ -267,19 +267,6 @@ export class Point { } } -/** - * Does this object look like a point? - * @param obj - Object to test if it is a point. - * @returns Whether it looks like a point. - */ -export function isPoint(obj: object): obj is Point { - if (!obj) { - return false; - } - const point = obj as Point; - return point.kind === 'point' && point.x !== undefined && point.y !== undefined; -} - export class NotOnCurveError extends Error { constructor(x: Fr) { super('The given x-coordinate is not on the Grumpkin curve: ' + x.toString()); diff --git a/yarn-project/pxe/src/database/incoming_note_dao.test.ts b/yarn-project/pxe/src/database/incoming_note_dao.test.ts index f20e957fc1b..00c70ea296e 100644 --- a/yarn-project/pxe/src/database/incoming_note_dao.test.ts +++ b/yarn-project/pxe/src/database/incoming_note_dao.test.ts @@ -11,7 +11,7 @@ export const randomIncomingNoteDao = ({ storageSlot = Fr.random(), noteTypeId = NoteSelector.random(), nonce = Fr.random(), - innerNoteHash = Fr.random(), + slottedNoteHash = Fr.random(), siloedNullifier = Fr.random(), index = Fr.random().toBigInt(), ivpkM = Point.random(), @@ -23,7 +23,7 @@ export const randomIncomingNoteDao = ({ noteTypeId, txHash, nonce, - innerNoteHash, + slottedNoteHash, siloedNullifier, index, ivpkM, diff --git a/yarn-project/pxe/src/database/incoming_note_dao.ts b/yarn-project/pxe/src/database/incoming_note_dao.ts index 0a128a74259..fb51b025c8f 100644 --- a/yarn-project/pxe/src/database/incoming_note_dao.ts +++ b/yarn-project/pxe/src/database/incoming_note_dao.ts @@ -23,10 +23,10 @@ export class IncomingNoteDao implements NoteData { /** The nonce of the note. */ public nonce: Fr, /** - * Inner note hash of the note. This is customizable by the app circuit. + * Slotted note hash of the note. This is customizable by the app circuit. * We can use this value to compute siloedNoteHash and uniqueSiloedNoteHash. */ - public innerNoteHash: Fr, + public slottedNoteHash: Fr, /** * The nullifier of the note (siloed by contract address). * Note: Might be set as 0 if the note was added to PXE as nullified. @@ -46,7 +46,7 @@ export class IncomingNoteDao implements NoteData { this.noteTypeId, this.txHash.buffer, this.nonce, - this.innerNoteHash, + this.slottedNoteHash, this.siloedNullifier, this.index, this.ivpkM, @@ -61,7 +61,7 @@ export class IncomingNoteDao implements NoteData { const noteTypeId = reader.readObject(NoteSelector); const txHash = reader.readObject(TxHash); const nonce = Fr.fromBuffer(reader); - const innerNoteHash = Fr.fromBuffer(reader); + const slottedNoteHash = Fr.fromBuffer(reader); const siloedNullifier = Fr.fromBuffer(reader); const index = toBigIntBE(reader.readBytes(32)); const publicKey = Point.fromBuffer(reader); @@ -73,7 +73,7 @@ export class IncomingNoteDao implements NoteData { noteTypeId, txHash, nonce, - innerNoteHash, + slottedNoteHash, siloedNullifier, index, publicKey, diff --git a/yarn-project/pxe/src/database/outgoing_note_dao.test.ts b/yarn-project/pxe/src/database/outgoing_note_dao.test.ts index 9e7241760ff..cb404be360b 100644 --- a/yarn-project/pxe/src/database/outgoing_note_dao.test.ts +++ b/yarn-project/pxe/src/database/outgoing_note_dao.test.ts @@ -11,7 +11,7 @@ export const randomOutgoingNoteDao = ({ storageSlot = Fr.random(), noteTypeId = NoteSelector.random(), nonce = Fr.random(), - innerNoteHash = Fr.random(), + slottedNoteHash = Fr.random(), index = Fr.random().toBigInt(), ovpkM = Point.random(), }: Partial = {}) => { @@ -22,7 +22,7 @@ export const randomOutgoingNoteDao = ({ noteTypeId, txHash, nonce, - innerNoteHash, + slottedNoteHash, index, ovpkM, ); diff --git a/yarn-project/pxe/src/database/outgoing_note_dao.ts b/yarn-project/pxe/src/database/outgoing_note_dao.ts index 03075f9f7df..1c038e5dc48 100644 --- a/yarn-project/pxe/src/database/outgoing_note_dao.ts +++ b/yarn-project/pxe/src/database/outgoing_note_dao.ts @@ -22,10 +22,10 @@ export class OutgoingNoteDao { /** The nonce of the note. */ public nonce: Fr, /** - * Inner note hash of the note. This is customizable by the app circuit. + * Slotted note hash of the note. This is customizable by the app circuit. * We can use this value to compute siloedNoteHash and uniqueSiloedNoteHash. */ - public innerNoteHash: Fr, + public slottedNoteHash: Fr, /** The location of the relevant note in the note hash tree. */ public index: bigint, /** The public key with which the note was encrypted. */ @@ -40,7 +40,7 @@ export class OutgoingNoteDao { this.noteTypeId, this.txHash.buffer, this.nonce, - this.innerNoteHash, + this.slottedNoteHash, this.index, this.ovpkM, ]); @@ -54,7 +54,7 @@ export class OutgoingNoteDao { const noteTypeId = reader.readObject(NoteSelector); const txHash = new TxHash(reader.readBytes(TxHash.SIZE)); const nonce = Fr.fromBuffer(reader); - const innerNoteHash = Fr.fromBuffer(reader); + const slottedNoteHash = Fr.fromBuffer(reader); const index = toBigIntBE(reader.readBytes(32)); const publicKey = Point.fromBuffer(reader); @@ -65,7 +65,7 @@ export class OutgoingNoteDao { noteTypeId, txHash, nonce, - innerNoteHash, + slottedNoteHash, index, publicKey, ); diff --git a/yarn-project/pxe/src/note_processor/note_processor.test.ts b/yarn-project/pxe/src/note_processor/note_processor.test.ts index 8fb954ea986..3757a1c4171 100644 --- a/yarn-project/pxe/src/note_processor/note_processor.test.ts +++ b/yarn-project/pxe/src/note_processor/note_processor.test.ts @@ -166,7 +166,7 @@ describe('Note Processor', () => { simulator.computeNoteHashAndOptionallyANullifier.mockImplementation((...args) => Promise.resolve({ - innerNoteHash: Fr.random(), + slottedNoteHash: Fr.random(), uniqueNoteHash: Fr.random(), siloedNoteHash: pedersenHash(args[5].items), // args[5] is note innerNullifier: Fr.random(), diff --git a/yarn-project/pxe/src/note_processor/produce_note_dao.ts b/yarn-project/pxe/src/note_processor/produce_note_dao.ts index 46d64c7125f..b8325f76415 100644 --- a/yarn-project/pxe/src/note_processor/produce_note_dao.ts +++ b/yarn-project/pxe/src/note_processor/produce_note_dao.ts @@ -51,7 +51,7 @@ export async function produceNoteDaos( try { if (ivpkM) { - const { noteHashIndex, nonce, innerNoteHash, siloedNullifier } = await findNoteIndexAndNullifier( + const { noteHashIndex, nonce, slottedNoteHash, siloedNullifier } = await findNoteIndexAndNullifier( simulator, noteHashes, txHash, @@ -69,7 +69,7 @@ export async function produceNoteDaos( payload.noteTypeId, txHash, nonce, - innerNoteHash, + slottedNoteHash, siloedNullifier, index, ivpkM, @@ -108,12 +108,12 @@ export async function produceNoteDaos( payload.noteTypeId, txHash, incomingNote.nonce, - incomingNote.innerNoteHash, + incomingNote.slottedNoteHash, incomingNote.index, ovpkM, ); } else { - const { noteHashIndex, nonce, innerNoteHash } = await findNoteIndexAndNullifier( + const { noteHashIndex, nonce, slottedNoteHash } = await findNoteIndexAndNullifier( simulator, noteHashes, txHash, @@ -130,7 +130,7 @@ export async function produceNoteDaos( payload.noteTypeId, txHash, nonce, - innerNoteHash, + slottedNoteHash, index, ovpkM, ); @@ -189,7 +189,7 @@ async function findNoteIndexAndNullifier( ) { let noteHashIndex = 0; let nonce: Fr | undefined; - let innerNoteHash: Fr | undefined; + let slottedNoteHash: Fr | undefined; let siloedNoteHash: Fr | undefined; let innerNullifier: Fr | undefined; const firstNullifier = Fr.fromBuffer(txHash.toBuffer()); @@ -205,7 +205,7 @@ async function findNoteIndexAndNullifier( } const expectedNonce = computeNoteHashNonce(firstNullifier, noteHashIndex); - ({ innerNoteHash, siloedNoteHash, innerNullifier } = await simulator.computeNoteHashAndOptionallyANullifier( + ({ slottedNoteHash, siloedNoteHash, innerNullifier } = await simulator.computeNoteHashAndOptionallyANullifier( contractAddress, expectedNonce, storageSlot, @@ -229,7 +229,7 @@ async function findNoteIndexAndNullifier( return { noteHashIndex, nonce, - innerNoteHash: innerNoteHash!, + slottedNoteHash: slottedNoteHash!, siloedNullifier: siloNullifier(contractAddress, innerNullifier!), }; } diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index ba1541f68ab..45b95686f59 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -350,7 +350,7 @@ export class PXEService implements PXE { } for (const nonce of nonces) { - const { innerNoteHash, siloedNoteHash, innerNullifier } = + const { slottedNoteHash, siloedNoteHash, innerNullifier } = await this.simulator.computeNoteHashAndOptionallyANullifier( note.contractAddress, nonce, @@ -379,7 +379,7 @@ export class PXEService implements PXE { note.noteTypeId, note.txHash, nonce, - innerNoteHash, + slottedNoteHash, siloedNullifier, index, owner.publicKeys.masterIncomingViewingPublicKey, @@ -400,7 +400,7 @@ export class PXEService implements PXE { } for (const nonce of nonces) { - const { innerNoteHash, siloedNoteHash, innerNullifier } = + const { slottedNoteHash, siloedNoteHash, innerNullifier } = await this.simulator.computeNoteHashAndOptionallyANullifier( note.contractAddress, nonce, @@ -427,7 +427,7 @@ export class PXEService implements PXE { note.noteTypeId, note.txHash, nonce, - innerNoteHash, + slottedNoteHash, Fr.ZERO, // We are not able to derive index, owner.publicKeys.masterIncomingViewingPublicKey, diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 6d1dcee0588..ce517998b2e 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -83,12 +83,12 @@ export class SimulatorOracle implements DBOracle { storageSlot, status, }); - return noteDaos.map(({ contractAddress, storageSlot, nonce, note, innerNoteHash, siloedNullifier, index }) => ({ + return noteDaos.map(({ contractAddress, storageSlot, nonce, note, slottedNoteHash, siloedNullifier, index }) => ({ contractAddress, storageSlot, nonce, note, - innerNoteHash, + slottedNoteHash, siloedNullifier, // PXE can use this index to get full MembershipWitness index, diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 2ebd3db2152..4714b23832f 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -247,14 +247,14 @@ export class Oracle { [storageSlot]: ACVMField[], [noteTypeId]: ACVMField[], note: ACVMField[], - [innerNoteHash]: ACVMField[], + [slottedNoteHash]: ACVMField[], [counter]: ACVMField[], ): ACVMField { this.typedOracle.notifyCreatedNote( fromACVMField(storageSlot), NoteSelector.fromField(fromACVMField(noteTypeId)), note.map(fromACVMField), - fromACVMField(innerNoteHash), + fromACVMField(slottedNoteHash), +counter, ); return toACVMField(0); @@ -262,10 +262,10 @@ export class Oracle { async notifyNullifiedNote( [innerNullifier]: ACVMField[], - [innerNoteHash]: ACVMField[], + [slottedNoteHash]: ACVMField[], [counter]: ACVMField[], ): Promise { - await this.typedOracle.notifyNullifiedNote(fromACVMField(innerNullifier), fromACVMField(innerNoteHash), +counter); + await this.typedOracle.notifyNullifiedNote(fromACVMField(innerNullifier), fromACVMField(slottedNoteHash), +counter); return toACVMField(0); } diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 36a84e4963b..28c08526b1d 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -27,8 +27,8 @@ export interface NoteData { storageSlot: Fr; /** The nonce of the note. */ nonce: Fr; - /** The inner note hash of the note. */ - innerNoteHash: Fr; + /** The slotted note hash of the note. */ + slottedNoteHash: Fr; /** The corresponding nullifier of the note. Undefined for pending notes. */ siloedNullifier?: Fr; /** The note's leaf index in the note hash tree. Undefined for pending notes. */ @@ -162,13 +162,13 @@ export abstract class TypedOracle { _storageSlot: Fr, _noteTypeId: NoteSelector, _note: Fr[], - _innerNoteHash: Fr, + _slottedNoteHash: Fr, _counter: number, ): void { throw new OracleMethodNotAvailableError('notifyCreatedNote'); } - notifyNullifiedNote(_innerNullifier: Fr, _innerNoteHash: Fr, _counter: number): Promise { + notifyNullifiedNote(_innerNullifier: Fr, _slottedNoteHash: Fr, _counter: number): Promise { throw new OracleMethodNotAvailableError('notifyNullifiedNote'); } diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 49363be658f..e79d6ea6c12 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -135,7 +135,7 @@ export class ClientExecutionContext extends ViewDataOracle { /** * Get the data for the newly created notes. - * @param innerNoteHashes - Inner note hashes for the notes. + * @param slottedNoteHashes - Slotted note hashes for the notes. */ public getNewNotes(): NoteAndSlot[] { return this.newNotes; @@ -278,7 +278,7 @@ export class ClientExecutionContext extends ViewDataOracle { if (n.index !== undefined) { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386) // Should always call computeUniqueNoteHash when publicly created notes include nonces. - const uniqueNoteHash = n.nonce.isZero() ? n.innerNoteHash : computeUniqueNoteHash(n.nonce, n.innerNoteHash); + const uniqueNoteHash = n.nonce.isZero() ? n.slottedNoteHash : computeUniqueNoteHash(n.nonce, n.slottedNoteHash); const siloedNoteHash = siloNoteHash(n.contractAddress, uniqueNoteHash); const noteHashForReadRequest = siloedNoteHash; this.noteHashLeafIndexMap.set(noteHashForReadRequest.toBigInt(), n.index); @@ -295,14 +295,14 @@ export class ClientExecutionContext extends ViewDataOracle { * @param storageSlot - The storage slot. * @param noteTypeId - The type ID of the note. * @param noteItems - The items to be included in a Note. - * @param innerNoteHash - The inner note hash of the new note. + * @param slottedNoteHash - The slotted note hash of the new note. * @returns */ public override notifyCreatedNote( storageSlot: Fr, noteTypeId: NoteSelector, noteItems: Fr[], - innerNoteHash: Fr, + slottedNoteHash: Fr, counter: number, ) { const note = new Note(noteItems); @@ -313,7 +313,7 @@ export class ClientExecutionContext extends ViewDataOracle { nonce: Fr.ZERO, // Nonce cannot be known during private execution. note, siloedNullifier: undefined, // Siloed nullifier cannot be known for newly created note. - innerNoteHash, + slottedNoteHash, }, counter, ); @@ -328,13 +328,13 @@ export class ClientExecutionContext extends ViewDataOracle { * Adding a siloed nullifier into the current set of all pending nullifiers created * within the current transaction/execution. * @param innerNullifier - The pending nullifier to add in the list (not yet siloed by contract address). - * @param innerNoteHash - The inner note hash of the new note. + * @param slottedNoteHash - The slotted note hash of the new note. */ - public override notifyNullifiedNote(innerNullifier: Fr, innerNoteHash: Fr, counter: number) { + public override notifyNullifiedNote(innerNullifier: Fr, slottedNoteHash: Fr, counter: number) { const nullifiedNoteHashCounter = this.noteCache.nullifyNote( this.callContext.storageContractAddress, innerNullifier, - innerNoteHash, + slottedNoteHash, ); if (nullifiedNoteHashCounter !== undefined) { this.nullifiedNoteHashCounters.set(nullifiedNoteHashCounter, counter); diff --git a/yarn-project/simulator/src/client/db_oracle.ts b/yarn-project/simulator/src/client/db_oracle.ts index 57d0d185ac6..5aa044dc5c9 100644 --- a/yarn-project/simulator/src/client/db_oracle.ts +++ b/yarn-project/simulator/src/client/db_oracle.ts @@ -78,8 +78,8 @@ export interface DBOracle extends CommitmentsDB { * The query result is paginated using 'limit' and 'offset' values. * Returns an object containing an array of note data. * - * @param contractAddress - The AztecAddress instance representing the contract address. - * @param storageSlot - The Fr instance representing the storage slot of the notes. + * @param contractAddress - The contract address of the notes. + * @param storageSlot - The storage slot of the notes. * @param status - The status of notes to fetch. * @returns A Promise that resolves to an array of note data. */ diff --git a/yarn-project/simulator/src/client/execution_note_cache.ts b/yarn-project/simulator/src/client/execution_note_cache.ts index 3615b012c99..2405870f927 100644 --- a/yarn-project/simulator/src/client/execution_note_cache.ts +++ b/yarn-project/simulator/src/client/execution_note_cache.ts @@ -42,20 +42,20 @@ export class ExecutionNoteCache { * @param contractAddress - Contract address of the note. * @param storageSlot - Storage slot of the note. * @param innerNullifier - Inner nullifier of the note. - * @param innerNoteHash - Inner note hash of the note. If this value equals 0, it means the + * @param slottedNoteHash - Slotted note hash of the note. If this value equals 0, it means the * note being nullified is from a previous transaction (and thus not a new note). */ - public nullifyNote(contractAddress: AztecAddress, innerNullifier: Fr, innerNoteHash: Fr) { + public nullifyNote(contractAddress: AztecAddress, innerNullifier: Fr, slottedNoteHash: Fr) { const siloedNullifier = siloNullifier(contractAddress, innerNullifier); const nullifiers = this.getNullifiers(contractAddress); nullifiers.add(siloedNullifier.value); this.nullifiers.set(contractAddress.toBigInt(), nullifiers); let nullifiedNoteHashCounter: number | undefined = undefined; - // Find and remove the matching new note and log(s) if the emitted innerNoteHash is not empty. - if (!innerNoteHash.equals(Fr.ZERO)) { + // Find and remove the matching new note and log(s) if the emitted slottedNoteHash is not empty. + if (!slottedNoteHash.equals(Fr.ZERO)) { const notes = this.newNotes.get(contractAddress.toBigInt()) ?? []; - const noteIndexToRemove = notes.findIndex(n => n.note.innerNoteHash.equals(innerNoteHash)); + const noteIndexToRemove = notes.findIndex(n => n.note.slottedNoteHash.equals(slottedNoteHash)); if (noteIndexToRemove === -1) { throw new Error('Attempt to remove a pending note that does not exist.'); } @@ -81,11 +81,11 @@ export class ExecutionNoteCache { * Check if a note exists in the newNotes array. * @param contractAddress - Contract address of the note. * @param storageSlot - Storage slot of the note. - * @param innerNoteHash - Inner note hash of the note. + * @param slottedNoteHash - Slotted note hash of the note. **/ - public checkNoteExists(contractAddress: AztecAddress, innerNoteHash: Fr) { + public checkNoteExists(contractAddress: AztecAddress, slottedNoteHash: Fr) { const notes = this.newNotes.get(contractAddress.toBigInt()) ?? []; - return notes.some(n => n.note.innerNoteHash.equals(innerNoteHash)); + return notes.some(n => n.note.slottedNoteHash.equals(slottedNoteHash)); } /** diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index d2384e803c9..0fa47d1f4ae 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -32,7 +32,12 @@ import { getContractInstanceFromDeployParams, getNonEmptyItems, } from '@aztec/circuits.js'; -import { computeNoteHashNonce, computeSecretHash, computeVarArgsHash } from '@aztec/circuits.js/hash'; +import { + computeNoteHashNonce, + computeSecretHash, + computeVarArgsHash, + deriveStorageSlotInMap, +} from '@aztec/circuits.js/hash'; import { makeHeader } from '@aztec/circuits.js/testing'; import { type FunctionArtifact, @@ -66,10 +71,10 @@ import { toFunctionSelector } from 'viem'; import { MessageLoadOracleInputs } from '../acvm/index.js'; import { buildL1ToL2Message } from '../test/utils.js'; -import { computeSlotForMapping } from '../utils.js'; import { type DBOracle } from './db_oracle.js'; import { CountedPublicExecutionRequest, type ExecutionResult, collectSortedEncryptedLogs } from './execution_result.js'; import { AcirSimulator } from './simulator.js'; +import { computeNoteHidingPoint, computeSlottedNoteHash } from './test_utils.js'; jest.setTimeout(60_000); @@ -316,14 +321,14 @@ describe('Private Execution test suite', () => { const noteHashIndex = randomInt(1); // mock index in TX's final noteHashes array const nonce = computeNoteHashNonce(mockFirstNullifier, noteHashIndex); const note = new Note([new Fr(amount), ownerNpkMHash, Fr.random()]); - const innerNoteHash = pedersenHash(note.items); + const slottedNoteHash = computeSlottedNoteHash(storageSlot, computeNoteHidingPoint(note.items)); return { contractAddress, storageSlot, noteTypeId, nonce, note, - innerNoteHash, + slottedNoteHash, siloedNullifier: new Fr(0), index: currentNoteIndex++, }; @@ -349,13 +354,13 @@ describe('Private Execution test suite', () => { expect(result.newNotes).toHaveLength(1); const newNote = result.newNotes[0]; - expect(newNote.storageSlot).toEqual(computeSlotForMapping(new Fr(1n), owner)); + expect(newNote.storageSlot).toEqual(deriveStorageSlotInMap(new Fr(1n), owner)); expect(newNote.noteTypeId).toEqual(valueNoteTypeId); // ValueNote const noteHashes = getNonEmptyItems(result.callStackItem.publicInputs.noteHashes); expect(noteHashes).toHaveLength(1); expect(noteHashes[0].value).toEqual( - await acirSimulator.computeInnerNoteHash( + await acirSimulator.computeSlottedNoteHash( contractAddress, newNote.storageSlot, newNote.noteTypeId, @@ -379,13 +384,13 @@ describe('Private Execution test suite', () => { expect(result.newNotes).toHaveLength(1); const newNote = result.newNotes[0]; - expect(newNote.storageSlot).toEqual(computeSlotForMapping(new Fr(1n), owner)); + expect(newNote.storageSlot).toEqual(deriveStorageSlotInMap(new Fr(1n), owner)); expect(newNote.noteTypeId).toEqual(valueNoteTypeId); // ValueNote const noteHashes = getNonEmptyItems(result.callStackItem.publicInputs.noteHashes); expect(noteHashes).toHaveLength(1); expect(noteHashes[0].value).toEqual( - await acirSimulator.computeInnerNoteHash( + await acirSimulator.computeSlottedNoteHash( contractAddress, newNote.storageSlot, newNote.noteTypeId, @@ -406,8 +411,8 @@ describe('Private Execution test suite', () => { const amountToTransfer = 100n; const artifact = getFunctionArtifact(StatefulTestContractArtifact, 'destroy_and_create_no_init_check'); - const storageSlot = computeSlotForMapping(StatefulTestContractArtifact.storageLayout['notes'].slot, owner); - const recipientStorageSlot = computeSlotForMapping( + const storageSlot = deriveStorageSlotInMap(StatefulTestContractArtifact.storageLayout['notes'].slot, owner); + const recipientStorageSlot = deriveStorageSlotInMap( StatefulTestContractArtifact.storageLayout['notes'].slot, recipient, ); @@ -446,17 +451,17 @@ describe('Private Execution test suite', () => { const noteHashes = getNonEmptyItems(result.callStackItem.publicInputs.noteHashes); expect(noteHashes).toHaveLength(2); const [changeNoteHash, recipientNoteHash] = noteHashes; - const [recipientInnerNoteHash, changeInnerNoteHash] = [ - await acirSimulator.computeInnerNoteHash( + const [recipientSlottedNoteHash, changeSlottedNoteHash] = [ + await acirSimulator.computeSlottedNoteHash( contractAddress, recipientStorageSlot, valueNoteTypeId, recipientNote.note, ), - await acirSimulator.computeInnerNoteHash(contractAddress, storageSlot, valueNoteTypeId, changeNote.note), + await acirSimulator.computeSlottedNoteHash(contractAddress, storageSlot, valueNoteTypeId, changeNote.note), ]; - expect(recipientNoteHash.value).toEqual(recipientInnerNoteHash); - expect(changeNoteHash.value).toEqual(changeInnerNoteHash); + expect(recipientNoteHash.value).toEqual(recipientSlottedNoteHash); + expect(changeNoteHash.value).toEqual(changeSlottedNoteHash); expect(recipientNote.note.items[0]).toEqual(new Fr(amountToTransfer)); expect(changeNote.note.items[0]).toEqual(new Fr(40n)); @@ -483,7 +488,7 @@ describe('Private Execution test suite', () => { const balance = 160n; const artifact = getFunctionArtifact(StatefulTestContractArtifact, 'destroy_and_create_no_init_check'); - const storageSlot = computeSlotForMapping(new Fr(1n), owner); + const storageSlot = deriveStorageSlotInMap(new Fr(1n), owner); const notes = [ buildNote( @@ -835,7 +840,7 @@ describe('Private Execution test suite', () => { storageSlot, nonce: Fr.ZERO, note, - innerNoteHash: Fr.ZERO, + slottedNoteHash: Fr.ZERO, siloedNullifier: Fr.random(), index: 1n, }, @@ -954,7 +959,7 @@ describe('Private Execution test suite', () => { expect(result.newNotes).toHaveLength(1); const noteAndSlot = result.newNotes[0]; - expect(noteAndSlot.storageSlot).toEqual(computeSlotForMapping(new Fr(1n), owner)); + expect(noteAndSlot.storageSlot).toEqual(deriveStorageSlotInMap(new Fr(1n), owner)); expect(noteAndSlot.note.items[0]).toEqual(new Fr(amountToTransfer)); @@ -962,18 +967,18 @@ describe('Private Execution test suite', () => { expect(noteHashes).toHaveLength(1); const noteHash = noteHashes[0].value; - const storageSlot = computeSlotForMapping( + const storageSlot = deriveStorageSlotInMap( PendingNoteHashesContractArtifact.storageLayout['balances'].slot, owner, ); - const innerNoteHash = await acirSimulator.computeInnerNoteHash( + const slottedNoteHash = await acirSimulator.computeSlottedNoteHash( contractAddress, storageSlot, valueNoteTypeId, noteAndSlot.note, ); - expect(noteHash).toEqual(innerNoteHash); + expect(noteHash).toEqual(slottedNoteHash); const newEncryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.noteEncryptedLogsHashes); expect(newEncryptedLogs).toHaveLength(1); @@ -983,15 +988,15 @@ describe('Private Execution test suite', () => { expect(encryptedLog.noteHashCounter).toEqual(result.noteEncryptedLogs[0].noteHashCounter); expect(encryptedLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[0].log.hash())); - // read request should match innerNoteHash for pending notes (there is no nonce, so can't compute "unique" hash) + // read request should match slottedNoteHash for pending notes (there is no nonce, so can't compute "unique" hash) const readRequest = getNonEmptyItems(result.callStackItem.publicInputs.noteHashReadRequests)[0]; - expect(readRequest.value).toEqual(innerNoteHash); + expect(readRequest.value).toEqual(slottedNoteHash); expect(result.returnValues).toEqual([new Fr(amountToTransfer)]); const nullifier = result.callStackItem.publicInputs.nullifiers[0]; const expectedNullifier = poseidon2Hash([ - innerNoteHash, + slottedNoteHash, computeAppNullifierSecretKey(ownerNskM, contractAddress), GeneratorIndex.NOTE_NULLIFIER, ]); @@ -1035,7 +1040,7 @@ describe('Private Execution test suite', () => { const execInsert = result.nestedExecutions[0]; const execGetThenNullify = result.nestedExecutions[1]; - const storageSlot = computeSlotForMapping( + const storageSlot = deriveStorageSlotInMap( PendingNoteHashesContractArtifact.storageLayout['balances'].slot, owner, ); @@ -1051,13 +1056,13 @@ describe('Private Execution test suite', () => { expect(noteHashes).toHaveLength(1); const noteHash = noteHashes[0].value; - const innerNoteHash = await acirSimulator.computeInnerNoteHash( + const slottedNoteHash = await acirSimulator.computeSlottedNoteHash( contractAddress, noteAndSlot.storageSlot, noteAndSlot.noteTypeId, noteAndSlot.note, ); - expect(noteHash).toEqual(innerNoteHash); + expect(noteHash).toEqual(slottedNoteHash); const newEncryptedLogs = getNonEmptyItems(execInsert.callStackItem.publicInputs.noteEncryptedLogsHashes); expect(newEncryptedLogs).toHaveLength(1); @@ -1067,15 +1072,15 @@ describe('Private Execution test suite', () => { expect(encryptedLog.noteHashCounter).toEqual(execInsert.noteEncryptedLogs[0].noteHashCounter); expect(encryptedLog.value).toEqual(Fr.fromBuffer(execInsert.noteEncryptedLogs[0].log.hash())); - // read request should match innerNoteHash for pending notes (there is no nonce, so can't compute "unique" hash) + // read request should match slottedNoteHash for pending notes (there is no nonce, so can't compute "unique" hash) const readRequest = execGetThenNullify.callStackItem.publicInputs.noteHashReadRequests[0]; - expect(readRequest.value).toEqual(innerNoteHash); + expect(readRequest.value).toEqual(slottedNoteHash); expect(execGetThenNullify.returnValues).toEqual([new Fr(amountToTransfer)]); const nullifier = execGetThenNullify.callStackItem.publicInputs.nullifiers[0]; const expectedNullifier = poseidon2Hash([ - innerNoteHash, + slottedNoteHash, computeAppNullifierSecretKey(ownerNskM, contractAddress), GeneratorIndex.NOTE_NULLIFIER, ]); diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index a761bb4df8f..8b15e719630 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -1,11 +1,6 @@ import { type AztecNode, CompleteAddress, Note } from '@aztec/circuit-types'; import { GeneratorIndex, KeyValidationRequest, computeAppNullifierSecretKey, deriveKeys } from '@aztec/circuits.js'; -import { - computeInnerNoteHash, - computeNoteContentHash, - computeUniqueNoteHash, - siloNoteHash, -} from '@aztec/circuits.js/hash'; +import { computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash'; import { type FunctionArtifact, getFunctionArtifact } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { poseidon2Hash } from '@aztec/foundation/crypto'; @@ -16,6 +11,7 @@ import { type MockProxy, mock } from 'jest-mock-extended'; import { type DBOracle } from './db_oracle.js'; import { AcirSimulator } from './simulator.js'; +import { computeNoteHidingPoint, computeSlottedNoteHash } from './test_utils.js'; describe('Simulator', () => { let oracle: MockProxy; @@ -62,9 +58,9 @@ describe('Simulator', () => { oracle.getFunctionArtifactByName.mockResolvedValue(artifact); const note = createNote(); - const tokenNoteHash = computeNoteContentHash(note.items); - const innerNoteHash = computeInnerNoteHash(storageSlot, tokenNoteHash); - const uniqueNoteHash = computeUniqueNoteHash(nonce, innerNoteHash); + const noteHidingPoint = computeNoteHidingPoint(note.items); + const slottedNoteHash = computeSlottedNoteHash(storageSlot, noteHidingPoint); + const uniqueNoteHash = computeUniqueNoteHash(nonce, slottedNoteHash); const siloedNoteHash = siloNoteHash(contractAddress, uniqueNoteHash); const innerNullifier = poseidon2Hash([siloedNoteHash, appNullifierSecretKey, GeneratorIndex.NOTE_NULLIFIER]); @@ -78,7 +74,7 @@ describe('Simulator', () => { ); expect(result).toEqual({ - innerNoteHash, + slottedNoteHash, uniqueNoteHash, siloedNoteHash, innerNullifier, diff --git a/yarn-project/simulator/src/client/simulator.ts b/yarn-project/simulator/src/client/simulator.ts index 0f31da45780..e23bb42ea6d 100644 --- a/yarn-project/simulator/src/client/simulator.ts +++ b/yarn-project/simulator/src/client/simulator.ts @@ -188,14 +188,14 @@ export class AcirSimulator { returnTypes: artifact.returnTypes, }; - const [innerNoteHash, uniqueNoteHash, siloedNoteHash, innerNullifier] = (await this.runUnconstrained( + const [slottedNoteHash, uniqueNoteHash, siloedNoteHash, innerNullifier] = (await this.runUnconstrained( execRequest, artifact, contractAddress, )) as bigint[]; return { - innerNoteHash: new Fr(innerNoteHash), + slottedNoteHash: new Fr(slottedNoteHash), uniqueNoteHash: new Fr(uniqueNoteHash), siloedNoteHash: new Fr(siloedNoteHash), innerNullifier: new Fr(innerNullifier), @@ -203,20 +203,20 @@ export class AcirSimulator { } /** - * Computes the inner note hash of a note, which contains storage slot and the custom note hash. + * Computes the slotted note hash of a note, which contains storage slot and the custom note hash. * @param contractAddress - The address of the contract. * @param storageSlot - The storage slot. * @param noteTypeId - The note type identifier. * @param note - The note. * @returns The note hash. */ - public async computeInnerNoteHash( + public async computeSlottedNoteHash( contractAddress: AztecAddress, storageSlot: Fr, noteTypeId: NoteSelector, note: Note, ) { - const { innerNoteHash } = await this.computeNoteHashAndOptionallyANullifier( + const { slottedNoteHash } = await this.computeNoteHashAndOptionallyANullifier( contractAddress, Fr.ZERO, storageSlot, @@ -224,6 +224,6 @@ export class AcirSimulator { false, note, ); - return innerNoteHash; + return slottedNoteHash; } } diff --git a/yarn-project/simulator/src/client/test_utils.ts b/yarn-project/simulator/src/client/test_utils.ts new file mode 100644 index 00000000000..0470397fafd --- /dev/null +++ b/yarn-project/simulator/src/client/test_utils.ts @@ -0,0 +1,35 @@ +import { Fq, Fr, GeneratorIndex, Point } from '@aztec/circuits.js'; +import { Grumpkin } from '@aztec/circuits.js/barretenberg'; +import { pedersenHash } from '@aztec/foundation/crypto'; + +// Copied over from `noir-projects/aztec-nr/aztec/src/generators.nr` +const G_SLOT = new Point( + new Fr(0x041223147b680850dc82e8a55a952d4df20256fe0593d949a9541ca00f0abf15n), + new Fr(0x0a8c72e60d0e60f5d804549d48f3044d06140b98ed717a9b532af630c1530791n), + false, +); + +/** + * Computes a note hiding point as is done by the default implementation injected by macros. + * @param noteContent - The note content (e.g. note.items). + * @returns A note hiding point. + */ +export function computeNoteHidingPoint(noteContent: Fr[]): Point { + // TODO(#7551): how this is computed will need to be updated + const h = pedersenHash(noteContent, GeneratorIndex.NOTE_HIDING_POINT); + const grumpkin = new Grumpkin(); + return grumpkin.mul(G_SLOT, new Fq(h.toBigInt())); +} + +/** + * Computes an slotted note hash, given a storage slot and a note hiding point. + * @param storageSlot - The storage slot. + * @param noteHidingPoint - The note hiding point. + * @returns A slotted note hash. + */ +export function computeSlottedNoteHash(storageSlot: Fr, noteHidingPoint: Point): Fr { + const grumpkin = new Grumpkin(); + const storageSlotPoint = grumpkin.mul(G_SLOT, new Fq(storageSlot.toBigInt())); + const slottedNoteHidingPoint = grumpkin.add(storageSlotPoint, noteHidingPoint); + return slottedNoteHidingPoint.x; +} diff --git a/yarn-project/simulator/src/client/unconstrained_execution.test.ts b/yarn-project/simulator/src/client/unconstrained_execution.test.ts index fbca7486e34..e446f01d8b5 100644 --- a/yarn-project/simulator/src/client/unconstrained_execution.test.ts +++ b/yarn-project/simulator/src/client/unconstrained_execution.test.ts @@ -61,7 +61,7 @@ describe('Unconstrained Execution test suite', () => { nonce: Fr.random(), isSome: new Fr(1), note, - innerNoteHash: Fr.random(), + slottedNoteHash: Fr.random(), siloedNullifier: Fr.random(), index: BigInt(index), })), diff --git a/yarn-project/simulator/src/index.ts b/yarn-project/simulator/src/index.ts index 444584e171a..fc5a4653413 100644 --- a/yarn-project/simulator/src/index.ts +++ b/yarn-project/simulator/src/index.ts @@ -6,4 +6,3 @@ export * from './public/index.js'; export * from './providers/index.js'; export * from './mocks/index.js'; export * from './stats/index.js'; -export * from './utils.js'; diff --git a/yarn-project/simulator/src/public/fee_payment.ts b/yarn-project/simulator/src/public/fee_payment.ts index 721f9055d4e..48082451122 100644 --- a/yarn-project/simulator/src/public/fee_payment.ts +++ b/yarn-project/simulator/src/public/fee_payment.ts @@ -1,16 +1,14 @@ import { GAS_TOKEN_ADDRESS } from '@aztec/circuits.js'; -import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash'; +import { computePublicDataTreeLeafSlot, deriveStorageSlotInMap } from '@aztec/circuits.js/hash'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { GasTokenArtifact } from '@aztec/protocol-contracts/gas-token'; -import { computeSlotForMapping } from '../utils.js'; - /** * Computes the storage slot within the gas token contract for the balance of the fee payer. */ export function computeFeePayerBalanceStorageSlot(feePayer: AztecAddress) { - return computeSlotForMapping(GasTokenArtifact.storageLayout.balances.slot, feePayer); + return deriveStorageSlotInMap(GasTokenArtifact.storageLayout.balances.slot, feePayer); } /** diff --git a/yarn-project/simulator/src/utils.ts b/yarn-project/simulator/src/utils.ts deleted file mode 100644 index 380222fa578..00000000000 --- a/yarn-project/simulator/src/utils.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { pedersenHash } from '@aztec/foundation/crypto'; -import { type Fr } from '@aztec/foundation/fields'; - -/** - * Computes the resulting storage slot for an entry in a mapping. - * @param mappingSlot - The slot of the mapping within state. - * @param key - The key of the mapping. - * @returns The slot in the contract storage where the value is stored. - */ -export function computeSlotForMapping( - mappingSlot: Fr, - key: { - /** Serialize to a field. */ - toField: () => Fr; - }, -) { - return pedersenHash([mappingSlot, key.toField()]); -} diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 474ba90cbe9..949e181179a 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -213,9 +213,9 @@ export class TXE implements TypedOracle { return Promise.resolve(); } - async avmOpcodeEmitNoteHash(innerNoteHash: Fr) { + async avmOpcodeEmitNoteHash(slottedNoteHash: Fr) { const db = this.trees.asLatest(); - const noteHash = siloNoteHash(this.contractAddress, innerNoteHash); + const noteHash = siloNoteHash(this.contractAddress, slottedNoteHash); await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, [noteHash]); return Promise.resolve(); } @@ -240,9 +240,9 @@ export class TXE implements TypedOracle { await db.batchInsert(MerkleTreeId.NULLIFIER_TREE, siloedNullifiers, NULLIFIER_SUBTREE_HEIGHT); } - async addNoteHashes(contractAddress: AztecAddress, innerNoteHashes: Fr[]) { + async addNoteHashes(contractAddress: AztecAddress, slottedNoteHashes: Fr[]) { const db = this.trees.asLatest(); - const siloedNoteHashes = innerNoteHashes.map(innerNoteHash => siloNoteHash(contractAddress, innerNoteHash)); + const siloedNoteHashes = slottedNoteHashes.map(slottedNoteHash => siloNoteHash(contractAddress, slottedNoteHash)); await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, siloedNoteHashes); } @@ -402,7 +402,7 @@ export class TXE implements TypedOracle { return Promise.resolve(notes); } - notifyCreatedNote(storageSlot: Fr, noteTypeId: NoteSelector, noteItems: Fr[], innerNoteHash: Fr, counter: number) { + notifyCreatedNote(storageSlot: Fr, noteTypeId: NoteSelector, noteItems: Fr[], slottedNoteHash: Fr, counter: number) { const note = new Note(noteItems); this.noteCache.addNewNote( { @@ -411,15 +411,15 @@ export class TXE implements TypedOracle { nonce: Fr.ZERO, // Nonce cannot be known during private execution. note, siloedNullifier: undefined, // Siloed nullifier cannot be known for newly created note. - innerNoteHash, + slottedNoteHash, }, counter, ); return Promise.resolve(); } - notifyNullifiedNote(innerNullifier: Fr, innerNoteHash: Fr, _counter: number) { - this.noteCache.nullifyNote(this.contractAddress, innerNullifier, innerNoteHash); + notifyNullifiedNote(innerNullifier: Fr, slottedNoteHash: Fr, _counter: number) { + this.noteCache.nullifyNote(this.contractAddress, innerNullifier, slottedNoteHash); return Promise.resolve(); } diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index 08dfa7fca25..a71ec4a388d 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -442,14 +442,14 @@ export class TXEService { storageSlot: ForeignCallSingle, noteTypeId: ForeignCallSingle, note: ForeignCallArray, - innerNoteHash: ForeignCallSingle, + slottedNoteHash: ForeignCallSingle, counter: ForeignCallSingle, ) { this.typedOracle.notifyCreatedNote( fromSingle(storageSlot), NoteSelector.fromField(fromSingle(noteTypeId)), fromArray(note), - fromSingle(innerNoteHash), + fromSingle(slottedNoteHash), fromSingle(counter).toNumber(), ); return toForeignCallResult([toSingle(new Fr(0))]); @@ -457,12 +457,12 @@ export class TXEService { async notifyNullifiedNote( innerNullifier: ForeignCallSingle, - innerNoteHash: ForeignCallSingle, + slottedNoteHash: ForeignCallSingle, counter: ForeignCallSingle, ) { await this.typedOracle.notifyNullifiedNote( fromSingle(innerNullifier), - fromSingle(innerNoteHash), + fromSingle(slottedNoteHash), fromSingle(counter).toNumber(), ); return toForeignCallResult([toSingle(new Fr(0))]); @@ -511,8 +511,8 @@ export class TXEService { return toForeignCallResult([]); } - async avmOpcodeEmitNoteHash(innerNoteHash: ForeignCallSingle) { - await (this.typedOracle as TXE).avmOpcodeEmitNoteHash(fromSingle(innerNoteHash)); + async avmOpcodeEmitNoteHash(slottedNoteHash: ForeignCallSingle) { + await (this.typedOracle as TXE).avmOpcodeEmitNoteHash(fromSingle(slottedNoteHash)); return toForeignCallResult([]); } From 19cdf01b44857d5e087c3ca7f804bd471e23d8e0 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 31 Jul 2024 14:56:05 +0100 Subject: [PATCH 20/35] fix: capture devnet cli errors (#7685) --- .github/workflows/devnet-deploys.yml | 30 ++++++++-------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index e604e5b27dd..99720a8dd80 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -121,19 +121,15 @@ jobs: - name: Deploy L1 Contracts run: | + set -e + set -o pipefail + docker pull aztecprotocol/aztec:${{ env.DEPLOY_TAG }} docker run aztecprotocol/aztec:${{ env.DEPLOY_TAG }} deploy-l1-contracts \ --private-key ${{ secrets.CONTRACT_PUBLISHER_PRIVATE_KEY }} \ --rpc-url https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ --l1-chain-id ${{ env.L1_CHAIN_ID }} \ - --json \ - | tee ./l1_contracts.json - - - if [ $? -ne 0 ]; then - echo "deploy-l1-contracts command failed" - exit 1 - fi + --json | tee ./l1_contracts.json # upload contract addresses to S3 aws s3 cp ./l1_contracts.json ${{ env.CONTRACT_S3_BUCKET }}/${{ env.DEPLOY_TAG }}/l1_contracts.json @@ -210,35 +206,25 @@ jobs: - name: Deploy protocol contracts run: | set -e + set -o pipefail docker pull aztecprotocol/aztec:${{ env.DEPLOY_TAG }} docker run aztecprotocol/aztec:${{ env.DEPLOY_TAG }} deploy-protocol-contracts \ --rpc-url https://api.aztec.network/${{ env.DEPLOY_TAG }}/aztec-pxe/${{ secrets.FORK_API_KEY }} \ --l1-chain-id ${{ env.L1_CHAIN_ID }} \ - --json \ - | tee ./protocol_contracts.json - - if [ $? -ne 0 ]; then - echo "deploy-protocol-contracts command failed" - exit 1 - fi + --json | tee ./protocol_contracts.json aws s3 cp ./protocol_contracts.json ${{ env.CONTRACT_S3_BUCKET }}/${{ env.DEPLOY_TAG }}/protocol_contracts.json - name: Bootstrap network run: | set -e + set -o pipefail docker run aztecprotocol/aztec:${{ env.DEPLOY_TAG }} bootstrap-network \ --rpc-url https://api.aztec.network/${{ env.DEPLOY_TAG }}/aztec-pxe/${{ secrets.FORK_API_KEY }} \ --l1-rpc-url https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ --l1-chain-id ${{ env.L1_CHAIN_ID }} \ --l1-private-key ${{ secrets.CONTRACT_PUBLISHER_PRIVATE_KEY }} \ - --json \ - | tee ./basic_contracts.json - - if [ $? -ne 0 ]; then - echo "bootstrap-network command failed" - exit 1 - fi + --json | tee ./basic_contracts.json aws s3 cp ./basic_contracts.json ${{ env.CONTRACT_S3_BUCKET }}/${{ env.DEPLOY_TAG }}/basic_contracts.json From 43a83aec4572f17444ba9d6d1e4c141dbbc07a76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Wed, 31 Jul 2024 17:07:39 +0200 Subject: [PATCH 21/35] chore: renaming private token as token with refunds (#7626) Private token makes me think that the token is working only with private state so the name is confusing. Also I plan on using the reference token impl and just extending it with the refund stuff in a future PR. This makes sense because a lot of the custom changes to the token were made because npk was used instead of owner address --> this required modiying balances_map. Given that this will be tackled the standard way now that we are able to compute slotted hiding point in private I can revert most of the custom changes to the token. --- noir-projects/noir-contracts/Nargo.toml | 2 +- .../contracts/private_fpc_contract/Nargo.toml | 2 +- .../private_fpc_contract/src/main.nr | 4 +- .../Nargo.toml | 2 +- .../src/main.nr | 17 ++----- .../src/test.nr | 0 .../src/test/basic.nr | 10 ++-- .../src/test/utils.nr | 10 ++-- .../src/types.nr | 0 .../src/types/balances_map.nr | 0 .../src/types/token_note.nr | 0 .../end-to-end/src/e2e_fees/fees_test.ts | 46 +++++++++++-------- .../src/e2e_fees/private_refunds.test.ts | 33 ++++++------- 13 files changed, 63 insertions(+), 63 deletions(-) rename noir-projects/noir-contracts/contracts/{private_token_contract => token_with_refunds_contract}/Nargo.toml (87%) rename noir-projects/noir-contracts/contracts/{private_token_contract => token_with_refunds_contract}/src/main.nr (93%) rename noir-projects/noir-contracts/contracts/{private_token_contract => token_with_refunds_contract}/src/test.nr (100%) rename noir-projects/noir-contracts/contracts/{private_token_contract => token_with_refunds_contract}/src/test/basic.nr (89%) rename noir-projects/noir-contracts/contracts/{private_token_contract => token_with_refunds_contract}/src/test/utils.nr (83%) rename noir-projects/noir-contracts/contracts/{private_token_contract => token_with_refunds_contract}/src/types.nr (100%) rename noir-projects/noir-contracts/contracts/{private_token_contract => token_with_refunds_contract}/src/types/balances_map.nr (100%) rename noir-projects/noir-contracts/contracts/{private_token_contract => token_with_refunds_contract}/src/types/token_note.nr (100%) diff --git a/noir-projects/noir-contracts/Nargo.toml b/noir-projects/noir-contracts/Nargo.toml index 13e3d4d0613..bbd466a5585 100644 --- a/noir-projects/noir-contracts/Nargo.toml +++ b/noir-projects/noir-contracts/Nargo.toml @@ -31,7 +31,7 @@ members = [ "contracts/pending_note_hashes_contract", "contracts/price_feed_contract", "contracts/private_fpc_contract", - "contracts/private_token_contract", + "contracts/token_with_refunds_contract", "contracts/schnorr_account_contract", "contracts/schnorr_hardcoded_account_contract", "contracts/schnorr_single_key_account_contract", diff --git a/noir-projects/noir-contracts/contracts/private_fpc_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/private_fpc_contract/Nargo.toml index 94f9996c80b..4f07243c139 100644 --- a/noir-projects/noir-contracts/contracts/private_fpc_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/private_fpc_contract/Nargo.toml @@ -7,4 +7,4 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } authwit = { path = "../../../aztec-nr/authwit" } -private_token = { path = "../private_token_contract" } +token_with_refunds = { path = "../token_with_refunds_contract" } diff --git a/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr index c4d5adea2b1..238ae7f4fca 100644 --- a/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr @@ -3,7 +3,7 @@ mod lib; contract PrivateFPC { use dep::aztec::protocol_types::{abis::log_hash::LogHash, address::AztecAddress, hash::poseidon2_hash}; use dep::aztec::state_vars::SharedImmutable; - use dep::private_token::PrivateToken; + use dep::token_with_refunds::TokenWithRefunds; use crate::lib::emit_randomness_as_unencrypted_log; #[aztec(storage)] @@ -31,7 +31,7 @@ contract PrivateFPC { // We emit fee payer randomness to ensure FPC admin can reconstruct their fee note emit_randomness_as_unencrypted_log(&mut context, fee_payer_randomness); - PrivateToken::at(asset).setup_refund( + TokenWithRefunds::at(asset).setup_refund( storage.admin_npk_m_hash.read_private(), context.msg_sender(), amount, diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/Nargo.toml similarity index 87% rename from noir-projects/noir-contracts/contracts/private_token_contract/Nargo.toml rename to noir-projects/noir-contracts/contracts/token_with_refunds_contract/Nargo.toml index 8d410f64565..a7f7c4b3586 100644 --- a/noir-projects/noir-contracts/contracts/private_token_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "private_token_contract" +name = "token_with_refunds_contract" authors = [""] compiler_version = ">=0.25.0" type = "contract" diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr similarity index 93% rename from noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr rename to noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr index 6c0890726d6..9a943af45e7 100644 --- a/noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr @@ -3,7 +3,7 @@ mod test; // Minimal token implementation that supports `AuthWit` accounts and private refunds -contract PrivateToken { +contract TokenWithRefunds { use dep::compressed_string::FieldCompressedString; use dep::aztec::{ note::utils::compute_slotted_note_hash_raw, hash::compute_secret_hash, @@ -97,7 +97,7 @@ contract PrivateToken { let header = context.get_header(); let caller_npk_m_hash = header.get_npk_m_hash(&mut context, caller); storage.balances.add(caller_npk_m_hash, U128::from_integer(amount)).emit(encode_and_encrypt_note(&mut context, caller, caller)); - PrivateToken::at(context.this_address()).assert_minter_and_mint(context.msg_sender(), amount).enqueue(&mut context); + TokenWithRefunds::at(context.this_address()).assert_minter_and_mint(context.msg_sender(), amount).enqueue(&mut context); } #[aztec(public)] @@ -205,16 +205,9 @@ contract PrivateToken { let tx_fee = context.transaction_fee(); let (fee_payer_note_hiding_point, user_note_hiding_point) = TokenNote::complete_refund(fee_payer_point, user_point, tx_fee); - // 2. Now we "manually" compute the slotted note hashes. - let fee_payer_slotted_note_hash = compute_slotted_note_hash_raw( - PrivateToken::storage().balances.slot, - fee_payer_note_hiding_point - ); - let user_slotted_note_hash = compute_slotted_note_hash_raw(PrivateToken::storage().balances.slot, user_note_hiding_point); - - // 3. At last we emit the note hashes. - context.push_note_hash(fee_payer_slotted_note_hash); - context.push_note_hash(user_slotted_note_hash); + // 2. At last we emit the note hashes. + context.push_note_hash(fee_payer_note_hiding_point.x); + context.push_note_hash(user_note_hiding_point.x); // --> Once the tx is settled user and fee recipient can add the notes to their pixies. } diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/test.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test.nr similarity index 100% rename from noir-projects/noir-contracts/contracts/private_token_contract/src/test.nr rename to noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test.nr diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/test/basic.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/basic.nr similarity index 89% rename from noir-projects/noir-contracts/contracts/private_token_contract/src/test/basic.nr rename to noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/basic.nr index dc593bf1085..98510f8a443 100644 --- a/noir-projects/noir-contracts/contracts/private_token_contract/src/test/basic.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/basic.nr @@ -3,7 +3,7 @@ use dep::aztec::{ test::helpers::cheatcodes, oracle::unsafe_rand::unsafe_rand, hash::compute_secret_hash, prelude::NoteHeader }; -use crate::PrivateToken; +use crate::TokenWithRefunds; use crate::types::token_note::TokenNote; use dep::authwit::cheatcodes as authwit_cheatcodes; @@ -13,7 +13,7 @@ unconstrained fn transfer_success() { let transfer_amount = 1_000; - let transfer_private_from_call_interface = PrivateToken::at(token_contract_address).transfer_from(owner, recipient, transfer_amount, 1); + let transfer_private_from_call_interface = TokenWithRefunds::at(token_contract_address).transfer_from(owner, recipient, transfer_amount, 1); authwit_cheatcodes::add_private_authwit_from_call_interface(owner, recipient, transfer_private_from_call_interface); @@ -45,7 +45,7 @@ unconstrained fn setup_refund_success() { let mut context = env.private(); let recipient_npk_m_hash = context.get_header().get_npk_m_hash(&mut context, recipient); - let setup_refund_from_call_interface = PrivateToken::at(token_contract_address).setup_refund( + let setup_refund_from_call_interface = TokenWithRefunds::at(token_contract_address).setup_refund( recipient_npk_m_hash, // fee payer owner, // sponsored user funded_amount, @@ -75,7 +75,7 @@ unconstrained fn setup_refund_success() { randomness: user_randomness, header: NoteHeader::empty() }, - PrivateToken::storage().balances.slot, + TokenWithRefunds::storage().balances.slot, token_contract_address ); env.store_note_in_cache( @@ -85,7 +85,7 @@ unconstrained fn setup_refund_success() { randomness: fee_payer_randomness, header: NoteHeader::empty() }, - PrivateToken::storage().balances.slot, + TokenWithRefunds::storage().balances.slot, token_contract_address ); diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/test/utils.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/utils.nr similarity index 83% rename from noir-projects/noir-contracts/contracts/private_token_contract/src/test/utils.nr rename to noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/utils.nr index f97e2706a79..b2dfd177921 100644 --- a/noir-projects/noir-contracts/contracts/private_token_contract/src/test/utils.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/utils.nr @@ -6,7 +6,7 @@ use dep::aztec::{ context::PrivateContext }; -use crate::{types::{token_note::TokenNote}, PrivateToken}; +use crate::{types::{token_note::TokenNote}, TokenWithRefunds}; pub fn setup(with_account_contracts: bool) -> (&mut TestEnvironment, AztecAddress, AztecAddress, AztecAddress) { // Setup env, generate keys @@ -27,13 +27,13 @@ pub fn setup(with_account_contracts: bool) -> (&mut TestEnvironment, AztecAddres env.impersonate(owner); // Deploy token contract - let initializer_call_interface = PrivateToken::interface().constructor( + let initializer_call_interface = TokenWithRefunds::interface().constructor( owner, "TestToken0000000000000000000000", "TT00000000000000000000000000000", 18 ); - let token_contract = env.deploy_self("PrivateToken").with_public_initializer(initializer_call_interface); + let token_contract = env.deploy_self("TokenWithRefunds").with_public_initializer(initializer_call_interface); let token_contract_address = token_contract.to_address(); env.advance_block_by(6); (&mut env, token_contract_address, owner, recipient) @@ -43,7 +43,7 @@ pub fn setup_and_mint(with_account_contracts: bool) -> (&mut TestEnvironment, Az // Setup let (env, token_contract_address, owner, recipient) = setup(with_account_contracts); let mint_amount = 10_000; - let mint_private_call_interface = PrivateToken::at(token_contract_address).privately_mint_private_note(mint_amount); + let mint_private_call_interface = TokenWithRefunds::at(token_contract_address).privately_mint_private_note(mint_amount); env.call_private_void(mint_private_call_interface); env.advance_block_by(6); @@ -64,7 +64,7 @@ pub fn check_private_balance( let header = context.get_header(); let owner_npk_m_hash = header.get_npk_m_hash(context, address); - let balance_of_private = PrivateToken::balance_of_unconstrained(owner_npk_m_hash); + let balance_of_private = TokenWithRefunds::balance_of_unconstrained(owner_npk_m_hash); assert(balance_of_private == address_amount, "Private balance is not correct"); cheatcodes::set_contract_address(current_contract_address); } diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/types.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types.nr similarity index 100% rename from noir-projects/noir-contracts/contracts/private_token_contract/src/types.nr rename to noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types.nr diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/balances_map.nr similarity index 100% rename from noir-projects/noir-contracts/contracts/private_token_contract/src/types/balances_map.nr rename to noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/balances_map.nr diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr similarity index 100% rename from noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr rename to noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr diff --git a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts index ef1dce54c36..a3e0792c435 100644 --- a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts @@ -24,7 +24,7 @@ import { FPCContract, GasTokenContract, PrivateFPCContract, - PrivateTokenContract, + TokenWithRefundsContract, } from '@aztec/noir-contracts.js'; import { getCanonicalGasToken } from '@aztec/protocol-contracts/gas-token'; @@ -67,7 +67,7 @@ export class FeesTest { public gasTokenContract!: GasTokenContract; public bananaCoin!: BananaCoin; public bananaFPC!: FPCContract; - public privateToken!: PrivateTokenContract; + public tokenWithRefunds!: TokenWithRefundsContract; public privateFPC!: PrivateFPCContract; public counterContract!: CounterContract; public subscriptionContract!: AppSubscriptionContract; @@ -77,7 +77,7 @@ export class FeesTest { public getGasBalanceFn!: BalancesFn; public getBananaPublicBalanceFn!: BalancesFn; public getBananaPrivateBalanceFn!: BalancesFn; - public getPrivateTokenBalanceFn!: BalancesFn; + public getTokenWithRefundsBalanceFn!: BalancesFn; public readonly INITIAL_GAS_BALANCE = BigInt(1e15); public readonly ALICE_INITIAL_BANANAS = BigInt(1e12); @@ -99,11 +99,11 @@ export class FeesTest { await this.snapshotManager.teardown(); } - /** Alice mints PrivateToken */ - async mintPrivateTokens(amount: bigint) { - const balanceBefore = await this.privateToken.methods.balance_of_private(this.aliceAddress).simulate(); - await this.privateToken.methods.privately_mint_private_note(amount).send().wait(); - const balanceAfter = await this.privateToken.methods.balance_of_private(this.aliceAddress).simulate(); + /** Alice mints TokenWithRefunds */ + async mintTokenWithRefunds(amount: bigint) { + const balanceBefore = await this.tokenWithRefunds.methods.balance_of_private(this.aliceAddress).simulate(); + await this.tokenWithRefunds.methods.privately_mint_private_note(amount).send().wait(); + const balanceAfter = await this.tokenWithRefunds.methods.balance_of_private(this.aliceAddress).simulate(); expect(balanceAfter).toEqual(balanceBefore + amount); } @@ -242,22 +242,28 @@ export class FeesTest { ); } - async applyPrivateTokenAndFPC() { + async applyTokenWithRefundsAndFPC() { await this.snapshotManager.snapshot( - 'private_token_and_private_fpc', + 'token_with_refunds_and_private_fpc', async context => { // Deploy token/fpc flavors for private refunds const gasTokenContract = this.gasBridgeTestHarness.l2Token; expect(await context.pxe.isContractPubliclyDeployed(gasTokenContract.address)).toBe(true); - const privateToken = await PrivateTokenContract.deploy(this.aliceWallet, this.aliceAddress, 'PVT', 'PVT', 18n) + const tokenWithRefunds = await TokenWithRefundsContract.deploy( + this.aliceWallet, + this.aliceAddress, + 'PVT', + 'PVT', + 18n, + ) .send() .deployed(); - this.logger.info(`PrivateToken deployed at ${privateToken.address}`); + this.logger.info(`TokenWithRefunds deployed at ${tokenWithRefunds.address}`); const adminKeyHash = this.bobWallet.getCompleteAddress().publicKeys.masterNullifierPublicKey.hash(); - const privateFPCSent = PrivateFPCContract.deploy(this.bobWallet, privateToken.address, adminKeyHash).send(); + const privateFPCSent = PrivateFPCContract.deploy(this.bobWallet, tokenWithRefunds.address, adminKeyHash).send(); const privateFPC = await privateFPCSent.deployed(); this.logger.info(`PrivateFPC deployed at ${privateFPC.address}`); @@ -268,18 +274,18 @@ export class FeesTest { ); return { - privateTokenAddress: privateToken.address, + tokenWithRefundsAddress: tokenWithRefunds.address, privateFPCAddress: privateFPC.address, }; }, async data => { this.privateFPC = await PrivateFPCContract.at(data.privateFPCAddress, this.bobWallet); - this.privateToken = await PrivateTokenContract.at(data.privateTokenAddress, this.aliceWallet); + this.tokenWithRefunds = await TokenWithRefundsContract.at(data.tokenWithRefundsAddress, this.aliceWallet); const logger = this.logger; - this.getPrivateTokenBalanceFn = getBalancesFn( + this.getTokenWithRefundsBalanceFn = getBalancesFn( '🕵️.private', - this.privateToken.methods.balance_of_private, + this.tokenWithRefunds.methods.balance_of_private, logger, ); }, @@ -348,11 +354,11 @@ export class FeesTest { ); } - public async applyFundAliceWithPrivateTokens() { + public async applyFundAliceWithTokens() { await this.snapshotManager.snapshot( - 'fund_alice_with_private_tokens', + 'fund_alice_with_tokens', async () => { - await this.mintPrivateTokens(BigInt(this.ALICE_INITIAL_BANANAS)); + await this.mintTokenWithRefunds(BigInt(this.ALICE_INITIAL_BANANAS)); }, () => Promise.resolve(), ); diff --git a/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts b/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts index 963cb351ce0..bfee50babff 100644 --- a/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts @@ -9,7 +9,7 @@ import { import { Fr, type GasSettings } from '@aztec/circuits.js'; import { FunctionSelector, FunctionType } from '@aztec/foundation/abi'; import { poseidon2Hash } from '@aztec/foundation/crypto'; -import { type PrivateFPCContract, PrivateTokenContract } from '@aztec/noir-contracts.js'; +import { type PrivateFPCContract, TokenWithRefundsContract } from '@aztec/noir-contracts.js'; import { expectMapping } from '../fixtures/utils.js'; import { FeesTest } from './fees_test.js'; @@ -17,7 +17,7 @@ import { FeesTest } from './fees_test.js'; describe('e2e_fees/private_refunds', () => { let aliceWallet: Wallet; let aliceAddress: AztecAddress; - let privateToken: PrivateTokenContract; + let tokenWithRefunds: TokenWithRefundsContract; let privateFPC: PrivateFPCContract; let initialAliceBalance: bigint; @@ -31,9 +31,9 @@ describe('e2e_fees/private_refunds', () => { await t.applyInitialAccountsSnapshot(); await t.applyPublicDeployAccountsSnapshot(); await t.applyDeployGasTokenSnapshot(); - await t.applyPrivateTokenAndFPC(); - await t.applyFundAliceWithPrivateTokens(); - ({ aliceWallet, aliceAddress, privateFPC, privateToken } = await t.setup()); + await t.applyTokenWithRefundsAndFPC(); + await t.applyFundAliceWithTokens(); + ({ aliceWallet, aliceAddress, privateFPC, tokenWithRefunds } = await t.setup()); t.logger.debug(`Alice address: ${aliceAddress}`); }); @@ -43,12 +43,13 @@ describe('e2e_fees/private_refunds', () => { beforeEach(async () => { [[initialAliceBalance, initialBobBalance], [initialFPCGasBalance]] = await Promise.all([ - t.getPrivateTokenBalanceFn(aliceAddress, t.bobAddress), + t.getTokenWithRefundsBalanceFn(aliceAddress, t.bobAddress), t.getGasBalanceFn(privateFPC.address), ]); }); - it('can do private payments and refunds', async () => { + // This will get re-enabled in a PR up the stack. + it.skip('can do private payments and refunds', async () => { // 1. We get the hash of Bob's master nullifier public key. The corresponding nullifier secret key can later on // be used to nullify/spend the note that contains the npk_m_hash. // TODO(#7324): The values in complete address are currently not updated after the keys are rotated so this does @@ -58,13 +59,13 @@ describe('e2e_fees/private_refunds', () => { const bobRandomness = poseidon2Hash([aliceRandomness]); // Called fee_payer_randomness in contracts // 2. We call arbitrary `private_get_name(...)` function to check that the fee refund flow works. - const tx = await privateToken.methods + const tx = await tokenWithRefunds.methods .private_get_name() .send({ fee: { gasSettings: t.gasSettings, paymentMethod: new PrivateRefundPaymentMethod( - privateToken.address, + tokenWithRefunds.address, privateFPC.address, aliceWallet, aliceRandomness, @@ -99,9 +100,9 @@ describe('e2e_fees/private_refunds', () => { new ExtendedNote( aliceRefundNote, t.aliceAddress, - privateToken.address, - PrivateTokenContract.storage.balances.slot, - PrivateTokenContract.notes.TokenNote.id, + tokenWithRefunds.address, + TokenWithRefundsContract.storage.balances.slot, + TokenWithRefundsContract.notes.TokenNote.id, tx.txHash, ), ); @@ -117,9 +118,9 @@ describe('e2e_fees/private_refunds', () => { new ExtendedNote( bobFeeNote, t.bobAddress, - privateToken.address, - PrivateTokenContract.storage.balances.slot, - PrivateTokenContract.notes.TokenNote.id, + tokenWithRefunds.address, + TokenWithRefundsContract.storage.balances.slot, + TokenWithRefundsContract.notes.TokenNote.id, tx.txHash, ), ); @@ -128,7 +129,7 @@ describe('e2e_fees/private_refunds', () => { await expectMapping(t.getGasBalanceFn, [privateFPC.address], [initialFPCGasBalance - tx.transactionFee!]); // ... and that the transaction fee was correctly transferred from Alice to Bob. await expectMapping( - t.getPrivateTokenBalanceFn, + t.getTokenWithRefundsBalanceFn, [aliceAddress, t.bobAddress], [initialAliceBalance - tx.transactionFee!, initialBobBalance + tx.transactionFee!], ); From b2224b48190d33af5e78efa3a470503331b0371f Mon Sep 17 00:00:00 2001 From: Ilyas Ridhuan Date: Wed, 31 Jul 2024 16:34:15 +0100 Subject: [PATCH 22/35] feat: ts pedersen commit with offset (#7699) --- .../crypto/pedersen_commitment/c_bind.cpp | 10 ++++-- .../crypto/pedersen_commitment/c_bind.hpp | 6 ++-- barretenberg/exports.json | 23 +++---------- barretenberg/scripts/bindgen.sh | 5 +-- .../ts/src/barretenberg/pedersen.test.ts | 4 +-- barretenberg/ts/src/barretenberg_api/index.ts | 32 +++---------------- .../contracts/avm_test_contract/src/main.nr | 2 +- .../src/crypto/pedersen/pedersen.wasm.ts | 7 ++-- .../simulator/src/avm/avm_simulator.test.ts | 2 +- .../src/avm/opcodes/commitment.test.ts | 27 ++++++++++++++++ .../simulator/src/avm/opcodes/commitment.ts | 6 ++-- 11 files changed, 61 insertions(+), 63 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/crypto/pedersen_commitment/c_bind.cpp b/barretenberg/cpp/src/barretenberg/crypto/pedersen_commitment/c_bind.cpp index c6b16e96b51..15c2972dadf 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/pedersen_commitment/c_bind.cpp +++ b/barretenberg/cpp/src/barretenberg/crypto/pedersen_commitment/c_bind.cpp @@ -5,11 +5,15 @@ using namespace bb; -WASM_EXPORT void pedersen_commit(fr::vec_in_buf inputs_buffer, grumpkin::g1::affine_element::out_buf output) +WASM_EXPORT void pedersen_commit(fr::vec_in_buf inputs_buffer, + uint32_t const* ctx_index, + grumpkin::g1::affine_element::out_buf output) { std::vector to_commit; read(inputs_buffer, to_commit); - grumpkin::g1::affine_element pedersen_commitment = crypto::pedersen_commitment::commit_native(to_commit); + crypto::GeneratorContext ctx; + ctx.offset = static_cast(ntohl(*ctx_index)); + grumpkin::g1::affine_element pedersen_commitment = crypto::pedersen_commitment::commit_native(to_commit, ctx); write(output, pedersen_commitment); -} \ No newline at end of file +} diff --git a/barretenberg/cpp/src/barretenberg/crypto/pedersen_commitment/c_bind.hpp b/barretenberg/cpp/src/barretenberg/crypto/pedersen_commitment/c_bind.hpp index a4a37b9eac5..8690459abc8 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/pedersen_commitment/c_bind.hpp +++ b/barretenberg/cpp/src/barretenberg/crypto/pedersen_commitment/c_bind.hpp @@ -8,5 +8,7 @@ extern "C" { using namespace bb; using affine_element = grumpkin::g1::affine_element; -WASM_EXPORT void pedersen_commit(fr::vec_in_buf inputs_buffer, affine_element::out_buf output); -} \ No newline at end of file +WASM_EXPORT void pedersen_commit(fr::vec_in_buf inputs_buffer, + uint32_t const* ctx_index, + affine_element::out_buf output); +} diff --git a/barretenberg/exports.json b/barretenberg/exports.json index b1ecdee8d83..d6819afe1e5 100644 --- a/barretenberg/exports.json +++ b/barretenberg/exports.json @@ -5,6 +5,10 @@ { "name": "inputs_buffer", "type": "fr::vec_in_buf" + }, + { + "name": "ctx_index", + "type": "const uint32_t *" } ], "outArgs": [ @@ -549,25 +553,6 @@ "outArgs": [], "isAsync": false }, - { - "functionName": "acir_create_circuit", - "inArgs": [ - { - "name": "acir_composer_ptr", - "type": "in_ptr" - }, - { - "name": "constraint_system_buf", - "type": "const uint8_t *" - }, - { - "name": "size_hint", - "type": "const uint32_t *" - } - ], - "outArgs": [], - "isAsync": false - }, { "functionName": "acir_init_proving_key", "inArgs": [ diff --git a/barretenberg/scripts/bindgen.sh b/barretenberg/scripts/bindgen.sh index 29ee5eb0778..a0053b5d8ef 100755 --- a/barretenberg/scripts/bindgen.sh +++ b/barretenberg/scripts/bindgen.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +# Run from aztec-packages/barretenberg. set -eu if ! dpkg -l python3-clang-18 &> /dev/null; then @@ -6,11 +7,11 @@ if ! dpkg -l python3-clang-18 &> /dev/null; then exit 1 fi -#find ./cpp/src -type f -name "c_bind*.hpp" | ./scripts/decls_json.py > exports.json +#find ./cpp/src -type f -name "c_bind*.hpp" > ./scripts/c_bind_files.txt cat ./scripts/c_bind_files.txt | ./scripts/decls_json.py > exports.json ( cd ./ts && \ yarn install && \ yarn node --loader ts-node/esm ./src/bindgen/index.ts ../exports.json > ./src/barretenberg_api/index.ts && \ yarn prettier -w ./src/barretenberg_api/index.ts -) \ No newline at end of file +) diff --git a/barretenberg/ts/src/barretenberg/pedersen.test.ts b/barretenberg/ts/src/barretenberg/pedersen.test.ts index 42ba13f9c8b..ef532411512 100644 --- a/barretenberg/ts/src/barretenberg/pedersen.test.ts +++ b/barretenberg/ts/src/barretenberg/pedersen.test.ts @@ -46,7 +46,7 @@ describe('pedersen sync', () => { }); it('pedersenCommit', () => { - const result = api.pedersenCommit([new Fr(4n), new Fr(8n), new Fr(12n)]); + const result = api.pedersenCommit([new Fr(4n), new Fr(8n), new Fr(12n)], 0); expect(result).toMatchSnapshot(); }); @@ -55,7 +55,7 @@ describe('pedersen sync', () => { const fields = Array.from({ length: loops * 2 }).map(() => Fr.random()); const t = new Timer(); for (let i = 0; i < loops; ++i) { - api.pedersenCommit([fields[i * 2], fields[i * 2 + 1]]); + api.pedersenCommit([fields[i * 2], fields[i * 2 + 1]], 0); } console.log(t.us() / loops); }); diff --git a/barretenberg/ts/src/barretenberg_api/index.ts b/barretenberg/ts/src/barretenberg_api/index.ts index f08e4f32a52..b55c29b5f9c 100644 --- a/barretenberg/ts/src/barretenberg_api/index.ts +++ b/barretenberg/ts/src/barretenberg_api/index.ts @@ -15,8 +15,8 @@ import { Fr, Fq, Point, Buffer32, Buffer128, Ptr } from '../types/index.js'; export class BarretenbergApi { constructor(protected wasm: BarretenbergWasmWorker) {} - async pedersenCommit(inputsBuffer: Fr[]): Promise { - const inArgs = [inputsBuffer].map(serializeBufferable); + async pedersenCommit(inputsBuffer: Fr[], ctxIndex: number): Promise { + const inArgs = [inputsBuffer, ctxIndex].map(serializeBufferable); const outTypes: OutputType[] = [Point]; const result = await this.wasm.callWasmExport( 'pedersen_commit', @@ -367,18 +367,6 @@ export class BarretenbergApi { return; } - async acirCreateCircuit(acirComposerPtr: Ptr, constraintSystemBuf: Uint8Array, sizeHint: number): Promise { - const inArgs = [acirComposerPtr, constraintSystemBuf, sizeHint].map(serializeBufferable); - const outTypes: OutputType[] = []; - const result = await this.wasm.callWasmExport( - 'acir_create_circuit', - inArgs, - outTypes.map(t => t.SIZE_IN_BYTES), - ); - const out = result.map((r, i) => outTypes[i].fromBuffer(r)); - return; - } - async acirInitProvingKey(acirComposerPtr: Ptr, constraintSystemBuf: Uint8Array): Promise { const inArgs = [acirComposerPtr, constraintSystemBuf].map(serializeBufferable); const outTypes: OutputType[] = []; @@ -606,8 +594,8 @@ export class BarretenbergApi { export class BarretenbergApiSync { constructor(protected wasm: BarretenbergWasm) {} - pedersenCommit(inputsBuffer: Fr[]): Point { - const inArgs = [inputsBuffer].map(serializeBufferable); + pedersenCommit(inputsBuffer: Fr[], ctxIndex: number): Point { + const inArgs = [inputsBuffer, ctxIndex].map(serializeBufferable); const outTypes: OutputType[] = [Point]; const result = this.wasm.callWasmExport( 'pedersen_commit', @@ -955,18 +943,6 @@ export class BarretenbergApiSync { return; } - acirCreateCircuit(acirComposerPtr: Ptr, constraintSystemBuf: Uint8Array, sizeHint: number): void { - const inArgs = [acirComposerPtr, constraintSystemBuf, sizeHint].map(serializeBufferable); - const outTypes: OutputType[] = []; - const result = this.wasm.callWasmExport( - 'acir_create_circuit', - inArgs, - outTypes.map(t => t.SIZE_IN_BYTES), - ); - const out = result.map((r, i) => outTypes[i].fromBuffer(r)); - return; - } - acirInitProvingKey(acirComposerPtr: Ptr, constraintSystemBuf: Uint8Array): void { const inArgs = [acirComposerPtr, constraintSystemBuf].map(serializeBufferable); const outTypes: OutputType[] = []; 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 4c6838558a1..55542886694 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 @@ -155,7 +155,7 @@ contract AvmTest { #[aztec(public)] fn pedersen_commit(x: Field, y: Field) -> EmbeddedCurvePoint { - let commitment = dep::std::hash::pedersen_commitment([x, y]); + let commitment = dep::std::hash::pedersen_commitment_with_separator([x, y], 20); commitment } diff --git a/yarn-project/foundation/src/crypto/pedersen/pedersen.wasm.ts b/yarn-project/foundation/src/crypto/pedersen/pedersen.wasm.ts index bb07994bb95..fcbceafbfb6 100644 --- a/yarn-project/foundation/src/crypto/pedersen/pedersen.wasm.ts +++ b/yarn-project/foundation/src/crypto/pedersen/pedersen.wasm.ts @@ -7,12 +7,15 @@ import { type Fieldable, serializeToFields } from '../../serialize/serialize.js' * Create a pedersen commitment (point) from an array of input fields. * Left pads any inputs less than 32 bytes. */ -export function pedersenCommit(input: Buffer[]) { +export function pedersenCommit(input: Buffer[], offset = 0) { if (!input.every(i => i.length <= 32)) { throw new Error('All Pedersen Commit input buffers must be <= 32 bytes.'); } input = input.map(i => (i.length < 32 ? Buffer.concat([Buffer.alloc(32 - i.length, 0), i]) : i)); - const point = BarretenbergSync.getSingleton().pedersenCommit(input.map(i => new FrBarretenberg(i))); + const point = BarretenbergSync.getSingleton().pedersenCommit( + input.map(i => new FrBarretenberg(i)), + offset, + ); // toBuffer returns Uint8Arrays (browser/worker-boundary friendly). // TODO: rename toTypedArray()? return [Buffer.from(point.x.toBuffer()), Buffer.from(point.y.toBuffer())]; diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 54b42fa3f80..0cf7a3c6e12 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -149,7 +149,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { expect(results.reverted).toBe(false); // This doesnt include infinites - const expectedResult = pedersenCommit([Buffer.from([100]), Buffer.from([1])]).map(f => new Fr(f)); + const expectedResult = pedersenCommit([Buffer.from([100]), Buffer.from([1])], 20).map(f => new Fr(f)); // TODO: Come back to the handling of infinities when we confirm how they're handled in bb const isInf = expectedResult[0] === new Fr(0) && expectedResult[1] === new Fr(0); expectedResult.push(new Fr(isInf)); diff --git a/yarn-project/simulator/src/avm/opcodes/commitment.test.ts b/yarn-project/simulator/src/avm/opcodes/commitment.test.ts index c5b7c509334..810d48a32dc 100644 --- a/yarn-project/simulator/src/avm/opcodes/commitment.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/commitment.test.ts @@ -58,6 +58,33 @@ describe('Commitment Opcode', () => { expect(0).toEqual(context.machineState.memory.get(outputOffset + 2).toNumber()); }); + it('Should commit correctly with a different gen - direct', async () => { + const args = randomMemoryFields(10); + const inputOffset = 0; + const inputSizeOffset = 20; + const outputOffset = 50; + const indirect = 0; + const generatorIndex = 40; + const generatorIndexOffset = 100; + + context.machineState.memory.setSlice(inputOffset, args); + context.machineState.memory.set(inputSizeOffset, new Uint32(args.length)); + context.machineState.memory.set(generatorIndexOffset, new Uint32(generatorIndex)); + + const expectedCommitment = pedersenCommit( + args.map(f => f.toBuffer()), + generatorIndex, + ).map(f => new Field(f)); + await new PedersenCommitment(indirect, inputOffset, outputOffset, inputSizeOffset, generatorIndexOffset).execute( + context, + ); + + const result = context.machineState.memory.getSlice(outputOffset, 2); + expect(result).toEqual(expectedCommitment); + // Check Inf + expect(0).toEqual(context.machineState.memory.get(outputOffset + 2).toNumber()); + }); + it('Should commit correctly - indirect', async () => { const args = randomMemoryFields(10); const indirect = new Addressing([ diff --git a/yarn-project/simulator/src/avm/opcodes/commitment.ts b/yarn-project/simulator/src/avm/opcodes/commitment.ts index ad99064a6d9..6c065781ded 100644 --- a/yarn-project/simulator/src/avm/opcodes/commitment.ts +++ b/yarn-project/simulator/src/avm/opcodes/commitment.ts @@ -43,15 +43,15 @@ export class PedersenCommitment extends Instruction { const inputs = memory.getSlice(inputOffset, inputSize); memory.checkTagsRange(TypeTag.FIELD, inputOffset, inputSize); - // Generator index not used for now since we dont utilise it in the pedersenCommit function + const generatorIndex = memory.get(genIndexOffset).toNumber(); memory.checkTag(TypeTag.UINT32, genIndexOffset); - const memoryOperations = { reads: inputSize + 1, writes: 3, indirect: this.indirect }; + const memoryOperations = { reads: inputSize + 2, writes: 3, indirect: this.indirect }; context.machineState.consumeGas(this.gasCost(memoryOperations)); const inputBuffer: Buffer[] = inputs.map(input => input.toBuffer()); // TODO: Add the generate index to the pedersenCommit function - const commitment = pedersenCommit(inputBuffer).map(f => new Field(f)); + const commitment = pedersenCommit(inputBuffer, generatorIndex).map(f => new Field(f)); // The function doesnt include a flag if the output point is infinity, come back to this // for now we just check if theyre zero - until we know how bb encodes them const isInfinity = commitment[0].equals(new Field(0)) && commitment[1].equals(new Field(0)); From 1dd4523bce2e005bd53c1d42d5c334f8d4322e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Wed, 31 Jul 2024 20:28:32 +0200 Subject: [PATCH 23/35] refactor: `TokenWithRefunds` optimizations (#7628) Fixes #7606 --- .../src/types/token_note.nr | 63 ++++++------------- 1 file changed, 19 insertions(+), 44 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr index 951caecdce9..c5251008c0f 100644 --- a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr @@ -1,12 +1,11 @@ use dep::aztec::{ generators::{Ga1 as G_amt, Ga2 as G_npk, Ga3 as G_rnd}, - prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, + prelude::{NoteHeader, NoteInterface, PrivateContext}, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, point::Point, scalar::Scalar, hash::poseidon2_hash}, note::utils::compute_note_hash_for_consumption, oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, note::note_getter_options::PropertySelector }; -use dep::std::field::bn254::decompose; -use dep::std::embedded_curve_ops::multi_scalar_mul; +use dep::std::{embedded_curve_ops::multi_scalar_mul, hash::from_field_unsafe}; trait OwnedNote { fn new(amount: U128, owner_npk_m_hash: Field) -> Self; @@ -72,8 +71,9 @@ impl NoteInterface for TokenNote { fn compute_note_hiding_point(self) -> Point { - let (npk_lo, npk_hi) = decompose(self.npk_m_hash); - let (random_lo, random_hi) = decompose(self.randomness); + // We use the unsafe version because the multi_scalar_mul will constrain the scalars. + let npk_m_hash_scalar = from_field_unsafe(self.npk_m_hash); + let randomness_scalar = from_field_unsafe(self.randomness); // We compute the note hiding point as `G_amt * amount + G_npk * npk_m_hash + G_rnd * randomness` instead // of using pedersen or poseidon2 because it allows us to privately add and subtract from amount in public // by leveraging homomorphism. @@ -83,14 +83,8 @@ impl NoteInterface for TokenNote { lo: self.amount.to_integer(), hi: 0 }, - Scalar { - lo: npk_lo, - hi: npk_hi - }, - Scalar { - lo: random_lo, - hi: random_hi, - }] + npk_m_hash_scalar, + randomness_scalar] ) } } @@ -208,45 +202,28 @@ impl PrivatelyRefundable for TokenNote { fn generate_refund_points(fee_payer_npk_m_hash: Field, user_npk_m_hash: Field, funded_amount: Field, user_randomness: Field, fee_payer_randomness: Field) -> (Point, Point) { // 1. To be able to multiply generators with randomness and npk_m_hash using barretneberg's (BB) blackbox // function we first need to convert the fields to high and low limbs. - // TODO(#7606): replace decompose with from_field_unsafe - let (fee_payer_randomness_lo, fee_payer_randomness_hi) = decompose(fee_payer_randomness); - let (fee_payer_npk_m_hash_lo, fee_payer_npk_m_hash_hi) = decompose(fee_payer_npk_m_hash); + // We use the unsafe version because the multi_scalar_mul will constrain the scalars. + let fee_payer_randomness_scalar = from_field_unsafe(fee_payer_randomness); + let fee_payer_npk_m_hash_scalar = from_field_unsafe(fee_payer_npk_m_hash); // 2. Now that we have correct representationsn of fee payer and randomness we can compute // `G_npk * fee_payer_npk + G_rnd * randomness`. let incomplete_fee_payer_point = multi_scalar_mul( [G_npk, G_rnd], - [Scalar { - lo: fee_payer_npk_m_hash_lo, - hi: fee_payer_npk_m_hash_hi - }, - Scalar { - lo: fee_payer_randomness_lo, - hi: fee_payer_randomness_hi - }] + [fee_payer_npk_m_hash_scalar, fee_payer_randomness_scalar] ); // 3. We do the necessary conversion for values relevant for the sponsored user point. - let (user_randomness_lo, user_randomness_hi) = decompose(user_randomness); + // We use the unsafe version because the multi_scalar_mul will constrain the scalars. + let funded_amount_scalar = from_field_unsafe(funded_amount); // TODO(#7324), TODO(#7323): using npk_m_hash here is vulnerable in 2 ways described in the linked issues. - let (user_npk_lo, user_npk_hi) = decompose(user_npk_m_hash); - let (funded_amount_lo, funded_amount_hi) = decompose(funded_amount); + let user_npk_m_hash_scalar = from_field_unsafe(user_npk_m_hash); + let user_randomness_scalar = from_field_unsafe(user_randomness); // 4. We compute `G_amt * funded_amount + G_npk * user_npk_m_hash + G_rnd * randomness`. let incomplete_user_point = multi_scalar_mul( [G_amt, G_npk, G_rnd], - [Scalar { - lo: funded_amount_lo, - hi: funded_amount_hi - }, - Scalar { - lo: user_npk_lo, - hi: user_npk_hi - }, - Scalar { - lo: user_randomness_lo, - hi: user_randomness_hi - }] + [funded_amount_scalar, user_npk_m_hash_scalar, user_randomness_scalar] ); // 5. At last we return the points. @@ -255,15 +232,13 @@ impl PrivatelyRefundable for TokenNote { fn complete_refund(incomplete_fee_payer_point: Point, incomplete_user_point: Point, transaction_fee: Field) -> (Point, Point) { // 1. We convert the transaction fee to high and low limbs to be able to use BB API. - let (transaction_fee_lo, transaction_fee_hi) = decompose(transaction_fee); + // We use the unsafe version because the multi_scalar_mul will constrain the scalars. + let transaction_fee_scalar = from_field_unsafe(transaction_fee); // 2. We compute the fee point as `G_amt * transaction_fee` let fee_point = multi_scalar_mul( [G_amt], - [Scalar { - lo: transaction_fee_lo, - hi: transaction_fee_hi, - }] + [transaction_fee_scalar] ); // 3. Now we leverage homomorphism to privately add the fee to fee payer point and subtract it from From 1b7d27e310c70a211f30816b42a879118378a049 Mon Sep 17 00:00:00 2001 From: Facundo Date: Wed, 31 Jul 2024 19:58:30 +0100 Subject: [PATCH 24/35] chore(avm): update stats (#7701) I realized much of the "proving time" (9 seconds in a 2^19 trace) is actually spent when creating the prover. In particular, when allocating memory for the prover polynomials, so I added some stats to track that. ``` ------- STATS ------- prove/all_ms: 6879 prove/check_circuit_ms: 2681 prove/create_composer_ms: 0 prove/create_prover_ms: 872 prove/create_verifier_ms: 0 prove/execute_log_derivative_inverse_commitments_round_ms: 124 prove/execute_log_derivative_inverse_round_ms: 179 prove/execute_pcs_rounds_ms: 268 prove/execute_relation_check_rounds_ms: 1619 prove/execute_wire_commitments_round_ms: 86 prove/gen_trace_ms: 975 ``` ----- As a side note for posterity, I researched on using `mmap` (ANON) for allocating zero-initialized memory and changing the following in `polynomial.cpp` ``` template std::shared_ptr _allocate_aligned_memory(const size_t n_elements) { // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) // return std::static_pointer_cast(get_mem_slab(sizeof(Fr) * n_elements)); auto size = sizeof(Fr) * n_elements; auto* ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); auto shared = std::shared_ptr(ptr, [size](void* p) { munmap(p, size); }); return std::static_pointer_cast(shared); } ``` plus removing the `memset` in the constructor, made 8 of those 9 seconds go away. I think even better performance (and memory usage) can be achieved for sparse vectors/polynomials if we never set zeroes. At some point I'll talk w/Charlie and Adam about this (which only applies to native and not wasm). PS: `mmap` anon makes the kernel return a page-aligned zero-initialized page, but it will re-use the same one and be copy-on-write. This saves both time and memory until we write, and possibly a lot of memory if we have sparse matrices with many pages fulls of zeroes. --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 7 +++--- .../vm/avm_trace/avm_execution.cpp | 7 +++--- .../src/barretenberg/vm/avm_trace/stats.cpp | 24 ++++++------------- .../src/barretenberg/vm/avm_trace/stats.hpp | 24 ++++++++++++++++--- .../barretenberg/vm/generated/avm_prover.cpp | 12 +++++----- .../bb-pil-backend/templates/prover.cpp.hbs | 12 +++++----- 6 files changed, 48 insertions(+), 38 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index a696c6796d3..9fabba8c996 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -968,7 +968,7 @@ void avm_prove(const std::filesystem::path& bytecode_path, // Prove execution and return vk auto const [verification_key, proof] = - avm_trace::Execution::prove(bytecode, calldata, public_inputs_vec, avm_hints); + AVM_TRACK_TIME_V("prove/all", avm_trace::Execution::prove(bytecode, calldata, public_inputs_vec, avm_hints)); // TODO(ilyas): <#4887>: Currently we only need these two parts of the vk, look into pcs_verification key reqs std::vector vk_vector = { verification_key.circuit_size, verification_key.num_public_inputs }; @@ -989,7 +989,8 @@ void avm_prove(const std::filesystem::path& bytecode_path, #ifdef AVM_TRACK_STATS info("------- STATS -------"); const auto& stats = avm_trace::Stats::get(); - info(stats.to_string()); + const int levels = std::getenv("AVM_STATS_DEPTH") != nullptr ? std::stoi(std::getenv("AVM_STATS_DEPTH")) : 2; + info(stats.to_string(levels)); #endif } @@ -1013,7 +1014,7 @@ bool avm_verify(const std::filesystem::path& proof_path, const std::filesystem:: auto num_public_inputs = from_buffer(vk_bytes, sizeof(size_t)); auto vk = AvmFlavor::VerificationKey(circuit_size, num_public_inputs); - const bool verified = avm_trace::Execution::verify(vk, proof); + const bool verified = AVM_TRACK_TIME_V("verify/all", avm_trace::Execution::verify(vk, proof)); vinfo("verified: ", verified); return verified; } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp index 5e81e6d38a9..6acb5b58b31 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -16,6 +16,7 @@ #include "barretenberg/vm/generated/avm_circuit_builder.hpp" #include "barretenberg/vm/generated/avm_composer.hpp" #include "barretenberg/vm/generated/avm_flavor.hpp" +#include "barretenberg/vm/generated/avm_verifier.hpp" #include #include @@ -132,9 +133,9 @@ std::tuple Execution::prove(std::vector f) +void Stats::time(const std::string& key, const std::function& f) { auto start = std::chrono::system_clock::now(); f(); auto elapsed = std::chrono::system_clock::now() - start; - increment(key, static_cast(std::chrono::duration_cast(elapsed).count())); + increment(key + "_ms", + static_cast(std::chrono::duration_cast(elapsed).count())); } -std::string Stats::to_string() const +std::string Stats::to_string(int depth) const { std::lock_guard lock(stats_mutex); std::vector result; result.reserve(stats.size()); for (const auto& [key, value] : stats) { - result.push_back(key + ": " + std::to_string(value)); + if (std::count(key.begin(), key.end(), '/') < depth) { + result.push_back(key + ": " + std::to_string(value)); + } } std::sort(result.begin(), result.end()); std::string joined; @@ -49,17 +52,4 @@ std::string Stats::to_string() const return joined; } -std::string Stats::aggregate_to_string(const std::string& key_prefix) const -{ - std::lock_guard lock(stats_mutex); - - uint64_t result = 0; - for (const auto& [key, value] : stats) { - if (key.starts_with(key_prefix)) { - result += value; - } - } - return key_prefix + ": " + std::to_string(result); -} - } // namespace bb::avm_trace \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/stats.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/stats.hpp index b1c6da1e338..be7002b9ba9 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/stats.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/stats.hpp @@ -13,9 +13,13 @@ #endif #ifdef AVM_TRACK_STATS +// For tracking time spent in a block of code. #define AVM_TRACK_TIME(key, body) ::bb::avm_trace::Stats::get().time(key, [&]() { body; }); +// For tracking time spent in a block of code and returning a value. +#define AVM_TRACK_TIME_V(key, body) ::bb::avm_trace::Stats::get().template time_r(key, [&]() { return body; }); #else #define AVM_TRACK_TIME(key, body) body +#define AVM_TRACK_TIME_V(key, body) body #endif namespace bb::avm_trace { @@ -25,9 +29,23 @@ class Stats { static Stats& get(); void reset(); void increment(const std::string& key, uint64_t value); - void time(const std::string& key, std::function f); - std::string to_string() const; - std::string aggregate_to_string(const std::string& key_prefix) const; + void time(const std::string& key, const std::function& f); + + template auto time_r(const std::string& key, F&& f) + { + auto start = std::chrono::system_clock::now(); + auto result = f(); + auto elapsed = std::chrono::system_clock::now() - start; + increment(key + "_ms", + static_cast(std::chrono::duration_cast(elapsed).count())); + return result; + } + + // Returns a string representation of the stats. + // E.g., if depth = 2, it will show the top 2 levels of the stats. + // That is, prove/logderiv_ms will be shown but + // prove/logderiv/relation_ms will not be shown. + std::string to_string(int depth = 2) const; private: Stats() = default; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp index d12ba25cee8..9cc9cc81876 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -79,7 +79,7 @@ void AvmProver::execute_log_derivative_inverse_round() bb::constexpr_for<0, std::tuple_size_v, 1>([&]() { using Relation = std::tuple_element_t; tasks.push_back([&]() { - AVM_TRACK_TIME(Relation::NAME + std::string("_ms"), + AVM_TRACK_TIME(std::string("prove/execute_log_derivative_inverse_round/") + Relation::NAME, (compute_logderivative_inverse( prover_polynomials, relation_parameters, key->circuit_size))); }); @@ -150,22 +150,22 @@ HonkProof AvmProver::construct_proof() execute_preamble_round(); // Compute wire commitments - AVM_TRACK_TIME("prove/execute_wire_commitments_round_ms", execute_wire_commitments_round()); + AVM_TRACK_TIME("prove/execute_wire_commitments_round", execute_wire_commitments_round()); // Compute sorted list accumulator - AVM_TRACK_TIME("prove/execute_log_derivative_inverse_round_ms", execute_log_derivative_inverse_round()); + AVM_TRACK_TIME("prove/execute_log_derivative_inverse_round", execute_log_derivative_inverse_round()); // Compute commitments to logderivative inverse polynomials - AVM_TRACK_TIME("prove/execute_log_derivative_inverse_commitments_round_ms", + AVM_TRACK_TIME("prove/execute_log_derivative_inverse_commitments_round", execute_log_derivative_inverse_commitments_round()); // Fiat-Shamir: alpha // Run sumcheck subprotocol. - AVM_TRACK_TIME("prove/execute_relation_check_rounds_ms", execute_relation_check_rounds()); + AVM_TRACK_TIME("prove/execute_relation_check_rounds", execute_relation_check_rounds()); // Fiat-Shamir: rho, y, x, z // Execute Zeromorph multilinear PCS - AVM_TRACK_TIME("prove/execute_pcs_rounds_ms", execute_pcs_rounds()); + AVM_TRACK_TIME("prove/execute_pcs_rounds", execute_pcs_rounds()); return export_proof(); } diff --git a/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs index f35f28cf763..42eb158c95a 100644 --- a/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs @@ -80,7 +80,7 @@ void AvmProver::execute_log_derivative_inverse_round() bb::constexpr_for<0, std::tuple_size_v, 1>([&]() { using Relation = std::tuple_element_t; tasks.push_back([&]() { - AVM_TRACK_TIME(Relation::NAME + std::string("_ms"), + AVM_TRACK_TIME(std::string("prove/execute_log_derivative_inverse_round/") + Relation::NAME, (compute_logderivative_inverse( prover_polynomials, relation_parameters, key->circuit_size))); }); @@ -151,21 +151,21 @@ HonkProof {{name}}Prover::construct_proof() execute_preamble_round(); // Compute wire commitments - AVM_TRACK_TIME("prove/execute_wire_commitments_round_ms", execute_wire_commitments_round()); + AVM_TRACK_TIME("prove/execute_wire_commitments_round", execute_wire_commitments_round()); // Compute sorted list accumulator - AVM_TRACK_TIME("prove/execute_log_derivative_inverse_round_ms", execute_log_derivative_inverse_round()); + AVM_TRACK_TIME("prove/execute_log_derivative_inverse_round", execute_log_derivative_inverse_round()); // Compute commitments to logderivative inverse polynomials - AVM_TRACK_TIME("prove/execute_log_derivative_inverse_commitments_round_ms", execute_log_derivative_inverse_commitments_round()); + AVM_TRACK_TIME("prove/execute_log_derivative_inverse_commitments_round", execute_log_derivative_inverse_commitments_round()); // Fiat-Shamir: alpha // Run sumcheck subprotocol. - AVM_TRACK_TIME("prove/execute_relation_check_rounds_ms", execute_relation_check_rounds()); + AVM_TRACK_TIME("prove/execute_relation_check_rounds", execute_relation_check_rounds()); // Fiat-Shamir: rho, y, x, z // Execute Zeromorph multilinear PCS - AVM_TRACK_TIME("prove/execute_pcs_rounds_ms", execute_pcs_rounds()); + AVM_TRACK_TIME("prove/execute_pcs_rounds", execute_pcs_rounds()); return export_proof(); } From f26bb32abcdcea4450f4867d2d88efbbcd468c01 Mon Sep 17 00:00:00 2001 From: Facundo Date: Wed, 31 Jul 2024 21:09:41 +0100 Subject: [PATCH 25/35] chore(avm): codegen improvements (#7703) * Moved more things from hpp to cpps * Hardcoded AvmProvingKey_ * In verifier.cpp we now use a for loop to get the logderiv commitments instead of an unrolled loop --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 2 +- .../relations/generated/avm/alu.hpp | 1 + .../relations/generated/avm/binary.hpp | 1 + .../relations/generated/avm/conversion.hpp | 1 + .../relations/generated/avm/gas.hpp | 1 + .../generated/avm/incl_main_tag_err.hpp | 1 + .../generated/avm/incl_mem_tag_err.hpp | 1 + .../relations/generated/avm/keccakf1600.hpp | 1 + .../relations/generated/avm/kernel.hpp | 1 + .../generated/avm/kernel_output_lookup.hpp | 1 + .../generated/avm/lookup_byte_lengths.hpp | 1 + .../generated/avm/lookup_byte_operations.hpp | 1 + .../generated/avm/lookup_cd_value.hpp | 1 + .../generated/avm/lookup_div_u16_0.hpp | 1 + .../generated/avm/lookup_div_u16_1.hpp | 1 + .../generated/avm/lookup_div_u16_2.hpp | 1 + .../generated/avm/lookup_div_u16_3.hpp | 1 + .../generated/avm/lookup_div_u16_4.hpp | 1 + .../generated/avm/lookup_div_u16_5.hpp | 1 + .../generated/avm/lookup_div_u16_6.hpp | 1 + .../generated/avm/lookup_div_u16_7.hpp | 1 + .../generated/avm/lookup_into_kernel.hpp | 1 + .../generated/avm/lookup_mem_rng_chk_hi.hpp | 1 + .../generated/avm/lookup_mem_rng_chk_lo.hpp | 1 + .../generated/avm/lookup_mem_rng_chk_mid.hpp | 1 + .../generated/avm/lookup_opcode_gas.hpp | 1 + .../generated/avm/lookup_pow_2_0.hpp | 1 + .../generated/avm/lookup_pow_2_1.hpp | 1 + .../generated/avm/lookup_ret_value.hpp | 1 + .../relations/generated/avm/lookup_u16_0.hpp | 1 + .../relations/generated/avm/lookup_u16_1.hpp | 1 + .../relations/generated/avm/lookup_u16_10.hpp | 1 + .../relations/generated/avm/lookup_u16_11.hpp | 1 + .../relations/generated/avm/lookup_u16_12.hpp | 1 + .../relations/generated/avm/lookup_u16_13.hpp | 1 + .../relations/generated/avm/lookup_u16_14.hpp | 1 + .../relations/generated/avm/lookup_u16_2.hpp | 1 + .../relations/generated/avm/lookup_u16_3.hpp | 1 + .../relations/generated/avm/lookup_u16_4.hpp | 1 + .../relations/generated/avm/lookup_u16_5.hpp | 1 + .../relations/generated/avm/lookup_u16_6.hpp | 1 + .../relations/generated/avm/lookup_u16_7.hpp | 1 + .../relations/generated/avm/lookup_u16_8.hpp | 1 + .../relations/generated/avm/lookup_u16_9.hpp | 1 + .../relations/generated/avm/lookup_u8_0.hpp | 1 + .../relations/generated/avm/lookup_u8_1.hpp | 1 + .../relations/generated/avm/main.hpp | 1 + .../relations/generated/avm/mem.hpp | 1 + .../relations/generated/avm/mem_slice.hpp | 1 + .../relations/generated/avm/pedersen.hpp | 1 + .../relations/generated/avm/perm_main_alu.hpp | 1 + .../relations/generated/avm/perm_main_bin.hpp | 1 + .../generated/avm/perm_main_conv.hpp | 1 + .../generated/avm/perm_main_mem_a.hpp | 1 + .../generated/avm/perm_main_mem_b.hpp | 1 + .../generated/avm/perm_main_mem_c.hpp | 1 + .../generated/avm/perm_main_mem_d.hpp | 1 + .../avm/perm_main_mem_ind_addr_a.hpp | 1 + .../avm/perm_main_mem_ind_addr_b.hpp | 1 + .../avm/perm_main_mem_ind_addr_c.hpp | 1 + .../avm/perm_main_mem_ind_addr_d.hpp | 1 + .../generated/avm/perm_main_pedersen.hpp | 1 + .../generated/avm/perm_main_pos2_perm.hpp | 1 + .../generated/avm/perm_main_slice.hpp | 1 + .../generated/avm/perm_slice_mem.hpp | 1 + .../relations/generated/avm/poseidon2.hpp | 1 + .../relations/generated/avm/powers.hpp | 1 + .../generated/avm/range_check_da_gas_hi.hpp | 1 + .../generated/avm/range_check_da_gas_lo.hpp | 1 + .../generated/avm/range_check_l2_gas_hi.hpp | 1 + .../generated/avm/range_check_l2_gas_lo.hpp | 1 + .../relations/generated/avm/sha256.hpp | 1 + .../vm/avm_trace/avm_execution.cpp | 2 +- .../barretenberg/vm/avm_trace/avm_trace.cpp | 2 +- .../vm/generated/avm_circuit_builder.cpp | 474 ++++++ .../vm/generated/avm_circuit_builder.hpp | 472 +----- .../vm/generated/avm_composer.cpp | 1 + .../vm/generated/avm_composer.hpp | 1 + .../barretenberg/vm/generated/avm_flavor.cpp | 1471 +++++++++++++++++ .../barretenberg/vm/generated/avm_flavor.hpp | 1468 +--------------- .../vm/generated/avm_flavor_settings.hpp | 1 + .../vm/generated/avm_full_row.cpp | 1 + .../vm/generated/avm_full_row.hpp | 1 + .../barretenberg/vm/generated/avm_prover.cpp | 3 +- .../barretenberg/vm/generated/avm_prover.hpp | 1 + .../vm/generated/avm_verifier.cpp | 97 +- .../vm/generated/avm_verifier.hpp | 1 + .../barretenberg/vm/{avm_trace => }/stats.cpp | 2 +- .../barretenberg/vm/{avm_trace => }/stats.hpp | 0 .../bb-pil-backend/src/circuit_builder.rs | 27 + .../bb-pil-backend/src/flavor_builder.rs | 63 + bb-pilcom/bb-pil-backend/src/vm_builder.rs | 18 +- .../templates/circuit_builder.cpp.hbs | 122 ++ .../templates/circuit_builder.hpp.hbs | 120 +- .../bb-pil-backend/templates/composer.cpp.hbs | 1 + .../bb-pil-backend/templates/composer.hpp.hbs | 1 + .../bb-pil-backend/templates/flavor.cpp.hbs | 112 ++ .../bb-pil-backend/templates/flavor.hpp.hbs | 112 +- .../templates/flavor_settings.hpp.hbs | 1 + .../bb-pil-backend/templates/full_row.cpp.hbs | 1 + .../bb-pil-backend/templates/full_row.hpp.hbs | 1 + .../bb-pil-backend/templates/lookup.hpp.hbs | 1 + .../templates/permutation.hpp.hbs | 1 + .../bb-pil-backend/templates/prover.cpp.hbs | 3 +- .../bb-pil-backend/templates/prover.hpp.hbs | 1 + .../bb-pil-backend/templates/relation.hpp.hbs | 1 + .../bb-pil-backend/templates/verifier.cpp.hbs | 7 +- .../bb-pil-backend/templates/verifier.hpp.hbs | 1 + 108 files changed, 2416 insertions(+), 2249 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.cpp rename barretenberg/cpp/src/barretenberg/vm/{avm_trace => }/stats.cpp (96%) rename barretenberg/cpp/src/barretenberg/vm/{avm_trace => }/stats.hpp (100%) create mode 100644 bb-pilcom/bb-pil-backend/templates/circuit_builder.cpp.hbs create mode 100644 bb-pilcom/bb-pil-backend/templates/flavor.cpp.hbs diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 9fabba8c996..a7a010f0ef2 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -15,7 +15,7 @@ #ifndef DISABLE_AZTEC_VM #include "barretenberg/vm/avm_trace/avm_common.hpp" #include "barretenberg/vm/avm_trace/avm_execution.hpp" -#include "barretenberg/vm/avm_trace/stats.hpp" +#include "barretenberg/vm/stats.hpp" #endif #include "config.hpp" #include "get_bn254_crs.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/alu.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/alu.hpp index f1f8714e80a..464c67f0c8f 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/alu.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/alu.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generated/avm/declare_views.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/binary.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/binary.hpp index dc0f110e875..91e9160af75 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/binary.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/binary.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generated/avm/declare_views.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/conversion.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/conversion.hpp index 759f82b4fbf..3b1c8ebb0ff 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/conversion.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/conversion.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generated/avm/declare_views.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/gas.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/gas.hpp index c5779ccb6e6..98333d9b9b9 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/gas.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/gas.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generated/avm/declare_views.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/incl_main_tag_err.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/incl_main_tag_err.hpp index 4b6eab5c924..cd157ae28c9 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/incl_main_tag_err.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/incl_main_tag_err.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/incl_mem_tag_err.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/incl_mem_tag_err.hpp index 04cfbb2e754..8ea3c0be818 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/incl_mem_tag_err.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/incl_mem_tag_err.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/keccakf1600.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/keccakf1600.hpp index df3f032d111..e065ece9dbf 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/keccakf1600.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/keccakf1600.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generated/avm/declare_views.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel.hpp index 9d4d2f1f9ce..8d4339c50f1 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generated/avm/declare_views.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel_output_lookup.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel_output_lookup.hpp index 797627d4abe..27a4f3b034d 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel_output_lookup.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel_output_lookup.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_byte_lengths.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_byte_lengths.hpp index c9e955f5c5d..48306c678ff 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_byte_lengths.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_byte_lengths.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_byte_operations.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_byte_operations.hpp index d75b148d8f8..990e68f8694 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_byte_operations.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_byte_operations.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_cd_value.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_cd_value.hpp index 928e027579f..d79010b79e8 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_cd_value.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_cd_value.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_0.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_0.hpp index 17d91f7a8fb..6d5eb914bf1 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_0.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_0.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_1.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_1.hpp index aa75b041c2f..10b95f3109a 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_1.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_1.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_2.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_2.hpp index fdbc101c196..980139dca14 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_2.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_2.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_3.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_3.hpp index 811751452c9..78f146e20fc 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_3.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_3.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_4.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_4.hpp index beccfbfe262..286c1c2f375 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_4.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_4.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_5.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_5.hpp index e3d88dbc9cc..ca7d2337de3 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_5.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_5.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_6.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_6.hpp index 71caffd331c..2c90e085116 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_6.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_6.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_7.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_7.hpp index 2658b60ad6b..2cfd36db9ba 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_7.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_div_u16_7.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_into_kernel.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_into_kernel.hpp index 37c92e25584..b4f60e4a2bf 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_into_kernel.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_into_kernel.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_mem_rng_chk_hi.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_mem_rng_chk_hi.hpp index 3b46f851c31..5c8aaa6fc3b 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_mem_rng_chk_hi.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_mem_rng_chk_hi.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_mem_rng_chk_lo.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_mem_rng_chk_lo.hpp index c16c955dbb1..0703aedb9b1 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_mem_rng_chk_lo.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_mem_rng_chk_lo.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_mem_rng_chk_mid.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_mem_rng_chk_mid.hpp index 6401efe9a16..c94810b17a4 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_mem_rng_chk_mid.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_mem_rng_chk_mid.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_opcode_gas.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_opcode_gas.hpp index 86a5593712a..e5710c1fba5 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_opcode_gas.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_opcode_gas.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_0.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_0.hpp index 4130b070028..863fcfeac24 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_0.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_0.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_1.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_1.hpp index 45e2674d889..051051f5ac4 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_1.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_1.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_ret_value.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_ret_value.hpp index e3a5b83ba58..ebdda1877a3 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_ret_value.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_ret_value.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_0.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_0.hpp index 80fb8d8fc1f..df8468fa309 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_0.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_0.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_1.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_1.hpp index d21789a78a3..b32bf947096 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_1.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_1.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_10.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_10.hpp index c5c53ca7001..cbc6159e660 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_10.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_10.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_11.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_11.hpp index 667d62ee80c..c851e3174e7 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_11.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_11.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_12.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_12.hpp index b996d90712e..897d9aa182b 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_12.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_12.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_13.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_13.hpp index 9a2be9b7a42..adcb2988599 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_13.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_13.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_14.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_14.hpp index 41cf86dc012..b9fb986d084 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_14.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_14.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_2.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_2.hpp index 591d5569418..765f529a0f7 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_2.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_2.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_3.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_3.hpp index 2a8aa71231f..9ea811735f7 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_3.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_3.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_4.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_4.hpp index d8a08585227..5dcfff11f66 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_4.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_4.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_5.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_5.hpp index 2a5df1d947f..43cc658542f 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_5.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_5.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_6.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_6.hpp index 0c3d77a4ba4..46d4b80a693 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_6.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_6.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_7.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_7.hpp index 58c4b7aaf95..576cc99c002 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_7.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_7.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_8.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_8.hpp index 009ba72de36..866e349c377 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_8.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_8.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_9.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_9.hpp index c1ce89d9253..0e3716af788 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_9.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u16_9.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u8_0.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u8_0.hpp index 8b73711893c..17d5956c9e2 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u8_0.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u8_0.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u8_1.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u8_1.hpp index 0f0bad11ee1..5c194db8b1a 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u8_1.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_u8_1.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp index 0ad1a01ba60..b208ffbd2b4 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generated/avm/declare_views.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp index 6fa40fcaed1..8f3b67f85d6 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generated/avm/declare_views.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem_slice.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem_slice.hpp index 4f97e128975..9fb9f5bf8a7 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem_slice.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem_slice.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generated/avm/declare_views.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/pedersen.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/pedersen.hpp index 6be8889e978..c1793ee084e 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/pedersen.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/pedersen.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generated/avm/declare_views.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp index 8e4ae3525da..6afb59543ff 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_alu.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_bin.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_bin.hpp index fbfbd4a9915..872e6b6dce4 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_bin.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_bin.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_conv.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_conv.hpp index 3f0ac59654c..9014c3af10c 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_conv.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_conv.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_a.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_a.hpp index fb822164ac3..069e757eb05 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_a.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_a.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_b.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_b.hpp index da7afb490b7..78c234553b4 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_b.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_b.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_c.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_c.hpp index 8b96595d294..c8644cbf456 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_c.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_c.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_d.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_d.hpp index 3d8c9b16ef5..cba0b47f08e 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_d.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_d.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_a.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_a.hpp index de3276a762a..5ed5c2b0068 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_a.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_a.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_b.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_b.hpp index 18a655012eb..8533af76d93 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_b.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_b.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_c.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_c.hpp index 14a43accda3..03efaa45c4b 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_c.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_c.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_d.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_d.hpp index 78e201106c1..8f8a2195066 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_d.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_mem_ind_addr_d.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_pedersen.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_pedersen.hpp index 7753ff50e8b..f91956a8870 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_pedersen.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_pedersen.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_pos2_perm.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_pos2_perm.hpp index 20b1d24dd74..d2788291864 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_pos2_perm.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_pos2_perm.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_slice.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_slice.hpp index e74fa08bf5f..abdd10c9300 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_slice.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_main_slice.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_slice_mem.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_slice_mem.hpp index 7bd0a9ff343..c42c3329075 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_slice_mem.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/perm_slice_mem.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/poseidon2.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/poseidon2.hpp index 6b23fc5c205..a687f1b7e9d 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/poseidon2.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/poseidon2.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generated/avm/declare_views.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/powers.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/powers.hpp index b6a9da83692..655c420a7e1 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/powers.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/powers.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generated/avm/declare_views.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_da_gas_hi.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_da_gas_hi.hpp index 4a13a744389..2a940db495e 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_da_gas_hi.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_da_gas_hi.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_da_gas_lo.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_da_gas_lo.hpp index 400306ca4b7..63c17060e85 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_da_gas_lo.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_da_gas_lo.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_l2_gas_hi.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_l2_gas_hi.hpp index deb10a672a2..7722789c2ed 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_l2_gas_hi.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_l2_gas_hi.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_l2_gas_lo.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_l2_gas_lo.hpp index 2acda771158..a2de806c54b 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_l2_gas_lo.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/range_check_l2_gas_lo.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/sha256.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/sha256.hpp index c7e2013f19b..77f8bee4487 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/sha256.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/sha256.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generated/avm/declare_views.hpp" diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp index 6acb5b58b31..dd62fca665f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -12,11 +12,11 @@ #include "barretenberg/vm/avm_trace/avm_trace.hpp" #include "barretenberg/vm/avm_trace/aztec_constants.hpp" #include "barretenberg/vm/avm_trace/constants.hpp" -#include "barretenberg/vm/avm_trace/stats.hpp" #include "barretenberg/vm/generated/avm_circuit_builder.hpp" #include "barretenberg/vm/generated/avm_composer.hpp" #include "barretenberg/vm/generated/avm_flavor.hpp" #include "barretenberg/vm/generated/avm_verifier.hpp" +#include "barretenberg/vm/stats.hpp" #include #include diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp index 620d264c7c7..8141cd87f6c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -25,7 +25,7 @@ #include "barretenberg/vm/avm_trace/fixed_gas.hpp" #include "barretenberg/vm/avm_trace/fixed_powers.hpp" #include "barretenberg/vm/avm_trace/gadgets/avm_slice_trace.hpp" -#include "barretenberg/vm/avm_trace/stats.hpp" +#include "barretenberg/vm/stats.hpp" namespace bb::avm_trace { diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp new file mode 100644 index 00000000000..649f7b91ed8 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp @@ -0,0 +1,474 @@ +// AUTOGENERATED FILE +#include "barretenberg/vm/generated/avm_circuit_builder.hpp" + +#include + +#include "barretenberg/common/constexpr_utils.hpp" +#include "barretenberg/common/thread.hpp" +#include "barretenberg/common/throw_or_abort.hpp" +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" +#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" +#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" + +namespace bb { + +AvmCircuitBuilder::ProverPolynomials AvmCircuitBuilder::compute_polynomials() const +{ + const auto num_rows = get_circuit_subgroup_size(); + ProverPolynomials polys; + + // Allocate mem for each column + for (auto& poly : polys.get_all()) { + poly = Polynomial(num_rows); + } + + for (size_t i = 0; i < rows.size(); i++) { + polys.main_clk[i] = rows[i].main_clk; + polys.main_sel_first[i] = rows[i].main_sel_first; + polys.kernel_kernel_inputs[i] = rows[i].kernel_kernel_inputs; + polys.kernel_kernel_value_out[i] = rows[i].kernel_kernel_value_out; + polys.kernel_kernel_side_effect_out[i] = rows[i].kernel_kernel_side_effect_out; + polys.kernel_kernel_metadata_out[i] = rows[i].kernel_kernel_metadata_out; + polys.main_calldata[i] = rows[i].main_calldata; + polys.main_returndata[i] = rows[i].main_returndata; + polys.alu_a_hi[i] = rows[i].alu_a_hi; + polys.alu_a_lo[i] = rows[i].alu_a_lo; + polys.alu_b_hi[i] = rows[i].alu_b_hi; + polys.alu_b_lo[i] = rows[i].alu_b_lo; + polys.alu_borrow[i] = rows[i].alu_borrow; + polys.alu_cf[i] = rows[i].alu_cf; + polys.alu_clk[i] = rows[i].alu_clk; + polys.alu_cmp_rng_ctr[i] = rows[i].alu_cmp_rng_ctr; + polys.alu_div_u16_r0[i] = rows[i].alu_div_u16_r0; + polys.alu_div_u16_r1[i] = rows[i].alu_div_u16_r1; + polys.alu_div_u16_r2[i] = rows[i].alu_div_u16_r2; + polys.alu_div_u16_r3[i] = rows[i].alu_div_u16_r3; + polys.alu_div_u16_r4[i] = rows[i].alu_div_u16_r4; + polys.alu_div_u16_r5[i] = rows[i].alu_div_u16_r5; + polys.alu_div_u16_r6[i] = rows[i].alu_div_u16_r6; + polys.alu_div_u16_r7[i] = rows[i].alu_div_u16_r7; + polys.alu_divisor_hi[i] = rows[i].alu_divisor_hi; + polys.alu_divisor_lo[i] = rows[i].alu_divisor_lo; + polys.alu_ff_tag[i] = rows[i].alu_ff_tag; + polys.alu_ia[i] = rows[i].alu_ia; + polys.alu_ib[i] = rows[i].alu_ib; + polys.alu_ic[i] = rows[i].alu_ic; + polys.alu_in_tag[i] = rows[i].alu_in_tag; + polys.alu_op_add[i] = rows[i].alu_op_add; + polys.alu_op_cast[i] = rows[i].alu_op_cast; + polys.alu_op_cast_prev[i] = rows[i].alu_op_cast_prev; + polys.alu_op_div[i] = rows[i].alu_op_div; + polys.alu_op_div_a_lt_b[i] = rows[i].alu_op_div_a_lt_b; + polys.alu_op_div_std[i] = rows[i].alu_op_div_std; + polys.alu_op_eq[i] = rows[i].alu_op_eq; + polys.alu_op_eq_diff_inv[i] = rows[i].alu_op_eq_diff_inv; + polys.alu_op_lt[i] = rows[i].alu_op_lt; + polys.alu_op_lte[i] = rows[i].alu_op_lte; + polys.alu_op_mul[i] = rows[i].alu_op_mul; + polys.alu_op_not[i] = rows[i].alu_op_not; + polys.alu_op_shl[i] = rows[i].alu_op_shl; + polys.alu_op_shr[i] = rows[i].alu_op_shr; + polys.alu_op_sub[i] = rows[i].alu_op_sub; + polys.alu_p_a_borrow[i] = rows[i].alu_p_a_borrow; + polys.alu_p_b_borrow[i] = rows[i].alu_p_b_borrow; + polys.alu_p_sub_a_hi[i] = rows[i].alu_p_sub_a_hi; + polys.alu_p_sub_a_lo[i] = rows[i].alu_p_sub_a_lo; + polys.alu_p_sub_b_hi[i] = rows[i].alu_p_sub_b_hi; + polys.alu_p_sub_b_lo[i] = rows[i].alu_p_sub_b_lo; + polys.alu_partial_prod_hi[i] = rows[i].alu_partial_prod_hi; + polys.alu_partial_prod_lo[i] = rows[i].alu_partial_prod_lo; + polys.alu_quotient_hi[i] = rows[i].alu_quotient_hi; + polys.alu_quotient_lo[i] = rows[i].alu_quotient_lo; + polys.alu_remainder[i] = rows[i].alu_remainder; + polys.alu_res_hi[i] = rows[i].alu_res_hi; + polys.alu_res_lo[i] = rows[i].alu_res_lo; + polys.alu_sel_alu[i] = rows[i].alu_sel_alu; + polys.alu_sel_cmp[i] = rows[i].alu_sel_cmp; + polys.alu_sel_div_rng_chk[i] = rows[i].alu_sel_div_rng_chk; + polys.alu_sel_rng_chk[i] = rows[i].alu_sel_rng_chk; + polys.alu_sel_rng_chk_lookup[i] = rows[i].alu_sel_rng_chk_lookup; + polys.alu_sel_shift_which[i] = rows[i].alu_sel_shift_which; + polys.alu_shift_lt_bit_len[i] = rows[i].alu_shift_lt_bit_len; + polys.alu_t_sub_s_bits[i] = rows[i].alu_t_sub_s_bits; + polys.alu_two_pow_s[i] = rows[i].alu_two_pow_s; + polys.alu_two_pow_t_sub_s[i] = rows[i].alu_two_pow_t_sub_s; + polys.alu_u128_tag[i] = rows[i].alu_u128_tag; + polys.alu_u16_r0[i] = rows[i].alu_u16_r0; + polys.alu_u16_r1[i] = rows[i].alu_u16_r1; + polys.alu_u16_r10[i] = rows[i].alu_u16_r10; + polys.alu_u16_r11[i] = rows[i].alu_u16_r11; + polys.alu_u16_r12[i] = rows[i].alu_u16_r12; + polys.alu_u16_r13[i] = rows[i].alu_u16_r13; + polys.alu_u16_r14[i] = rows[i].alu_u16_r14; + polys.alu_u16_r2[i] = rows[i].alu_u16_r2; + polys.alu_u16_r3[i] = rows[i].alu_u16_r3; + polys.alu_u16_r4[i] = rows[i].alu_u16_r4; + polys.alu_u16_r5[i] = rows[i].alu_u16_r5; + polys.alu_u16_r6[i] = rows[i].alu_u16_r6; + polys.alu_u16_r7[i] = rows[i].alu_u16_r7; + polys.alu_u16_r8[i] = rows[i].alu_u16_r8; + polys.alu_u16_r9[i] = rows[i].alu_u16_r9; + polys.alu_u16_tag[i] = rows[i].alu_u16_tag; + polys.alu_u32_tag[i] = rows[i].alu_u32_tag; + polys.alu_u64_tag[i] = rows[i].alu_u64_tag; + polys.alu_u8_r0[i] = rows[i].alu_u8_r0; + polys.alu_u8_r1[i] = rows[i].alu_u8_r1; + polys.alu_u8_tag[i] = rows[i].alu_u8_tag; + polys.binary_acc_ia[i] = rows[i].binary_acc_ia; + polys.binary_acc_ib[i] = rows[i].binary_acc_ib; + polys.binary_acc_ic[i] = rows[i].binary_acc_ic; + polys.binary_clk[i] = rows[i].binary_clk; + polys.binary_ia_bytes[i] = rows[i].binary_ia_bytes; + polys.binary_ib_bytes[i] = rows[i].binary_ib_bytes; + polys.binary_ic_bytes[i] = rows[i].binary_ic_bytes; + polys.binary_in_tag[i] = rows[i].binary_in_tag; + polys.binary_mem_tag_ctr[i] = rows[i].binary_mem_tag_ctr; + polys.binary_mem_tag_ctr_inv[i] = rows[i].binary_mem_tag_ctr_inv; + polys.binary_op_id[i] = rows[i].binary_op_id; + polys.binary_sel_bin[i] = rows[i].binary_sel_bin; + polys.binary_start[i] = rows[i].binary_start; + polys.byte_lookup_sel_bin[i] = rows[i].byte_lookup_sel_bin; + polys.byte_lookup_table_byte_lengths[i] = rows[i].byte_lookup_table_byte_lengths; + polys.byte_lookup_table_in_tags[i] = rows[i].byte_lookup_table_in_tags; + polys.byte_lookup_table_input_a[i] = rows[i].byte_lookup_table_input_a; + polys.byte_lookup_table_input_b[i] = rows[i].byte_lookup_table_input_b; + polys.byte_lookup_table_op_id[i] = rows[i].byte_lookup_table_op_id; + polys.byte_lookup_table_output[i] = rows[i].byte_lookup_table_output; + polys.conversion_clk[i] = rows[i].conversion_clk; + polys.conversion_input[i] = rows[i].conversion_input; + polys.conversion_num_limbs[i] = rows[i].conversion_num_limbs; + polys.conversion_radix[i] = rows[i].conversion_radix; + polys.conversion_sel_to_radix_le[i] = rows[i].conversion_sel_to_radix_le; + polys.gas_da_gas_fixed_table[i] = rows[i].gas_da_gas_fixed_table; + polys.gas_l2_gas_fixed_table[i] = rows[i].gas_l2_gas_fixed_table; + polys.gas_sel_gas_cost[i] = rows[i].gas_sel_gas_cost; + polys.keccakf1600_clk[i] = rows[i].keccakf1600_clk; + polys.keccakf1600_input[i] = rows[i].keccakf1600_input; + polys.keccakf1600_output[i] = rows[i].keccakf1600_output; + polys.keccakf1600_sel_keccakf1600[i] = rows[i].keccakf1600_sel_keccakf1600; + polys.kernel_emit_l2_to_l1_msg_write_offset[i] = rows[i].kernel_emit_l2_to_l1_msg_write_offset; + polys.kernel_emit_note_hash_write_offset[i] = rows[i].kernel_emit_note_hash_write_offset; + polys.kernel_emit_nullifier_write_offset[i] = rows[i].kernel_emit_nullifier_write_offset; + polys.kernel_emit_unencrypted_log_write_offset[i] = rows[i].kernel_emit_unencrypted_log_write_offset; + polys.kernel_kernel_in_offset[i] = rows[i].kernel_kernel_in_offset; + polys.kernel_kernel_out_offset[i] = rows[i].kernel_kernel_out_offset; + polys.kernel_l1_to_l2_msg_exists_write_offset[i] = rows[i].kernel_l1_to_l2_msg_exists_write_offset; + polys.kernel_note_hash_exist_write_offset[i] = rows[i].kernel_note_hash_exist_write_offset; + polys.kernel_nullifier_exists_write_offset[i] = rows[i].kernel_nullifier_exists_write_offset; + polys.kernel_nullifier_non_exists_write_offset[i] = rows[i].kernel_nullifier_non_exists_write_offset; + polys.kernel_q_public_input_kernel_add_to_table[i] = rows[i].kernel_q_public_input_kernel_add_to_table; + polys.kernel_q_public_input_kernel_out_add_to_table[i] = rows[i].kernel_q_public_input_kernel_out_add_to_table; + polys.kernel_side_effect_counter[i] = rows[i].kernel_side_effect_counter; + polys.kernel_sload_write_offset[i] = rows[i].kernel_sload_write_offset; + polys.kernel_sstore_write_offset[i] = rows[i].kernel_sstore_write_offset; + polys.main_abs_da_rem_gas_hi[i] = rows[i].main_abs_da_rem_gas_hi; + polys.main_abs_da_rem_gas_lo[i] = rows[i].main_abs_da_rem_gas_lo; + polys.main_abs_l2_rem_gas_hi[i] = rows[i].main_abs_l2_rem_gas_hi; + polys.main_abs_l2_rem_gas_lo[i] = rows[i].main_abs_l2_rem_gas_lo; + polys.main_alu_in_tag[i] = rows[i].main_alu_in_tag; + polys.main_bin_op_id[i] = rows[i].main_bin_op_id; + polys.main_call_ptr[i] = rows[i].main_call_ptr; + polys.main_da_gas_op_cost[i] = rows[i].main_da_gas_op_cost; + polys.main_da_gas_remaining[i] = rows[i].main_da_gas_remaining; + polys.main_da_out_of_gas[i] = rows[i].main_da_out_of_gas; + polys.main_ia[i] = rows[i].main_ia; + polys.main_ib[i] = rows[i].main_ib; + polys.main_ic[i] = rows[i].main_ic; + polys.main_id[i] = rows[i].main_id; + polys.main_id_zero[i] = rows[i].main_id_zero; + polys.main_ind_addr_a[i] = rows[i].main_ind_addr_a; + polys.main_ind_addr_b[i] = rows[i].main_ind_addr_b; + polys.main_ind_addr_c[i] = rows[i].main_ind_addr_c; + polys.main_ind_addr_d[i] = rows[i].main_ind_addr_d; + polys.main_internal_return_ptr[i] = rows[i].main_internal_return_ptr; + polys.main_inv[i] = rows[i].main_inv; + polys.main_l2_gas_op_cost[i] = rows[i].main_l2_gas_op_cost; + polys.main_l2_gas_remaining[i] = rows[i].main_l2_gas_remaining; + polys.main_l2_out_of_gas[i] = rows[i].main_l2_out_of_gas; + polys.main_mem_addr_a[i] = rows[i].main_mem_addr_a; + polys.main_mem_addr_b[i] = rows[i].main_mem_addr_b; + polys.main_mem_addr_c[i] = rows[i].main_mem_addr_c; + polys.main_mem_addr_d[i] = rows[i].main_mem_addr_d; + polys.main_op_err[i] = rows[i].main_op_err; + polys.main_opcode_val[i] = rows[i].main_opcode_val; + polys.main_pc[i] = rows[i].main_pc; + polys.main_r_in_tag[i] = rows[i].main_r_in_tag; + polys.main_rwa[i] = rows[i].main_rwa; + polys.main_rwb[i] = rows[i].main_rwb; + polys.main_rwc[i] = rows[i].main_rwc; + polys.main_rwd[i] = rows[i].main_rwd; + polys.main_sel_alu[i] = rows[i].main_sel_alu; + polys.main_sel_bin[i] = rows[i].main_sel_bin; + polys.main_sel_calldata[i] = rows[i].main_sel_calldata; + polys.main_sel_gas_accounting_active[i] = rows[i].main_sel_gas_accounting_active; + polys.main_sel_last[i] = rows[i].main_sel_last; + polys.main_sel_mem_op_a[i] = rows[i].main_sel_mem_op_a; + polys.main_sel_mem_op_activate_gas[i] = rows[i].main_sel_mem_op_activate_gas; + polys.main_sel_mem_op_b[i] = rows[i].main_sel_mem_op_b; + polys.main_sel_mem_op_c[i] = rows[i].main_sel_mem_op_c; + polys.main_sel_mem_op_d[i] = rows[i].main_sel_mem_op_d; + polys.main_sel_mov_ia_to_ic[i] = rows[i].main_sel_mov_ia_to_ic; + polys.main_sel_mov_ib_to_ic[i] = rows[i].main_sel_mov_ib_to_ic; + polys.main_sel_op_add[i] = rows[i].main_sel_op_add; + polys.main_sel_op_address[i] = rows[i].main_sel_op_address; + polys.main_sel_op_and[i] = rows[i].main_sel_op_and; + polys.main_sel_op_block_number[i] = rows[i].main_sel_op_block_number; + polys.main_sel_op_calldata_copy[i] = rows[i].main_sel_op_calldata_copy; + polys.main_sel_op_cast[i] = rows[i].main_sel_op_cast; + polys.main_sel_op_chain_id[i] = rows[i].main_sel_op_chain_id; + polys.main_sel_op_cmov[i] = rows[i].main_sel_op_cmov; + polys.main_sel_op_coinbase[i] = rows[i].main_sel_op_coinbase; + polys.main_sel_op_dagasleft[i] = rows[i].main_sel_op_dagasleft; + polys.main_sel_op_div[i] = rows[i].main_sel_op_div; + polys.main_sel_op_emit_l2_to_l1_msg[i] = rows[i].main_sel_op_emit_l2_to_l1_msg; + polys.main_sel_op_emit_note_hash[i] = rows[i].main_sel_op_emit_note_hash; + polys.main_sel_op_emit_nullifier[i] = rows[i].main_sel_op_emit_nullifier; + polys.main_sel_op_emit_unencrypted_log[i] = rows[i].main_sel_op_emit_unencrypted_log; + polys.main_sel_op_eq[i] = rows[i].main_sel_op_eq; + polys.main_sel_op_external_call[i] = rows[i].main_sel_op_external_call; + polys.main_sel_op_external_return[i] = rows[i].main_sel_op_external_return; + polys.main_sel_op_fdiv[i] = rows[i].main_sel_op_fdiv; + polys.main_sel_op_fee_per_da_gas[i] = rows[i].main_sel_op_fee_per_da_gas; + polys.main_sel_op_fee_per_l2_gas[i] = rows[i].main_sel_op_fee_per_l2_gas; + polys.main_sel_op_function_selector[i] = rows[i].main_sel_op_function_selector; + polys.main_sel_op_get_contract_instance[i] = rows[i].main_sel_op_get_contract_instance; + polys.main_sel_op_halt[i] = rows[i].main_sel_op_halt; + polys.main_sel_op_internal_call[i] = rows[i].main_sel_op_internal_call; + polys.main_sel_op_internal_return[i] = rows[i].main_sel_op_internal_return; + polys.main_sel_op_jump[i] = rows[i].main_sel_op_jump; + polys.main_sel_op_jumpi[i] = rows[i].main_sel_op_jumpi; + polys.main_sel_op_keccak[i] = rows[i].main_sel_op_keccak; + polys.main_sel_op_l1_to_l2_msg_exists[i] = rows[i].main_sel_op_l1_to_l2_msg_exists; + polys.main_sel_op_l2gasleft[i] = rows[i].main_sel_op_l2gasleft; + polys.main_sel_op_lt[i] = rows[i].main_sel_op_lt; + polys.main_sel_op_lte[i] = rows[i].main_sel_op_lte; + polys.main_sel_op_mov[i] = rows[i].main_sel_op_mov; + polys.main_sel_op_mul[i] = rows[i].main_sel_op_mul; + polys.main_sel_op_not[i] = rows[i].main_sel_op_not; + polys.main_sel_op_note_hash_exists[i] = rows[i].main_sel_op_note_hash_exists; + polys.main_sel_op_nullifier_exists[i] = rows[i].main_sel_op_nullifier_exists; + polys.main_sel_op_or[i] = rows[i].main_sel_op_or; + polys.main_sel_op_pedersen[i] = rows[i].main_sel_op_pedersen; + polys.main_sel_op_poseidon2[i] = rows[i].main_sel_op_poseidon2; + polys.main_sel_op_radix_le[i] = rows[i].main_sel_op_radix_le; + polys.main_sel_op_sender[i] = rows[i].main_sel_op_sender; + polys.main_sel_op_sha256[i] = rows[i].main_sel_op_sha256; + polys.main_sel_op_shl[i] = rows[i].main_sel_op_shl; + polys.main_sel_op_shr[i] = rows[i].main_sel_op_shr; + polys.main_sel_op_sload[i] = rows[i].main_sel_op_sload; + polys.main_sel_op_sstore[i] = rows[i].main_sel_op_sstore; + polys.main_sel_op_storage_address[i] = rows[i].main_sel_op_storage_address; + polys.main_sel_op_sub[i] = rows[i].main_sel_op_sub; + polys.main_sel_op_timestamp[i] = rows[i].main_sel_op_timestamp; + polys.main_sel_op_transaction_fee[i] = rows[i].main_sel_op_transaction_fee; + polys.main_sel_op_version[i] = rows[i].main_sel_op_version; + polys.main_sel_op_xor[i] = rows[i].main_sel_op_xor; + polys.main_sel_q_kernel_lookup[i] = rows[i].main_sel_q_kernel_lookup; + polys.main_sel_q_kernel_output_lookup[i] = rows[i].main_sel_q_kernel_output_lookup; + polys.main_sel_resolve_ind_addr_a[i] = rows[i].main_sel_resolve_ind_addr_a; + polys.main_sel_resolve_ind_addr_b[i] = rows[i].main_sel_resolve_ind_addr_b; + polys.main_sel_resolve_ind_addr_c[i] = rows[i].main_sel_resolve_ind_addr_c; + polys.main_sel_resolve_ind_addr_d[i] = rows[i].main_sel_resolve_ind_addr_d; + polys.main_sel_returndata[i] = rows[i].main_sel_returndata; + polys.main_sel_rng_16[i] = rows[i].main_sel_rng_16; + polys.main_sel_rng_8[i] = rows[i].main_sel_rng_8; + polys.main_sel_slice_gadget[i] = rows[i].main_sel_slice_gadget; + polys.main_space_id[i] = rows[i].main_space_id; + polys.main_tag_err[i] = rows[i].main_tag_err; + polys.main_w_in_tag[i] = rows[i].main_w_in_tag; + polys.mem_addr[i] = rows[i].mem_addr; + polys.mem_clk[i] = rows[i].mem_clk; + polys.mem_diff_hi[i] = rows[i].mem_diff_hi; + polys.mem_diff_lo[i] = rows[i].mem_diff_lo; + polys.mem_diff_mid[i] = rows[i].mem_diff_mid; + polys.mem_glob_addr[i] = rows[i].mem_glob_addr; + polys.mem_last[i] = rows[i].mem_last; + polys.mem_lastAccess[i] = rows[i].mem_lastAccess; + polys.mem_one_min_inv[i] = rows[i].mem_one_min_inv; + polys.mem_r_in_tag[i] = rows[i].mem_r_in_tag; + polys.mem_rw[i] = rows[i].mem_rw; + polys.mem_sel_mem[i] = rows[i].mem_sel_mem; + polys.mem_sel_mov_ia_to_ic[i] = rows[i].mem_sel_mov_ia_to_ic; + polys.mem_sel_mov_ib_to_ic[i] = rows[i].mem_sel_mov_ib_to_ic; + polys.mem_sel_op_a[i] = rows[i].mem_sel_op_a; + polys.mem_sel_op_b[i] = rows[i].mem_sel_op_b; + polys.mem_sel_op_c[i] = rows[i].mem_sel_op_c; + polys.mem_sel_op_cmov[i] = rows[i].mem_sel_op_cmov; + polys.mem_sel_op_d[i] = rows[i].mem_sel_op_d; + polys.mem_sel_op_slice[i] = rows[i].mem_sel_op_slice; + polys.mem_sel_resolve_ind_addr_a[i] = rows[i].mem_sel_resolve_ind_addr_a; + polys.mem_sel_resolve_ind_addr_b[i] = rows[i].mem_sel_resolve_ind_addr_b; + polys.mem_sel_resolve_ind_addr_c[i] = rows[i].mem_sel_resolve_ind_addr_c; + polys.mem_sel_resolve_ind_addr_d[i] = rows[i].mem_sel_resolve_ind_addr_d; + polys.mem_sel_rng_chk[i] = rows[i].mem_sel_rng_chk; + polys.mem_skip_check_tag[i] = rows[i].mem_skip_check_tag; + polys.mem_space_id[i] = rows[i].mem_space_id; + polys.mem_tag[i] = rows[i].mem_tag; + polys.mem_tag_err[i] = rows[i].mem_tag_err; + polys.mem_tsp[i] = rows[i].mem_tsp; + polys.mem_val[i] = rows[i].mem_val; + polys.mem_w_in_tag[i] = rows[i].mem_w_in_tag; + polys.pedersen_clk[i] = rows[i].pedersen_clk; + polys.pedersen_input[i] = rows[i].pedersen_input; + polys.pedersen_output[i] = rows[i].pedersen_output; + polys.pedersen_sel_pedersen[i] = rows[i].pedersen_sel_pedersen; + polys.poseidon2_clk[i] = rows[i].poseidon2_clk; + polys.poseidon2_input[i] = rows[i].poseidon2_input; + polys.poseidon2_output[i] = rows[i].poseidon2_output; + polys.poseidon2_sel_poseidon_perm[i] = rows[i].poseidon2_sel_poseidon_perm; + polys.powers_power_of_2[i] = rows[i].powers_power_of_2; + polys.sha256_clk[i] = rows[i].sha256_clk; + polys.sha256_input[i] = rows[i].sha256_input; + polys.sha256_output[i] = rows[i].sha256_output; + polys.sha256_sel_sha256_compression[i] = rows[i].sha256_sel_sha256_compression; + polys.sha256_state[i] = rows[i].sha256_state; + polys.slice_addr[i] = rows[i].slice_addr; + polys.slice_clk[i] = rows[i].slice_clk; + polys.slice_cnt[i] = rows[i].slice_cnt; + polys.slice_col_offset[i] = rows[i].slice_col_offset; + polys.slice_one_min_inv[i] = rows[i].slice_one_min_inv; + polys.slice_sel_cd_cpy[i] = rows[i].slice_sel_cd_cpy; + polys.slice_sel_mem_active[i] = rows[i].slice_sel_mem_active; + polys.slice_sel_return[i] = rows[i].slice_sel_return; + polys.slice_sel_start[i] = rows[i].slice_sel_start; + polys.slice_space_id[i] = rows[i].slice_space_id; + polys.slice_val[i] = rows[i].slice_val; + polys.lookup_byte_lengths_counts[i] = rows[i].lookup_byte_lengths_counts; + polys.lookup_byte_operations_counts[i] = rows[i].lookup_byte_operations_counts; + polys.lookup_cd_value_counts[i] = rows[i].lookup_cd_value_counts; + polys.lookup_ret_value_counts[i] = rows[i].lookup_ret_value_counts; + polys.lookup_opcode_gas_counts[i] = rows[i].lookup_opcode_gas_counts; + polys.range_check_l2_gas_hi_counts[i] = rows[i].range_check_l2_gas_hi_counts; + polys.range_check_l2_gas_lo_counts[i] = rows[i].range_check_l2_gas_lo_counts; + polys.range_check_da_gas_hi_counts[i] = rows[i].range_check_da_gas_hi_counts; + polys.range_check_da_gas_lo_counts[i] = rows[i].range_check_da_gas_lo_counts; + polys.kernel_output_lookup_counts[i] = rows[i].kernel_output_lookup_counts; + polys.lookup_into_kernel_counts[i] = rows[i].lookup_into_kernel_counts; + polys.incl_main_tag_err_counts[i] = rows[i].incl_main_tag_err_counts; + polys.incl_mem_tag_err_counts[i] = rows[i].incl_mem_tag_err_counts; + polys.lookup_mem_rng_chk_lo_counts[i] = rows[i].lookup_mem_rng_chk_lo_counts; + polys.lookup_mem_rng_chk_mid_counts[i] = rows[i].lookup_mem_rng_chk_mid_counts; + polys.lookup_mem_rng_chk_hi_counts[i] = rows[i].lookup_mem_rng_chk_hi_counts; + polys.lookup_pow_2_0_counts[i] = rows[i].lookup_pow_2_0_counts; + polys.lookup_pow_2_1_counts[i] = rows[i].lookup_pow_2_1_counts; + polys.lookup_u8_0_counts[i] = rows[i].lookup_u8_0_counts; + polys.lookup_u8_1_counts[i] = rows[i].lookup_u8_1_counts; + polys.lookup_u16_0_counts[i] = rows[i].lookup_u16_0_counts; + polys.lookup_u16_1_counts[i] = rows[i].lookup_u16_1_counts; + polys.lookup_u16_2_counts[i] = rows[i].lookup_u16_2_counts; + polys.lookup_u16_3_counts[i] = rows[i].lookup_u16_3_counts; + polys.lookup_u16_4_counts[i] = rows[i].lookup_u16_4_counts; + polys.lookup_u16_5_counts[i] = rows[i].lookup_u16_5_counts; + polys.lookup_u16_6_counts[i] = rows[i].lookup_u16_6_counts; + polys.lookup_u16_7_counts[i] = rows[i].lookup_u16_7_counts; + polys.lookup_u16_8_counts[i] = rows[i].lookup_u16_8_counts; + polys.lookup_u16_9_counts[i] = rows[i].lookup_u16_9_counts; + polys.lookup_u16_10_counts[i] = rows[i].lookup_u16_10_counts; + polys.lookup_u16_11_counts[i] = rows[i].lookup_u16_11_counts; + polys.lookup_u16_12_counts[i] = rows[i].lookup_u16_12_counts; + polys.lookup_u16_13_counts[i] = rows[i].lookup_u16_13_counts; + polys.lookup_u16_14_counts[i] = rows[i].lookup_u16_14_counts; + polys.lookup_div_u16_0_counts[i] = rows[i].lookup_div_u16_0_counts; + polys.lookup_div_u16_1_counts[i] = rows[i].lookup_div_u16_1_counts; + polys.lookup_div_u16_2_counts[i] = rows[i].lookup_div_u16_2_counts; + polys.lookup_div_u16_3_counts[i] = rows[i].lookup_div_u16_3_counts; + polys.lookup_div_u16_4_counts[i] = rows[i].lookup_div_u16_4_counts; + polys.lookup_div_u16_5_counts[i] = rows[i].lookup_div_u16_5_counts; + polys.lookup_div_u16_6_counts[i] = rows[i].lookup_div_u16_6_counts; + polys.lookup_div_u16_7_counts[i] = rows[i].lookup_div_u16_7_counts; + } + + for (auto [shifted, to_be_shifted] : zip_view(polys.get_shifted(), polys.get_to_be_shifted())) { + shifted = to_be_shifted.shifted(); + } + + return polys; +} + +bool AvmCircuitBuilder::check_circuit() const +{ + const FF gamma = FF::random_element(); + const FF beta = FF::random_element(); + bb::RelationParameters params{ + .eta = 0, + .beta = beta, + .gamma = gamma, + .public_input_delta = 0, + .lookup_grand_product_delta = 0, + .beta_sqr = 0, + .beta_cube = 0, + .eccvm_set_permutation_delta = 0, + }; + + auto polys = compute_polynomials(); + const size_t num_rows = polys.get_polynomial_size(); + + // Checks that we will run. + using SignalErrorFn = const std::function&; + std::vector> checks; + + // Add relation checks. + bb::constexpr_for<0, std::tuple_size_v, 1>([&]() { + using Relation = std::tuple_element_t; + checks.push_back([&](SignalErrorFn signal_error) { + typename Relation::SumcheckArrayOfValuesOverSubrelations result; + for (auto& r : result) { + r = 0; + } + constexpr size_t NUM_SUBRELATIONS = result.size(); + + for (size_t r = 0; r < num_rows; ++r) { + Relation::accumulate(result, polys.get_row(r), {}, 1); + for (size_t j = 0; j < NUM_SUBRELATIONS; ++j) { + if (result[j] != 0) { + signal_error(format("Relation ", + Relation::NAME, + ", subrelation ", + Relation::get_subrelation_label(j), + " failed at row ", + r)); + } + } + } + }); + }); + + // Add calculation of logderivatives and lookup/permutation checks. + bb::constexpr_for<0, std::tuple_size_v, 1>([&]() { + using Relation = std::tuple_element_t; + checks.push_back([&, num_rows](SignalErrorFn signal_error) { + // Check the logderivative relation + bb::compute_logderivative_inverse(polys, params, num_rows); + + typename Relation::SumcheckArrayOfValuesOverSubrelations lookup_result; + + for (auto& r : lookup_result) { + r = 0; + } + for (size_t r = 0; r < num_rows; ++r) { + Relation::accumulate(lookup_result, polys.get_row(r), params, 1); + } + for (auto r : lookup_result) { + if (r != 0) { + signal_error(format("Lookup ", Relation::NAME, " failed.")); + } + } + }); + }); + + std::string errors; + std::mutex m; + auto signal_error = [&](const std::string& error) { + std::lock_guard lock(m); + errors += error + "\n"; + }; + bb::parallel_for(checks.size(), [&](size_t i) { checks[i](signal_error); }); + if (!errors.empty()) { + throw_or_abort(errors); + } + + return errors.empty(); +} + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp index 9db07fe5038..40a2844a71e 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -1,16 +1,8 @@ // AUTOGENERATED FILE #pragma once -#include #include -#include "barretenberg/common/constexpr_utils.hpp" -#include "barretenberg/common/thread.hpp" -#include "barretenberg/common/throw_or_abort.hpp" -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/honk/proof_system/logderivative_library.hpp" -#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" -#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" #include "barretenberg/stdlib_circuit_builders/circuit_builder_base.hpp" #include "barretenberg/vm/generated/avm_flavor.hpp" @@ -34,469 +26,13 @@ class AvmCircuitBuilder { void set_trace(std::vector&& trace) { rows = std::move(trace); } - ProverPolynomials compute_polynomials() - { - const auto num_rows = get_circuit_subgroup_size(); - ProverPolynomials polys; - - // Allocate mem for each column - for (auto& poly : polys.get_all()) { - poly = Polynomial(num_rows); - } - - for (size_t i = 0; i < rows.size(); i++) { - polys.main_clk[i] = rows[i].main_clk; - polys.main_sel_first[i] = rows[i].main_sel_first; - polys.kernel_kernel_inputs[i] = rows[i].kernel_kernel_inputs; - polys.kernel_kernel_value_out[i] = rows[i].kernel_kernel_value_out; - polys.kernel_kernel_side_effect_out[i] = rows[i].kernel_kernel_side_effect_out; - polys.kernel_kernel_metadata_out[i] = rows[i].kernel_kernel_metadata_out; - polys.main_calldata[i] = rows[i].main_calldata; - polys.main_returndata[i] = rows[i].main_returndata; - polys.alu_a_hi[i] = rows[i].alu_a_hi; - polys.alu_a_lo[i] = rows[i].alu_a_lo; - polys.alu_b_hi[i] = rows[i].alu_b_hi; - polys.alu_b_lo[i] = rows[i].alu_b_lo; - polys.alu_borrow[i] = rows[i].alu_borrow; - polys.alu_cf[i] = rows[i].alu_cf; - polys.alu_clk[i] = rows[i].alu_clk; - polys.alu_cmp_rng_ctr[i] = rows[i].alu_cmp_rng_ctr; - polys.alu_div_u16_r0[i] = rows[i].alu_div_u16_r0; - polys.alu_div_u16_r1[i] = rows[i].alu_div_u16_r1; - polys.alu_div_u16_r2[i] = rows[i].alu_div_u16_r2; - polys.alu_div_u16_r3[i] = rows[i].alu_div_u16_r3; - polys.alu_div_u16_r4[i] = rows[i].alu_div_u16_r4; - polys.alu_div_u16_r5[i] = rows[i].alu_div_u16_r5; - polys.alu_div_u16_r6[i] = rows[i].alu_div_u16_r6; - polys.alu_div_u16_r7[i] = rows[i].alu_div_u16_r7; - polys.alu_divisor_hi[i] = rows[i].alu_divisor_hi; - polys.alu_divisor_lo[i] = rows[i].alu_divisor_lo; - polys.alu_ff_tag[i] = rows[i].alu_ff_tag; - polys.alu_ia[i] = rows[i].alu_ia; - polys.alu_ib[i] = rows[i].alu_ib; - polys.alu_ic[i] = rows[i].alu_ic; - polys.alu_in_tag[i] = rows[i].alu_in_tag; - polys.alu_op_add[i] = rows[i].alu_op_add; - polys.alu_op_cast[i] = rows[i].alu_op_cast; - polys.alu_op_cast_prev[i] = rows[i].alu_op_cast_prev; - polys.alu_op_div[i] = rows[i].alu_op_div; - polys.alu_op_div_a_lt_b[i] = rows[i].alu_op_div_a_lt_b; - polys.alu_op_div_std[i] = rows[i].alu_op_div_std; - polys.alu_op_eq[i] = rows[i].alu_op_eq; - polys.alu_op_eq_diff_inv[i] = rows[i].alu_op_eq_diff_inv; - polys.alu_op_lt[i] = rows[i].alu_op_lt; - polys.alu_op_lte[i] = rows[i].alu_op_lte; - polys.alu_op_mul[i] = rows[i].alu_op_mul; - polys.alu_op_not[i] = rows[i].alu_op_not; - polys.alu_op_shl[i] = rows[i].alu_op_shl; - polys.alu_op_shr[i] = rows[i].alu_op_shr; - polys.alu_op_sub[i] = rows[i].alu_op_sub; - polys.alu_p_a_borrow[i] = rows[i].alu_p_a_borrow; - polys.alu_p_b_borrow[i] = rows[i].alu_p_b_borrow; - polys.alu_p_sub_a_hi[i] = rows[i].alu_p_sub_a_hi; - polys.alu_p_sub_a_lo[i] = rows[i].alu_p_sub_a_lo; - polys.alu_p_sub_b_hi[i] = rows[i].alu_p_sub_b_hi; - polys.alu_p_sub_b_lo[i] = rows[i].alu_p_sub_b_lo; - polys.alu_partial_prod_hi[i] = rows[i].alu_partial_prod_hi; - polys.alu_partial_prod_lo[i] = rows[i].alu_partial_prod_lo; - polys.alu_quotient_hi[i] = rows[i].alu_quotient_hi; - polys.alu_quotient_lo[i] = rows[i].alu_quotient_lo; - polys.alu_remainder[i] = rows[i].alu_remainder; - polys.alu_res_hi[i] = rows[i].alu_res_hi; - polys.alu_res_lo[i] = rows[i].alu_res_lo; - polys.alu_sel_alu[i] = rows[i].alu_sel_alu; - polys.alu_sel_cmp[i] = rows[i].alu_sel_cmp; - polys.alu_sel_div_rng_chk[i] = rows[i].alu_sel_div_rng_chk; - polys.alu_sel_rng_chk[i] = rows[i].alu_sel_rng_chk; - polys.alu_sel_rng_chk_lookup[i] = rows[i].alu_sel_rng_chk_lookup; - polys.alu_sel_shift_which[i] = rows[i].alu_sel_shift_which; - polys.alu_shift_lt_bit_len[i] = rows[i].alu_shift_lt_bit_len; - polys.alu_t_sub_s_bits[i] = rows[i].alu_t_sub_s_bits; - polys.alu_two_pow_s[i] = rows[i].alu_two_pow_s; - polys.alu_two_pow_t_sub_s[i] = rows[i].alu_two_pow_t_sub_s; - polys.alu_u128_tag[i] = rows[i].alu_u128_tag; - polys.alu_u16_r0[i] = rows[i].alu_u16_r0; - polys.alu_u16_r1[i] = rows[i].alu_u16_r1; - polys.alu_u16_r10[i] = rows[i].alu_u16_r10; - polys.alu_u16_r11[i] = rows[i].alu_u16_r11; - polys.alu_u16_r12[i] = rows[i].alu_u16_r12; - polys.alu_u16_r13[i] = rows[i].alu_u16_r13; - polys.alu_u16_r14[i] = rows[i].alu_u16_r14; - polys.alu_u16_r2[i] = rows[i].alu_u16_r2; - polys.alu_u16_r3[i] = rows[i].alu_u16_r3; - polys.alu_u16_r4[i] = rows[i].alu_u16_r4; - polys.alu_u16_r5[i] = rows[i].alu_u16_r5; - polys.alu_u16_r6[i] = rows[i].alu_u16_r6; - polys.alu_u16_r7[i] = rows[i].alu_u16_r7; - polys.alu_u16_r8[i] = rows[i].alu_u16_r8; - polys.alu_u16_r9[i] = rows[i].alu_u16_r9; - polys.alu_u16_tag[i] = rows[i].alu_u16_tag; - polys.alu_u32_tag[i] = rows[i].alu_u32_tag; - polys.alu_u64_tag[i] = rows[i].alu_u64_tag; - polys.alu_u8_r0[i] = rows[i].alu_u8_r0; - polys.alu_u8_r1[i] = rows[i].alu_u8_r1; - polys.alu_u8_tag[i] = rows[i].alu_u8_tag; - polys.binary_acc_ia[i] = rows[i].binary_acc_ia; - polys.binary_acc_ib[i] = rows[i].binary_acc_ib; - polys.binary_acc_ic[i] = rows[i].binary_acc_ic; - polys.binary_clk[i] = rows[i].binary_clk; - polys.binary_ia_bytes[i] = rows[i].binary_ia_bytes; - polys.binary_ib_bytes[i] = rows[i].binary_ib_bytes; - polys.binary_ic_bytes[i] = rows[i].binary_ic_bytes; - polys.binary_in_tag[i] = rows[i].binary_in_tag; - polys.binary_mem_tag_ctr[i] = rows[i].binary_mem_tag_ctr; - polys.binary_mem_tag_ctr_inv[i] = rows[i].binary_mem_tag_ctr_inv; - polys.binary_op_id[i] = rows[i].binary_op_id; - polys.binary_sel_bin[i] = rows[i].binary_sel_bin; - polys.binary_start[i] = rows[i].binary_start; - polys.byte_lookup_sel_bin[i] = rows[i].byte_lookup_sel_bin; - polys.byte_lookup_table_byte_lengths[i] = rows[i].byte_lookup_table_byte_lengths; - polys.byte_lookup_table_in_tags[i] = rows[i].byte_lookup_table_in_tags; - polys.byte_lookup_table_input_a[i] = rows[i].byte_lookup_table_input_a; - polys.byte_lookup_table_input_b[i] = rows[i].byte_lookup_table_input_b; - polys.byte_lookup_table_op_id[i] = rows[i].byte_lookup_table_op_id; - polys.byte_lookup_table_output[i] = rows[i].byte_lookup_table_output; - polys.conversion_clk[i] = rows[i].conversion_clk; - polys.conversion_input[i] = rows[i].conversion_input; - polys.conversion_num_limbs[i] = rows[i].conversion_num_limbs; - polys.conversion_radix[i] = rows[i].conversion_radix; - polys.conversion_sel_to_radix_le[i] = rows[i].conversion_sel_to_radix_le; - polys.gas_da_gas_fixed_table[i] = rows[i].gas_da_gas_fixed_table; - polys.gas_l2_gas_fixed_table[i] = rows[i].gas_l2_gas_fixed_table; - polys.gas_sel_gas_cost[i] = rows[i].gas_sel_gas_cost; - polys.keccakf1600_clk[i] = rows[i].keccakf1600_clk; - polys.keccakf1600_input[i] = rows[i].keccakf1600_input; - polys.keccakf1600_output[i] = rows[i].keccakf1600_output; - polys.keccakf1600_sel_keccakf1600[i] = rows[i].keccakf1600_sel_keccakf1600; - polys.kernel_emit_l2_to_l1_msg_write_offset[i] = rows[i].kernel_emit_l2_to_l1_msg_write_offset; - polys.kernel_emit_note_hash_write_offset[i] = rows[i].kernel_emit_note_hash_write_offset; - polys.kernel_emit_nullifier_write_offset[i] = rows[i].kernel_emit_nullifier_write_offset; - polys.kernel_emit_unencrypted_log_write_offset[i] = rows[i].kernel_emit_unencrypted_log_write_offset; - polys.kernel_kernel_in_offset[i] = rows[i].kernel_kernel_in_offset; - polys.kernel_kernel_out_offset[i] = rows[i].kernel_kernel_out_offset; - polys.kernel_l1_to_l2_msg_exists_write_offset[i] = rows[i].kernel_l1_to_l2_msg_exists_write_offset; - polys.kernel_note_hash_exist_write_offset[i] = rows[i].kernel_note_hash_exist_write_offset; - polys.kernel_nullifier_exists_write_offset[i] = rows[i].kernel_nullifier_exists_write_offset; - polys.kernel_nullifier_non_exists_write_offset[i] = rows[i].kernel_nullifier_non_exists_write_offset; - polys.kernel_q_public_input_kernel_add_to_table[i] = rows[i].kernel_q_public_input_kernel_add_to_table; - polys.kernel_q_public_input_kernel_out_add_to_table[i] = - rows[i].kernel_q_public_input_kernel_out_add_to_table; - polys.kernel_side_effect_counter[i] = rows[i].kernel_side_effect_counter; - polys.kernel_sload_write_offset[i] = rows[i].kernel_sload_write_offset; - polys.kernel_sstore_write_offset[i] = rows[i].kernel_sstore_write_offset; - polys.main_abs_da_rem_gas_hi[i] = rows[i].main_abs_da_rem_gas_hi; - polys.main_abs_da_rem_gas_lo[i] = rows[i].main_abs_da_rem_gas_lo; - polys.main_abs_l2_rem_gas_hi[i] = rows[i].main_abs_l2_rem_gas_hi; - polys.main_abs_l2_rem_gas_lo[i] = rows[i].main_abs_l2_rem_gas_lo; - polys.main_alu_in_tag[i] = rows[i].main_alu_in_tag; - polys.main_bin_op_id[i] = rows[i].main_bin_op_id; - polys.main_call_ptr[i] = rows[i].main_call_ptr; - polys.main_da_gas_op_cost[i] = rows[i].main_da_gas_op_cost; - polys.main_da_gas_remaining[i] = rows[i].main_da_gas_remaining; - polys.main_da_out_of_gas[i] = rows[i].main_da_out_of_gas; - polys.main_ia[i] = rows[i].main_ia; - polys.main_ib[i] = rows[i].main_ib; - polys.main_ic[i] = rows[i].main_ic; - polys.main_id[i] = rows[i].main_id; - polys.main_id_zero[i] = rows[i].main_id_zero; - polys.main_ind_addr_a[i] = rows[i].main_ind_addr_a; - polys.main_ind_addr_b[i] = rows[i].main_ind_addr_b; - polys.main_ind_addr_c[i] = rows[i].main_ind_addr_c; - polys.main_ind_addr_d[i] = rows[i].main_ind_addr_d; - polys.main_internal_return_ptr[i] = rows[i].main_internal_return_ptr; - polys.main_inv[i] = rows[i].main_inv; - polys.main_l2_gas_op_cost[i] = rows[i].main_l2_gas_op_cost; - polys.main_l2_gas_remaining[i] = rows[i].main_l2_gas_remaining; - polys.main_l2_out_of_gas[i] = rows[i].main_l2_out_of_gas; - polys.main_mem_addr_a[i] = rows[i].main_mem_addr_a; - polys.main_mem_addr_b[i] = rows[i].main_mem_addr_b; - polys.main_mem_addr_c[i] = rows[i].main_mem_addr_c; - polys.main_mem_addr_d[i] = rows[i].main_mem_addr_d; - polys.main_op_err[i] = rows[i].main_op_err; - polys.main_opcode_val[i] = rows[i].main_opcode_val; - polys.main_pc[i] = rows[i].main_pc; - polys.main_r_in_tag[i] = rows[i].main_r_in_tag; - polys.main_rwa[i] = rows[i].main_rwa; - polys.main_rwb[i] = rows[i].main_rwb; - polys.main_rwc[i] = rows[i].main_rwc; - polys.main_rwd[i] = rows[i].main_rwd; - polys.main_sel_alu[i] = rows[i].main_sel_alu; - polys.main_sel_bin[i] = rows[i].main_sel_bin; - polys.main_sel_calldata[i] = rows[i].main_sel_calldata; - polys.main_sel_gas_accounting_active[i] = rows[i].main_sel_gas_accounting_active; - polys.main_sel_last[i] = rows[i].main_sel_last; - polys.main_sel_mem_op_a[i] = rows[i].main_sel_mem_op_a; - polys.main_sel_mem_op_activate_gas[i] = rows[i].main_sel_mem_op_activate_gas; - polys.main_sel_mem_op_b[i] = rows[i].main_sel_mem_op_b; - polys.main_sel_mem_op_c[i] = rows[i].main_sel_mem_op_c; - polys.main_sel_mem_op_d[i] = rows[i].main_sel_mem_op_d; - polys.main_sel_mov_ia_to_ic[i] = rows[i].main_sel_mov_ia_to_ic; - polys.main_sel_mov_ib_to_ic[i] = rows[i].main_sel_mov_ib_to_ic; - polys.main_sel_op_add[i] = rows[i].main_sel_op_add; - polys.main_sel_op_address[i] = rows[i].main_sel_op_address; - polys.main_sel_op_and[i] = rows[i].main_sel_op_and; - polys.main_sel_op_block_number[i] = rows[i].main_sel_op_block_number; - polys.main_sel_op_calldata_copy[i] = rows[i].main_sel_op_calldata_copy; - polys.main_sel_op_cast[i] = rows[i].main_sel_op_cast; - polys.main_sel_op_chain_id[i] = rows[i].main_sel_op_chain_id; - polys.main_sel_op_cmov[i] = rows[i].main_sel_op_cmov; - polys.main_sel_op_coinbase[i] = rows[i].main_sel_op_coinbase; - polys.main_sel_op_dagasleft[i] = rows[i].main_sel_op_dagasleft; - polys.main_sel_op_div[i] = rows[i].main_sel_op_div; - polys.main_sel_op_emit_l2_to_l1_msg[i] = rows[i].main_sel_op_emit_l2_to_l1_msg; - polys.main_sel_op_emit_note_hash[i] = rows[i].main_sel_op_emit_note_hash; - polys.main_sel_op_emit_nullifier[i] = rows[i].main_sel_op_emit_nullifier; - polys.main_sel_op_emit_unencrypted_log[i] = rows[i].main_sel_op_emit_unencrypted_log; - polys.main_sel_op_eq[i] = rows[i].main_sel_op_eq; - polys.main_sel_op_external_call[i] = rows[i].main_sel_op_external_call; - polys.main_sel_op_external_return[i] = rows[i].main_sel_op_external_return; - polys.main_sel_op_fdiv[i] = rows[i].main_sel_op_fdiv; - polys.main_sel_op_fee_per_da_gas[i] = rows[i].main_sel_op_fee_per_da_gas; - polys.main_sel_op_fee_per_l2_gas[i] = rows[i].main_sel_op_fee_per_l2_gas; - polys.main_sel_op_function_selector[i] = rows[i].main_sel_op_function_selector; - polys.main_sel_op_get_contract_instance[i] = rows[i].main_sel_op_get_contract_instance; - polys.main_sel_op_halt[i] = rows[i].main_sel_op_halt; - polys.main_sel_op_internal_call[i] = rows[i].main_sel_op_internal_call; - polys.main_sel_op_internal_return[i] = rows[i].main_sel_op_internal_return; - polys.main_sel_op_jump[i] = rows[i].main_sel_op_jump; - polys.main_sel_op_jumpi[i] = rows[i].main_sel_op_jumpi; - polys.main_sel_op_keccak[i] = rows[i].main_sel_op_keccak; - polys.main_sel_op_l1_to_l2_msg_exists[i] = rows[i].main_sel_op_l1_to_l2_msg_exists; - polys.main_sel_op_l2gasleft[i] = rows[i].main_sel_op_l2gasleft; - polys.main_sel_op_lt[i] = rows[i].main_sel_op_lt; - polys.main_sel_op_lte[i] = rows[i].main_sel_op_lte; - polys.main_sel_op_mov[i] = rows[i].main_sel_op_mov; - polys.main_sel_op_mul[i] = rows[i].main_sel_op_mul; - polys.main_sel_op_not[i] = rows[i].main_sel_op_not; - polys.main_sel_op_note_hash_exists[i] = rows[i].main_sel_op_note_hash_exists; - polys.main_sel_op_nullifier_exists[i] = rows[i].main_sel_op_nullifier_exists; - polys.main_sel_op_or[i] = rows[i].main_sel_op_or; - polys.main_sel_op_pedersen[i] = rows[i].main_sel_op_pedersen; - polys.main_sel_op_poseidon2[i] = rows[i].main_sel_op_poseidon2; - polys.main_sel_op_radix_le[i] = rows[i].main_sel_op_radix_le; - polys.main_sel_op_sender[i] = rows[i].main_sel_op_sender; - polys.main_sel_op_sha256[i] = rows[i].main_sel_op_sha256; - polys.main_sel_op_shl[i] = rows[i].main_sel_op_shl; - polys.main_sel_op_shr[i] = rows[i].main_sel_op_shr; - polys.main_sel_op_sload[i] = rows[i].main_sel_op_sload; - polys.main_sel_op_sstore[i] = rows[i].main_sel_op_sstore; - polys.main_sel_op_storage_address[i] = rows[i].main_sel_op_storage_address; - polys.main_sel_op_sub[i] = rows[i].main_sel_op_sub; - polys.main_sel_op_timestamp[i] = rows[i].main_sel_op_timestamp; - polys.main_sel_op_transaction_fee[i] = rows[i].main_sel_op_transaction_fee; - polys.main_sel_op_version[i] = rows[i].main_sel_op_version; - polys.main_sel_op_xor[i] = rows[i].main_sel_op_xor; - polys.main_sel_q_kernel_lookup[i] = rows[i].main_sel_q_kernel_lookup; - polys.main_sel_q_kernel_output_lookup[i] = rows[i].main_sel_q_kernel_output_lookup; - polys.main_sel_resolve_ind_addr_a[i] = rows[i].main_sel_resolve_ind_addr_a; - polys.main_sel_resolve_ind_addr_b[i] = rows[i].main_sel_resolve_ind_addr_b; - polys.main_sel_resolve_ind_addr_c[i] = rows[i].main_sel_resolve_ind_addr_c; - polys.main_sel_resolve_ind_addr_d[i] = rows[i].main_sel_resolve_ind_addr_d; - polys.main_sel_returndata[i] = rows[i].main_sel_returndata; - polys.main_sel_rng_16[i] = rows[i].main_sel_rng_16; - polys.main_sel_rng_8[i] = rows[i].main_sel_rng_8; - polys.main_sel_slice_gadget[i] = rows[i].main_sel_slice_gadget; - polys.main_space_id[i] = rows[i].main_space_id; - polys.main_tag_err[i] = rows[i].main_tag_err; - polys.main_w_in_tag[i] = rows[i].main_w_in_tag; - polys.mem_addr[i] = rows[i].mem_addr; - polys.mem_clk[i] = rows[i].mem_clk; - polys.mem_diff_hi[i] = rows[i].mem_diff_hi; - polys.mem_diff_lo[i] = rows[i].mem_diff_lo; - polys.mem_diff_mid[i] = rows[i].mem_diff_mid; - polys.mem_glob_addr[i] = rows[i].mem_glob_addr; - polys.mem_last[i] = rows[i].mem_last; - polys.mem_lastAccess[i] = rows[i].mem_lastAccess; - polys.mem_one_min_inv[i] = rows[i].mem_one_min_inv; - polys.mem_r_in_tag[i] = rows[i].mem_r_in_tag; - polys.mem_rw[i] = rows[i].mem_rw; - polys.mem_sel_mem[i] = rows[i].mem_sel_mem; - polys.mem_sel_mov_ia_to_ic[i] = rows[i].mem_sel_mov_ia_to_ic; - polys.mem_sel_mov_ib_to_ic[i] = rows[i].mem_sel_mov_ib_to_ic; - polys.mem_sel_op_a[i] = rows[i].mem_sel_op_a; - polys.mem_sel_op_b[i] = rows[i].mem_sel_op_b; - polys.mem_sel_op_c[i] = rows[i].mem_sel_op_c; - polys.mem_sel_op_cmov[i] = rows[i].mem_sel_op_cmov; - polys.mem_sel_op_d[i] = rows[i].mem_sel_op_d; - polys.mem_sel_op_slice[i] = rows[i].mem_sel_op_slice; - polys.mem_sel_resolve_ind_addr_a[i] = rows[i].mem_sel_resolve_ind_addr_a; - polys.mem_sel_resolve_ind_addr_b[i] = rows[i].mem_sel_resolve_ind_addr_b; - polys.mem_sel_resolve_ind_addr_c[i] = rows[i].mem_sel_resolve_ind_addr_c; - polys.mem_sel_resolve_ind_addr_d[i] = rows[i].mem_sel_resolve_ind_addr_d; - polys.mem_sel_rng_chk[i] = rows[i].mem_sel_rng_chk; - polys.mem_skip_check_tag[i] = rows[i].mem_skip_check_tag; - polys.mem_space_id[i] = rows[i].mem_space_id; - polys.mem_tag[i] = rows[i].mem_tag; - polys.mem_tag_err[i] = rows[i].mem_tag_err; - polys.mem_tsp[i] = rows[i].mem_tsp; - polys.mem_val[i] = rows[i].mem_val; - polys.mem_w_in_tag[i] = rows[i].mem_w_in_tag; - polys.pedersen_clk[i] = rows[i].pedersen_clk; - polys.pedersen_input[i] = rows[i].pedersen_input; - polys.pedersen_output[i] = rows[i].pedersen_output; - polys.pedersen_sel_pedersen[i] = rows[i].pedersen_sel_pedersen; - polys.poseidon2_clk[i] = rows[i].poseidon2_clk; - polys.poseidon2_input[i] = rows[i].poseidon2_input; - polys.poseidon2_output[i] = rows[i].poseidon2_output; - polys.poseidon2_sel_poseidon_perm[i] = rows[i].poseidon2_sel_poseidon_perm; - polys.powers_power_of_2[i] = rows[i].powers_power_of_2; - polys.sha256_clk[i] = rows[i].sha256_clk; - polys.sha256_input[i] = rows[i].sha256_input; - polys.sha256_output[i] = rows[i].sha256_output; - polys.sha256_sel_sha256_compression[i] = rows[i].sha256_sel_sha256_compression; - polys.sha256_state[i] = rows[i].sha256_state; - polys.slice_addr[i] = rows[i].slice_addr; - polys.slice_clk[i] = rows[i].slice_clk; - polys.slice_cnt[i] = rows[i].slice_cnt; - polys.slice_col_offset[i] = rows[i].slice_col_offset; - polys.slice_one_min_inv[i] = rows[i].slice_one_min_inv; - polys.slice_sel_cd_cpy[i] = rows[i].slice_sel_cd_cpy; - polys.slice_sel_mem_active[i] = rows[i].slice_sel_mem_active; - polys.slice_sel_return[i] = rows[i].slice_sel_return; - polys.slice_sel_start[i] = rows[i].slice_sel_start; - polys.slice_space_id[i] = rows[i].slice_space_id; - polys.slice_val[i] = rows[i].slice_val; - polys.lookup_byte_lengths_counts[i] = rows[i].lookup_byte_lengths_counts; - polys.lookup_byte_operations_counts[i] = rows[i].lookup_byte_operations_counts; - polys.lookup_cd_value_counts[i] = rows[i].lookup_cd_value_counts; - polys.lookup_ret_value_counts[i] = rows[i].lookup_ret_value_counts; - polys.lookup_opcode_gas_counts[i] = rows[i].lookup_opcode_gas_counts; - polys.range_check_l2_gas_hi_counts[i] = rows[i].range_check_l2_gas_hi_counts; - polys.range_check_l2_gas_lo_counts[i] = rows[i].range_check_l2_gas_lo_counts; - polys.range_check_da_gas_hi_counts[i] = rows[i].range_check_da_gas_hi_counts; - polys.range_check_da_gas_lo_counts[i] = rows[i].range_check_da_gas_lo_counts; - polys.kernel_output_lookup_counts[i] = rows[i].kernel_output_lookup_counts; - polys.lookup_into_kernel_counts[i] = rows[i].lookup_into_kernel_counts; - polys.incl_main_tag_err_counts[i] = rows[i].incl_main_tag_err_counts; - polys.incl_mem_tag_err_counts[i] = rows[i].incl_mem_tag_err_counts; - polys.lookup_mem_rng_chk_lo_counts[i] = rows[i].lookup_mem_rng_chk_lo_counts; - polys.lookup_mem_rng_chk_mid_counts[i] = rows[i].lookup_mem_rng_chk_mid_counts; - polys.lookup_mem_rng_chk_hi_counts[i] = rows[i].lookup_mem_rng_chk_hi_counts; - polys.lookup_pow_2_0_counts[i] = rows[i].lookup_pow_2_0_counts; - polys.lookup_pow_2_1_counts[i] = rows[i].lookup_pow_2_1_counts; - polys.lookup_u8_0_counts[i] = rows[i].lookup_u8_0_counts; - polys.lookup_u8_1_counts[i] = rows[i].lookup_u8_1_counts; - polys.lookup_u16_0_counts[i] = rows[i].lookup_u16_0_counts; - polys.lookup_u16_1_counts[i] = rows[i].lookup_u16_1_counts; - polys.lookup_u16_2_counts[i] = rows[i].lookup_u16_2_counts; - polys.lookup_u16_3_counts[i] = rows[i].lookup_u16_3_counts; - polys.lookup_u16_4_counts[i] = rows[i].lookup_u16_4_counts; - polys.lookup_u16_5_counts[i] = rows[i].lookup_u16_5_counts; - polys.lookup_u16_6_counts[i] = rows[i].lookup_u16_6_counts; - polys.lookup_u16_7_counts[i] = rows[i].lookup_u16_7_counts; - polys.lookup_u16_8_counts[i] = rows[i].lookup_u16_8_counts; - polys.lookup_u16_9_counts[i] = rows[i].lookup_u16_9_counts; - polys.lookup_u16_10_counts[i] = rows[i].lookup_u16_10_counts; - polys.lookup_u16_11_counts[i] = rows[i].lookup_u16_11_counts; - polys.lookup_u16_12_counts[i] = rows[i].lookup_u16_12_counts; - polys.lookup_u16_13_counts[i] = rows[i].lookup_u16_13_counts; - polys.lookup_u16_14_counts[i] = rows[i].lookup_u16_14_counts; - polys.lookup_div_u16_0_counts[i] = rows[i].lookup_div_u16_0_counts; - polys.lookup_div_u16_1_counts[i] = rows[i].lookup_div_u16_1_counts; - polys.lookup_div_u16_2_counts[i] = rows[i].lookup_div_u16_2_counts; - polys.lookup_div_u16_3_counts[i] = rows[i].lookup_div_u16_3_counts; - polys.lookup_div_u16_4_counts[i] = rows[i].lookup_div_u16_4_counts; - polys.lookup_div_u16_5_counts[i] = rows[i].lookup_div_u16_5_counts; - polys.lookup_div_u16_6_counts[i] = rows[i].lookup_div_u16_6_counts; - polys.lookup_div_u16_7_counts[i] = rows[i].lookup_div_u16_7_counts; - } - - for (auto [shifted, to_be_shifted] : zip_view(polys.get_shifted(), polys.get_to_be_shifted())) { - shifted = to_be_shifted.shifted(); - } - - return polys; - } - - [[maybe_unused]] bool check_circuit() - { - const FF gamma = FF::random_element(); - const FF beta = FF::random_element(); - bb::RelationParameters params{ - .eta = 0, - .beta = beta, - .gamma = gamma, - .public_input_delta = 0, - .lookup_grand_product_delta = 0, - .beta_sqr = 0, - .beta_cube = 0, - .eccvm_set_permutation_delta = 0, - }; - - auto polys = compute_polynomials(); - const size_t num_rows = polys.get_polynomial_size(); + ProverPolynomials compute_polynomials() const; - // Checks that we will run. - using SignalErrorFn = const std::function&; - std::vector> checks; - - // Add relation checks. - bb::constexpr_for<0, std::tuple_size_v, 1>([&]() { - using Relation = std::tuple_element_t; - checks.push_back([&](SignalErrorFn signal_error) { - typename Relation::SumcheckArrayOfValuesOverSubrelations result; - for (auto& r : result) { - r = 0; - } - constexpr size_t NUM_SUBRELATIONS = result.size(); - - for (size_t r = 0; r < num_rows; ++r) { - Relation::accumulate(result, polys.get_row(r), {}, 1); - for (size_t j = 0; j < NUM_SUBRELATIONS; ++j) { - if (result[j] != 0) { - signal_error(format("Relation ", - Relation::NAME, - ", subrelation ", - Relation::get_subrelation_label(j), - " failed at row ", - r)); - } - } - } - }); - }); - - // Add calculation of logderivatives and lookup/permutation checks. - bb::constexpr_for<0, std::tuple_size_v, 1>([&]() { - using Relation = std::tuple_element_t; - checks.push_back([&, num_rows](SignalErrorFn signal_error) { - // Check the logderivative relation - bb::compute_logderivative_inverse(polys, params, num_rows); - - typename Relation::SumcheckArrayOfValuesOverSubrelations lookup_result; - - for (auto& r : lookup_result) { - r = 0; - } - for (size_t r = 0; r < num_rows; ++r) { - Relation::accumulate(lookup_result, polys.get_row(r), params, 1); - } - for (auto r : lookup_result) { - if (r != 0) { - signal_error(format("Lookup ", Relation::NAME, " failed.")); - } - } - }); - }); - - std::string errors; - auto signal_error = [&](const std::string& error) { - // Thread safety first! - static std::mutex m; - std::lock_guard lock(m); - errors += error + "\n"; - }; - bb::parallel_for(checks.size(), [&](size_t i) { checks[i](signal_error); }); - if (!errors.empty()) { - throw_or_abort(errors); - } - - return errors.empty(); - } + bool check_circuit() const; - [[nodiscard]] size_t get_num_gates() const { return rows.size(); } + size_t get_num_gates() const { return rows.size(); } - [[nodiscard]] size_t get_circuit_subgroup_size() const + size_t get_circuit_subgroup_size() const { const size_t num_rows = get_num_gates(); const auto num_rows_log2 = static_cast(numeric::get_msb64(num_rows)); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_composer.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_composer.cpp index e0086cfeab0..3694d429693 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_composer.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_composer.cpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #include "barretenberg/vm/generated/avm_composer.hpp" #include "barretenberg/plonk_honk_shared/composer/composer_lib.hpp" diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_composer.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_composer.hpp index 796e85f346c..bf1e0f381b0 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_composer.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/plonk_honk_shared/composer/composer_lib.hpp" diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.cpp new file mode 100644 index 00000000000..59874f2bca6 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.cpp @@ -0,0 +1,1471 @@ +// AUTOGENERATED FILE +#include "barretenberg/vm/generated/avm_flavor.hpp" + +namespace bb { + +AvmFlavor::AllConstRefValues::AllConstRefValues(const RefArray& il) + : main_clk(il[0]) + , main_sel_first(il[1]) + , kernel_kernel_inputs(il[2]) + , kernel_kernel_value_out(il[3]) + , kernel_kernel_side_effect_out(il[4]) + , kernel_kernel_metadata_out(il[5]) + , main_calldata(il[6]) + , main_returndata(il[7]) + , alu_a_hi(il[8]) + , alu_a_lo(il[9]) + , alu_b_hi(il[10]) + , alu_b_lo(il[11]) + , alu_borrow(il[12]) + , alu_cf(il[13]) + , alu_clk(il[14]) + , alu_cmp_rng_ctr(il[15]) + , alu_div_u16_r0(il[16]) + , alu_div_u16_r1(il[17]) + , alu_div_u16_r2(il[18]) + , alu_div_u16_r3(il[19]) + , alu_div_u16_r4(il[20]) + , alu_div_u16_r5(il[21]) + , alu_div_u16_r6(il[22]) + , alu_div_u16_r7(il[23]) + , alu_divisor_hi(il[24]) + , alu_divisor_lo(il[25]) + , alu_ff_tag(il[26]) + , alu_ia(il[27]) + , alu_ib(il[28]) + , alu_ic(il[29]) + , alu_in_tag(il[30]) + , alu_op_add(il[31]) + , alu_op_cast(il[32]) + , alu_op_cast_prev(il[33]) + , alu_op_div(il[34]) + , alu_op_div_a_lt_b(il[35]) + , alu_op_div_std(il[36]) + , alu_op_eq(il[37]) + , alu_op_eq_diff_inv(il[38]) + , alu_op_lt(il[39]) + , alu_op_lte(il[40]) + , alu_op_mul(il[41]) + , alu_op_not(il[42]) + , alu_op_shl(il[43]) + , alu_op_shr(il[44]) + , alu_op_sub(il[45]) + , alu_p_a_borrow(il[46]) + , alu_p_b_borrow(il[47]) + , alu_p_sub_a_hi(il[48]) + , alu_p_sub_a_lo(il[49]) + , alu_p_sub_b_hi(il[50]) + , alu_p_sub_b_lo(il[51]) + , alu_partial_prod_hi(il[52]) + , alu_partial_prod_lo(il[53]) + , alu_quotient_hi(il[54]) + , alu_quotient_lo(il[55]) + , alu_remainder(il[56]) + , alu_res_hi(il[57]) + , alu_res_lo(il[58]) + , alu_sel_alu(il[59]) + , alu_sel_cmp(il[60]) + , alu_sel_div_rng_chk(il[61]) + , alu_sel_rng_chk(il[62]) + , alu_sel_rng_chk_lookup(il[63]) + , alu_sel_shift_which(il[64]) + , alu_shift_lt_bit_len(il[65]) + , alu_t_sub_s_bits(il[66]) + , alu_two_pow_s(il[67]) + , alu_two_pow_t_sub_s(il[68]) + , alu_u128_tag(il[69]) + , alu_u16_r0(il[70]) + , alu_u16_r1(il[71]) + , alu_u16_r10(il[72]) + , alu_u16_r11(il[73]) + , alu_u16_r12(il[74]) + , alu_u16_r13(il[75]) + , alu_u16_r14(il[76]) + , alu_u16_r2(il[77]) + , alu_u16_r3(il[78]) + , alu_u16_r4(il[79]) + , alu_u16_r5(il[80]) + , alu_u16_r6(il[81]) + , alu_u16_r7(il[82]) + , alu_u16_r8(il[83]) + , alu_u16_r9(il[84]) + , alu_u16_tag(il[85]) + , alu_u32_tag(il[86]) + , alu_u64_tag(il[87]) + , alu_u8_r0(il[88]) + , alu_u8_r1(il[89]) + , alu_u8_tag(il[90]) + , binary_acc_ia(il[91]) + , binary_acc_ib(il[92]) + , binary_acc_ic(il[93]) + , binary_clk(il[94]) + , binary_ia_bytes(il[95]) + , binary_ib_bytes(il[96]) + , binary_ic_bytes(il[97]) + , binary_in_tag(il[98]) + , binary_mem_tag_ctr(il[99]) + , binary_mem_tag_ctr_inv(il[100]) + , binary_op_id(il[101]) + , binary_sel_bin(il[102]) + , binary_start(il[103]) + , byte_lookup_sel_bin(il[104]) + , byte_lookup_table_byte_lengths(il[105]) + , byte_lookup_table_in_tags(il[106]) + , byte_lookup_table_input_a(il[107]) + , byte_lookup_table_input_b(il[108]) + , byte_lookup_table_op_id(il[109]) + , byte_lookup_table_output(il[110]) + , conversion_clk(il[111]) + , conversion_input(il[112]) + , conversion_num_limbs(il[113]) + , conversion_radix(il[114]) + , conversion_sel_to_radix_le(il[115]) + , gas_da_gas_fixed_table(il[116]) + , gas_l2_gas_fixed_table(il[117]) + , gas_sel_gas_cost(il[118]) + , keccakf1600_clk(il[119]) + , keccakf1600_input(il[120]) + , keccakf1600_output(il[121]) + , keccakf1600_sel_keccakf1600(il[122]) + , kernel_emit_l2_to_l1_msg_write_offset(il[123]) + , kernel_emit_note_hash_write_offset(il[124]) + , kernel_emit_nullifier_write_offset(il[125]) + , kernel_emit_unencrypted_log_write_offset(il[126]) + , kernel_kernel_in_offset(il[127]) + , kernel_kernel_out_offset(il[128]) + , kernel_l1_to_l2_msg_exists_write_offset(il[129]) + , kernel_note_hash_exist_write_offset(il[130]) + , kernel_nullifier_exists_write_offset(il[131]) + , kernel_nullifier_non_exists_write_offset(il[132]) + , kernel_q_public_input_kernel_add_to_table(il[133]) + , kernel_q_public_input_kernel_out_add_to_table(il[134]) + , kernel_side_effect_counter(il[135]) + , kernel_sload_write_offset(il[136]) + , kernel_sstore_write_offset(il[137]) + , main_abs_da_rem_gas_hi(il[138]) + , main_abs_da_rem_gas_lo(il[139]) + , main_abs_l2_rem_gas_hi(il[140]) + , main_abs_l2_rem_gas_lo(il[141]) + , main_alu_in_tag(il[142]) + , main_bin_op_id(il[143]) + , main_call_ptr(il[144]) + , main_da_gas_op_cost(il[145]) + , main_da_gas_remaining(il[146]) + , main_da_out_of_gas(il[147]) + , main_ia(il[148]) + , main_ib(il[149]) + , main_ic(il[150]) + , main_id(il[151]) + , main_id_zero(il[152]) + , main_ind_addr_a(il[153]) + , main_ind_addr_b(il[154]) + , main_ind_addr_c(il[155]) + , main_ind_addr_d(il[156]) + , main_internal_return_ptr(il[157]) + , main_inv(il[158]) + , main_l2_gas_op_cost(il[159]) + , main_l2_gas_remaining(il[160]) + , main_l2_out_of_gas(il[161]) + , main_mem_addr_a(il[162]) + , main_mem_addr_b(il[163]) + , main_mem_addr_c(il[164]) + , main_mem_addr_d(il[165]) + , main_op_err(il[166]) + , main_opcode_val(il[167]) + , main_pc(il[168]) + , main_r_in_tag(il[169]) + , main_rwa(il[170]) + , main_rwb(il[171]) + , main_rwc(il[172]) + , main_rwd(il[173]) + , main_sel_alu(il[174]) + , main_sel_bin(il[175]) + , main_sel_calldata(il[176]) + , main_sel_gas_accounting_active(il[177]) + , main_sel_last(il[178]) + , main_sel_mem_op_a(il[179]) + , main_sel_mem_op_activate_gas(il[180]) + , main_sel_mem_op_b(il[181]) + , main_sel_mem_op_c(il[182]) + , main_sel_mem_op_d(il[183]) + , main_sel_mov_ia_to_ic(il[184]) + , main_sel_mov_ib_to_ic(il[185]) + , main_sel_op_add(il[186]) + , main_sel_op_address(il[187]) + , main_sel_op_and(il[188]) + , main_sel_op_block_number(il[189]) + , main_sel_op_calldata_copy(il[190]) + , main_sel_op_cast(il[191]) + , main_sel_op_chain_id(il[192]) + , main_sel_op_cmov(il[193]) + , main_sel_op_coinbase(il[194]) + , main_sel_op_dagasleft(il[195]) + , main_sel_op_div(il[196]) + , main_sel_op_emit_l2_to_l1_msg(il[197]) + , main_sel_op_emit_note_hash(il[198]) + , main_sel_op_emit_nullifier(il[199]) + , main_sel_op_emit_unencrypted_log(il[200]) + , main_sel_op_eq(il[201]) + , main_sel_op_external_call(il[202]) + , main_sel_op_external_return(il[203]) + , main_sel_op_fdiv(il[204]) + , main_sel_op_fee_per_da_gas(il[205]) + , main_sel_op_fee_per_l2_gas(il[206]) + , main_sel_op_function_selector(il[207]) + , main_sel_op_get_contract_instance(il[208]) + , main_sel_op_halt(il[209]) + , main_sel_op_internal_call(il[210]) + , main_sel_op_internal_return(il[211]) + , main_sel_op_jump(il[212]) + , main_sel_op_jumpi(il[213]) + , main_sel_op_keccak(il[214]) + , main_sel_op_l1_to_l2_msg_exists(il[215]) + , main_sel_op_l2gasleft(il[216]) + , main_sel_op_lt(il[217]) + , main_sel_op_lte(il[218]) + , main_sel_op_mov(il[219]) + , main_sel_op_mul(il[220]) + , main_sel_op_not(il[221]) + , main_sel_op_note_hash_exists(il[222]) + , main_sel_op_nullifier_exists(il[223]) + , main_sel_op_or(il[224]) + , main_sel_op_pedersen(il[225]) + , main_sel_op_poseidon2(il[226]) + , main_sel_op_radix_le(il[227]) + , main_sel_op_sender(il[228]) + , main_sel_op_sha256(il[229]) + , main_sel_op_shl(il[230]) + , main_sel_op_shr(il[231]) + , main_sel_op_sload(il[232]) + , main_sel_op_sstore(il[233]) + , main_sel_op_storage_address(il[234]) + , main_sel_op_sub(il[235]) + , main_sel_op_timestamp(il[236]) + , main_sel_op_transaction_fee(il[237]) + , main_sel_op_version(il[238]) + , main_sel_op_xor(il[239]) + , main_sel_q_kernel_lookup(il[240]) + , main_sel_q_kernel_output_lookup(il[241]) + , main_sel_resolve_ind_addr_a(il[242]) + , main_sel_resolve_ind_addr_b(il[243]) + , main_sel_resolve_ind_addr_c(il[244]) + , main_sel_resolve_ind_addr_d(il[245]) + , main_sel_returndata(il[246]) + , main_sel_rng_16(il[247]) + , main_sel_rng_8(il[248]) + , main_sel_slice_gadget(il[249]) + , main_space_id(il[250]) + , main_tag_err(il[251]) + , main_w_in_tag(il[252]) + , mem_addr(il[253]) + , mem_clk(il[254]) + , mem_diff_hi(il[255]) + , mem_diff_lo(il[256]) + , mem_diff_mid(il[257]) + , mem_glob_addr(il[258]) + , mem_last(il[259]) + , mem_lastAccess(il[260]) + , mem_one_min_inv(il[261]) + , mem_r_in_tag(il[262]) + , mem_rw(il[263]) + , mem_sel_mem(il[264]) + , mem_sel_mov_ia_to_ic(il[265]) + , mem_sel_mov_ib_to_ic(il[266]) + , mem_sel_op_a(il[267]) + , mem_sel_op_b(il[268]) + , mem_sel_op_c(il[269]) + , mem_sel_op_cmov(il[270]) + , mem_sel_op_d(il[271]) + , mem_sel_op_slice(il[272]) + , mem_sel_resolve_ind_addr_a(il[273]) + , mem_sel_resolve_ind_addr_b(il[274]) + , mem_sel_resolve_ind_addr_c(il[275]) + , mem_sel_resolve_ind_addr_d(il[276]) + , mem_sel_rng_chk(il[277]) + , mem_skip_check_tag(il[278]) + , mem_space_id(il[279]) + , mem_tag(il[280]) + , mem_tag_err(il[281]) + , mem_tsp(il[282]) + , mem_val(il[283]) + , mem_w_in_tag(il[284]) + , pedersen_clk(il[285]) + , pedersen_input(il[286]) + , pedersen_output(il[287]) + , pedersen_sel_pedersen(il[288]) + , poseidon2_clk(il[289]) + , poseidon2_input(il[290]) + , poseidon2_output(il[291]) + , poseidon2_sel_poseidon_perm(il[292]) + , powers_power_of_2(il[293]) + , sha256_clk(il[294]) + , sha256_input(il[295]) + , sha256_output(il[296]) + , sha256_sel_sha256_compression(il[297]) + , sha256_state(il[298]) + , slice_addr(il[299]) + , slice_clk(il[300]) + , slice_cnt(il[301]) + , slice_col_offset(il[302]) + , slice_one_min_inv(il[303]) + , slice_sel_cd_cpy(il[304]) + , slice_sel_mem_active(il[305]) + , slice_sel_return(il[306]) + , slice_sel_start(il[307]) + , slice_space_id(il[308]) + , slice_val(il[309]) + , lookup_byte_lengths_counts(il[310]) + , lookup_byte_operations_counts(il[311]) + , lookup_cd_value_counts(il[312]) + , lookup_ret_value_counts(il[313]) + , lookup_opcode_gas_counts(il[314]) + , range_check_l2_gas_hi_counts(il[315]) + , range_check_l2_gas_lo_counts(il[316]) + , range_check_da_gas_hi_counts(il[317]) + , range_check_da_gas_lo_counts(il[318]) + , kernel_output_lookup_counts(il[319]) + , lookup_into_kernel_counts(il[320]) + , incl_main_tag_err_counts(il[321]) + , incl_mem_tag_err_counts(il[322]) + , lookup_mem_rng_chk_lo_counts(il[323]) + , lookup_mem_rng_chk_mid_counts(il[324]) + , lookup_mem_rng_chk_hi_counts(il[325]) + , lookup_pow_2_0_counts(il[326]) + , lookup_pow_2_1_counts(il[327]) + , lookup_u8_0_counts(il[328]) + , lookup_u8_1_counts(il[329]) + , lookup_u16_0_counts(il[330]) + , lookup_u16_1_counts(il[331]) + , lookup_u16_2_counts(il[332]) + , lookup_u16_3_counts(il[333]) + , lookup_u16_4_counts(il[334]) + , lookup_u16_5_counts(il[335]) + , lookup_u16_6_counts(il[336]) + , lookup_u16_7_counts(il[337]) + , lookup_u16_8_counts(il[338]) + , lookup_u16_9_counts(il[339]) + , lookup_u16_10_counts(il[340]) + , lookup_u16_11_counts(il[341]) + , lookup_u16_12_counts(il[342]) + , lookup_u16_13_counts(il[343]) + , lookup_u16_14_counts(il[344]) + , lookup_div_u16_0_counts(il[345]) + , lookup_div_u16_1_counts(il[346]) + , lookup_div_u16_2_counts(il[347]) + , lookup_div_u16_3_counts(il[348]) + , lookup_div_u16_4_counts(il[349]) + , lookup_div_u16_5_counts(il[350]) + , lookup_div_u16_6_counts(il[351]) + , lookup_div_u16_7_counts(il[352]) + , perm_slice_mem(il[353]) + , perm_main_alu(il[354]) + , perm_main_bin(il[355]) + , perm_main_conv(il[356]) + , perm_main_pos2_perm(il[357]) + , perm_main_pedersen(il[358]) + , perm_main_slice(il[359]) + , perm_main_mem_a(il[360]) + , perm_main_mem_b(il[361]) + , perm_main_mem_c(il[362]) + , perm_main_mem_d(il[363]) + , perm_main_mem_ind_addr_a(il[364]) + , perm_main_mem_ind_addr_b(il[365]) + , perm_main_mem_ind_addr_c(il[366]) + , perm_main_mem_ind_addr_d(il[367]) + , lookup_byte_lengths(il[368]) + , lookup_byte_operations(il[369]) + , lookup_cd_value(il[370]) + , lookup_ret_value(il[371]) + , lookup_opcode_gas(il[372]) + , range_check_l2_gas_hi(il[373]) + , range_check_l2_gas_lo(il[374]) + , range_check_da_gas_hi(il[375]) + , range_check_da_gas_lo(il[376]) + , kernel_output_lookup(il[377]) + , lookup_into_kernel(il[378]) + , incl_main_tag_err(il[379]) + , incl_mem_tag_err(il[380]) + , lookup_mem_rng_chk_lo(il[381]) + , lookup_mem_rng_chk_mid(il[382]) + , lookup_mem_rng_chk_hi(il[383]) + , lookup_pow_2_0(il[384]) + , lookup_pow_2_1(il[385]) + , lookup_u8_0(il[386]) + , lookup_u8_1(il[387]) + , lookup_u16_0(il[388]) + , lookup_u16_1(il[389]) + , lookup_u16_2(il[390]) + , lookup_u16_3(il[391]) + , lookup_u16_4(il[392]) + , lookup_u16_5(il[393]) + , lookup_u16_6(il[394]) + , lookup_u16_7(il[395]) + , lookup_u16_8(il[396]) + , lookup_u16_9(il[397]) + , lookup_u16_10(il[398]) + , lookup_u16_11(il[399]) + , lookup_u16_12(il[400]) + , lookup_u16_13(il[401]) + , lookup_u16_14(il[402]) + , lookup_div_u16_0(il[403]) + , lookup_div_u16_1(il[404]) + , lookup_div_u16_2(il[405]) + , lookup_div_u16_3(il[406]) + , lookup_div_u16_4(il[407]) + , lookup_div_u16_5(il[408]) + , lookup_div_u16_6(il[409]) + , lookup_div_u16_7(il[410]) + , alu_a_hi_shift(il[411]) + , alu_a_lo_shift(il[412]) + , alu_b_hi_shift(il[413]) + , alu_b_lo_shift(il[414]) + , alu_cmp_rng_ctr_shift(il[415]) + , alu_div_u16_r0_shift(il[416]) + , alu_div_u16_r1_shift(il[417]) + , alu_div_u16_r2_shift(il[418]) + , alu_div_u16_r3_shift(il[419]) + , alu_div_u16_r4_shift(il[420]) + , alu_div_u16_r5_shift(il[421]) + , alu_div_u16_r6_shift(il[422]) + , alu_div_u16_r7_shift(il[423]) + , alu_op_add_shift(il[424]) + , alu_op_cast_prev_shift(il[425]) + , alu_op_cast_shift(il[426]) + , alu_op_div_shift(il[427]) + , alu_op_mul_shift(il[428]) + , alu_op_shl_shift(il[429]) + , alu_op_shr_shift(il[430]) + , alu_op_sub_shift(il[431]) + , alu_p_sub_a_hi_shift(il[432]) + , alu_p_sub_a_lo_shift(il[433]) + , alu_p_sub_b_hi_shift(il[434]) + , alu_p_sub_b_lo_shift(il[435]) + , alu_sel_alu_shift(il[436]) + , alu_sel_cmp_shift(il[437]) + , alu_sel_div_rng_chk_shift(il[438]) + , alu_sel_rng_chk_lookup_shift(il[439]) + , alu_sel_rng_chk_shift(il[440]) + , alu_u16_r0_shift(il[441]) + , alu_u16_r1_shift(il[442]) + , alu_u16_r2_shift(il[443]) + , alu_u16_r3_shift(il[444]) + , alu_u16_r4_shift(il[445]) + , alu_u16_r5_shift(il[446]) + , alu_u16_r6_shift(il[447]) + , alu_u8_r0_shift(il[448]) + , alu_u8_r1_shift(il[449]) + , binary_acc_ia_shift(il[450]) + , binary_acc_ib_shift(il[451]) + , binary_acc_ic_shift(il[452]) + , binary_mem_tag_ctr_shift(il[453]) + , binary_op_id_shift(il[454]) + , kernel_emit_l2_to_l1_msg_write_offset_shift(il[455]) + , kernel_emit_note_hash_write_offset_shift(il[456]) + , kernel_emit_nullifier_write_offset_shift(il[457]) + , kernel_emit_unencrypted_log_write_offset_shift(il[458]) + , kernel_l1_to_l2_msg_exists_write_offset_shift(il[459]) + , kernel_note_hash_exist_write_offset_shift(il[460]) + , kernel_nullifier_exists_write_offset_shift(il[461]) + , kernel_nullifier_non_exists_write_offset_shift(il[462]) + , kernel_side_effect_counter_shift(il[463]) + , kernel_sload_write_offset_shift(il[464]) + , kernel_sstore_write_offset_shift(il[465]) + , main_da_gas_remaining_shift(il[466]) + , main_internal_return_ptr_shift(il[467]) + , main_l2_gas_remaining_shift(il[468]) + , main_pc_shift(il[469]) + , mem_glob_addr_shift(il[470]) + , mem_rw_shift(il[471]) + , mem_sel_mem_shift(il[472]) + , mem_tag_shift(il[473]) + , mem_tsp_shift(il[474]) + , mem_val_shift(il[475]) + , slice_addr_shift(il[476]) + , slice_clk_shift(il[477]) + , slice_cnt_shift(il[478]) + , slice_col_offset_shift(il[479]) + , slice_sel_cd_cpy_shift(il[480]) + , slice_sel_mem_active_shift(il[481]) + , slice_sel_return_shift(il[482]) + , slice_sel_start_shift(il[483]) + , slice_space_id_shift(il[484]) +{} + +AvmFlavor::ProverPolynomials::ProverPolynomials(ProvingKey& proving_key) +{ + for (auto [prover_poly, key_poly] : zip_view(this->get_unshifted(), proving_key.get_all())) { + ASSERT(flavor_get_label(*this, prover_poly) == flavor_get_label(proving_key, key_poly)); + prover_poly = key_poly.share(); + } + for (auto [prover_poly, key_poly] : zip_view(this->get_shifted(), proving_key.get_to_be_shifted())) { + ASSERT(flavor_get_label(*this, prover_poly) == (flavor_get_label(proving_key, key_poly) + "_shift")); + prover_poly = key_poly.shifted(); + } +} + +AvmFlavor::AllConstRefValues AvmFlavor::ProverPolynomials::get_row(size_t row_idx) const +{ + return AllConstRefValues(RefArray{ main_clk[row_idx], + main_sel_first[row_idx], + kernel_kernel_inputs[row_idx], + kernel_kernel_value_out[row_idx], + kernel_kernel_side_effect_out[row_idx], + kernel_kernel_metadata_out[row_idx], + main_calldata[row_idx], + main_returndata[row_idx], + alu_a_hi[row_idx], + alu_a_lo[row_idx], + alu_b_hi[row_idx], + alu_b_lo[row_idx], + alu_borrow[row_idx], + alu_cf[row_idx], + alu_clk[row_idx], + alu_cmp_rng_ctr[row_idx], + alu_div_u16_r0[row_idx], + alu_div_u16_r1[row_idx], + alu_div_u16_r2[row_idx], + alu_div_u16_r3[row_idx], + alu_div_u16_r4[row_idx], + alu_div_u16_r5[row_idx], + alu_div_u16_r6[row_idx], + alu_div_u16_r7[row_idx], + alu_divisor_hi[row_idx], + alu_divisor_lo[row_idx], + alu_ff_tag[row_idx], + alu_ia[row_idx], + alu_ib[row_idx], + alu_ic[row_idx], + alu_in_tag[row_idx], + alu_op_add[row_idx], + alu_op_cast[row_idx], + alu_op_cast_prev[row_idx], + alu_op_div[row_idx], + alu_op_div_a_lt_b[row_idx], + alu_op_div_std[row_idx], + alu_op_eq[row_idx], + alu_op_eq_diff_inv[row_idx], + alu_op_lt[row_idx], + alu_op_lte[row_idx], + alu_op_mul[row_idx], + alu_op_not[row_idx], + alu_op_shl[row_idx], + alu_op_shr[row_idx], + alu_op_sub[row_idx], + alu_p_a_borrow[row_idx], + alu_p_b_borrow[row_idx], + alu_p_sub_a_hi[row_idx], + alu_p_sub_a_lo[row_idx], + alu_p_sub_b_hi[row_idx], + alu_p_sub_b_lo[row_idx], + alu_partial_prod_hi[row_idx], + alu_partial_prod_lo[row_idx], + alu_quotient_hi[row_idx], + alu_quotient_lo[row_idx], + alu_remainder[row_idx], + alu_res_hi[row_idx], + alu_res_lo[row_idx], + alu_sel_alu[row_idx], + alu_sel_cmp[row_idx], + alu_sel_div_rng_chk[row_idx], + alu_sel_rng_chk[row_idx], + alu_sel_rng_chk_lookup[row_idx], + alu_sel_shift_which[row_idx], + alu_shift_lt_bit_len[row_idx], + alu_t_sub_s_bits[row_idx], + alu_two_pow_s[row_idx], + alu_two_pow_t_sub_s[row_idx], + alu_u128_tag[row_idx], + alu_u16_r0[row_idx], + alu_u16_r1[row_idx], + alu_u16_r10[row_idx], + alu_u16_r11[row_idx], + alu_u16_r12[row_idx], + alu_u16_r13[row_idx], + alu_u16_r14[row_idx], + alu_u16_r2[row_idx], + alu_u16_r3[row_idx], + alu_u16_r4[row_idx], + alu_u16_r5[row_idx], + alu_u16_r6[row_idx], + alu_u16_r7[row_idx], + alu_u16_r8[row_idx], + alu_u16_r9[row_idx], + alu_u16_tag[row_idx], + alu_u32_tag[row_idx], + alu_u64_tag[row_idx], + alu_u8_r0[row_idx], + alu_u8_r1[row_idx], + alu_u8_tag[row_idx], + binary_acc_ia[row_idx], + binary_acc_ib[row_idx], + binary_acc_ic[row_idx], + binary_clk[row_idx], + binary_ia_bytes[row_idx], + binary_ib_bytes[row_idx], + binary_ic_bytes[row_idx], + binary_in_tag[row_idx], + binary_mem_tag_ctr[row_idx], + binary_mem_tag_ctr_inv[row_idx], + binary_op_id[row_idx], + binary_sel_bin[row_idx], + binary_start[row_idx], + byte_lookup_sel_bin[row_idx], + byte_lookup_table_byte_lengths[row_idx], + byte_lookup_table_in_tags[row_idx], + byte_lookup_table_input_a[row_idx], + byte_lookup_table_input_b[row_idx], + byte_lookup_table_op_id[row_idx], + byte_lookup_table_output[row_idx], + conversion_clk[row_idx], + conversion_input[row_idx], + conversion_num_limbs[row_idx], + conversion_radix[row_idx], + conversion_sel_to_radix_le[row_idx], + gas_da_gas_fixed_table[row_idx], + gas_l2_gas_fixed_table[row_idx], + gas_sel_gas_cost[row_idx], + keccakf1600_clk[row_idx], + keccakf1600_input[row_idx], + keccakf1600_output[row_idx], + keccakf1600_sel_keccakf1600[row_idx], + kernel_emit_l2_to_l1_msg_write_offset[row_idx], + kernel_emit_note_hash_write_offset[row_idx], + kernel_emit_nullifier_write_offset[row_idx], + kernel_emit_unencrypted_log_write_offset[row_idx], + kernel_kernel_in_offset[row_idx], + kernel_kernel_out_offset[row_idx], + kernel_l1_to_l2_msg_exists_write_offset[row_idx], + kernel_note_hash_exist_write_offset[row_idx], + kernel_nullifier_exists_write_offset[row_idx], + kernel_nullifier_non_exists_write_offset[row_idx], + kernel_q_public_input_kernel_add_to_table[row_idx], + kernel_q_public_input_kernel_out_add_to_table[row_idx], + kernel_side_effect_counter[row_idx], + kernel_sload_write_offset[row_idx], + kernel_sstore_write_offset[row_idx], + main_abs_da_rem_gas_hi[row_idx], + main_abs_da_rem_gas_lo[row_idx], + main_abs_l2_rem_gas_hi[row_idx], + main_abs_l2_rem_gas_lo[row_idx], + main_alu_in_tag[row_idx], + main_bin_op_id[row_idx], + main_call_ptr[row_idx], + main_da_gas_op_cost[row_idx], + main_da_gas_remaining[row_idx], + main_da_out_of_gas[row_idx], + main_ia[row_idx], + main_ib[row_idx], + main_ic[row_idx], + main_id[row_idx], + main_id_zero[row_idx], + main_ind_addr_a[row_idx], + main_ind_addr_b[row_idx], + main_ind_addr_c[row_idx], + main_ind_addr_d[row_idx], + main_internal_return_ptr[row_idx], + main_inv[row_idx], + main_l2_gas_op_cost[row_idx], + main_l2_gas_remaining[row_idx], + main_l2_out_of_gas[row_idx], + main_mem_addr_a[row_idx], + main_mem_addr_b[row_idx], + main_mem_addr_c[row_idx], + main_mem_addr_d[row_idx], + main_op_err[row_idx], + main_opcode_val[row_idx], + main_pc[row_idx], + main_r_in_tag[row_idx], + main_rwa[row_idx], + main_rwb[row_idx], + main_rwc[row_idx], + main_rwd[row_idx], + main_sel_alu[row_idx], + main_sel_bin[row_idx], + main_sel_calldata[row_idx], + main_sel_gas_accounting_active[row_idx], + main_sel_last[row_idx], + main_sel_mem_op_a[row_idx], + main_sel_mem_op_activate_gas[row_idx], + main_sel_mem_op_b[row_idx], + main_sel_mem_op_c[row_idx], + main_sel_mem_op_d[row_idx], + main_sel_mov_ia_to_ic[row_idx], + main_sel_mov_ib_to_ic[row_idx], + main_sel_op_add[row_idx], + main_sel_op_address[row_idx], + main_sel_op_and[row_idx], + main_sel_op_block_number[row_idx], + main_sel_op_calldata_copy[row_idx], + main_sel_op_cast[row_idx], + main_sel_op_chain_id[row_idx], + main_sel_op_cmov[row_idx], + main_sel_op_coinbase[row_idx], + main_sel_op_dagasleft[row_idx], + main_sel_op_div[row_idx], + main_sel_op_emit_l2_to_l1_msg[row_idx], + main_sel_op_emit_note_hash[row_idx], + main_sel_op_emit_nullifier[row_idx], + main_sel_op_emit_unencrypted_log[row_idx], + main_sel_op_eq[row_idx], + main_sel_op_external_call[row_idx], + main_sel_op_external_return[row_idx], + main_sel_op_fdiv[row_idx], + main_sel_op_fee_per_da_gas[row_idx], + main_sel_op_fee_per_l2_gas[row_idx], + main_sel_op_function_selector[row_idx], + main_sel_op_get_contract_instance[row_idx], + main_sel_op_halt[row_idx], + main_sel_op_internal_call[row_idx], + main_sel_op_internal_return[row_idx], + main_sel_op_jump[row_idx], + main_sel_op_jumpi[row_idx], + main_sel_op_keccak[row_idx], + main_sel_op_l1_to_l2_msg_exists[row_idx], + main_sel_op_l2gasleft[row_idx], + main_sel_op_lt[row_idx], + main_sel_op_lte[row_idx], + main_sel_op_mov[row_idx], + main_sel_op_mul[row_idx], + main_sel_op_not[row_idx], + main_sel_op_note_hash_exists[row_idx], + main_sel_op_nullifier_exists[row_idx], + main_sel_op_or[row_idx], + main_sel_op_pedersen[row_idx], + main_sel_op_poseidon2[row_idx], + main_sel_op_radix_le[row_idx], + main_sel_op_sender[row_idx], + main_sel_op_sha256[row_idx], + main_sel_op_shl[row_idx], + main_sel_op_shr[row_idx], + main_sel_op_sload[row_idx], + main_sel_op_sstore[row_idx], + main_sel_op_storage_address[row_idx], + main_sel_op_sub[row_idx], + main_sel_op_timestamp[row_idx], + main_sel_op_transaction_fee[row_idx], + main_sel_op_version[row_idx], + main_sel_op_xor[row_idx], + main_sel_q_kernel_lookup[row_idx], + main_sel_q_kernel_output_lookup[row_idx], + main_sel_resolve_ind_addr_a[row_idx], + main_sel_resolve_ind_addr_b[row_idx], + main_sel_resolve_ind_addr_c[row_idx], + main_sel_resolve_ind_addr_d[row_idx], + main_sel_returndata[row_idx], + main_sel_rng_16[row_idx], + main_sel_rng_8[row_idx], + main_sel_slice_gadget[row_idx], + main_space_id[row_idx], + main_tag_err[row_idx], + main_w_in_tag[row_idx], + mem_addr[row_idx], + mem_clk[row_idx], + mem_diff_hi[row_idx], + mem_diff_lo[row_idx], + mem_diff_mid[row_idx], + mem_glob_addr[row_idx], + mem_last[row_idx], + mem_lastAccess[row_idx], + mem_one_min_inv[row_idx], + mem_r_in_tag[row_idx], + mem_rw[row_idx], + mem_sel_mem[row_idx], + mem_sel_mov_ia_to_ic[row_idx], + mem_sel_mov_ib_to_ic[row_idx], + mem_sel_op_a[row_idx], + mem_sel_op_b[row_idx], + mem_sel_op_c[row_idx], + mem_sel_op_cmov[row_idx], + mem_sel_op_d[row_idx], + mem_sel_op_slice[row_idx], + mem_sel_resolve_ind_addr_a[row_idx], + mem_sel_resolve_ind_addr_b[row_idx], + mem_sel_resolve_ind_addr_c[row_idx], + mem_sel_resolve_ind_addr_d[row_idx], + mem_sel_rng_chk[row_idx], + mem_skip_check_tag[row_idx], + mem_space_id[row_idx], + mem_tag[row_idx], + mem_tag_err[row_idx], + mem_tsp[row_idx], + mem_val[row_idx], + mem_w_in_tag[row_idx], + pedersen_clk[row_idx], + pedersen_input[row_idx], + pedersen_output[row_idx], + pedersen_sel_pedersen[row_idx], + poseidon2_clk[row_idx], + poseidon2_input[row_idx], + poseidon2_output[row_idx], + poseidon2_sel_poseidon_perm[row_idx], + powers_power_of_2[row_idx], + sha256_clk[row_idx], + sha256_input[row_idx], + sha256_output[row_idx], + sha256_sel_sha256_compression[row_idx], + sha256_state[row_idx], + slice_addr[row_idx], + slice_clk[row_idx], + slice_cnt[row_idx], + slice_col_offset[row_idx], + slice_one_min_inv[row_idx], + slice_sel_cd_cpy[row_idx], + slice_sel_mem_active[row_idx], + slice_sel_return[row_idx], + slice_sel_start[row_idx], + slice_space_id[row_idx], + slice_val[row_idx], + lookup_byte_lengths_counts[row_idx], + lookup_byte_operations_counts[row_idx], + lookup_cd_value_counts[row_idx], + lookup_ret_value_counts[row_idx], + lookup_opcode_gas_counts[row_idx], + range_check_l2_gas_hi_counts[row_idx], + range_check_l2_gas_lo_counts[row_idx], + range_check_da_gas_hi_counts[row_idx], + range_check_da_gas_lo_counts[row_idx], + kernel_output_lookup_counts[row_idx], + lookup_into_kernel_counts[row_idx], + incl_main_tag_err_counts[row_idx], + incl_mem_tag_err_counts[row_idx], + lookup_mem_rng_chk_lo_counts[row_idx], + lookup_mem_rng_chk_mid_counts[row_idx], + lookup_mem_rng_chk_hi_counts[row_idx], + lookup_pow_2_0_counts[row_idx], + lookup_pow_2_1_counts[row_idx], + lookup_u8_0_counts[row_idx], + lookup_u8_1_counts[row_idx], + lookup_u16_0_counts[row_idx], + lookup_u16_1_counts[row_idx], + lookup_u16_2_counts[row_idx], + lookup_u16_3_counts[row_idx], + lookup_u16_4_counts[row_idx], + lookup_u16_5_counts[row_idx], + lookup_u16_6_counts[row_idx], + lookup_u16_7_counts[row_idx], + lookup_u16_8_counts[row_idx], + lookup_u16_9_counts[row_idx], + lookup_u16_10_counts[row_idx], + lookup_u16_11_counts[row_idx], + lookup_u16_12_counts[row_idx], + lookup_u16_13_counts[row_idx], + lookup_u16_14_counts[row_idx], + lookup_div_u16_0_counts[row_idx], + lookup_div_u16_1_counts[row_idx], + lookup_div_u16_2_counts[row_idx], + lookup_div_u16_3_counts[row_idx], + lookup_div_u16_4_counts[row_idx], + lookup_div_u16_5_counts[row_idx], + lookup_div_u16_6_counts[row_idx], + lookup_div_u16_7_counts[row_idx], + perm_slice_mem[row_idx], + perm_main_alu[row_idx], + perm_main_bin[row_idx], + perm_main_conv[row_idx], + perm_main_pos2_perm[row_idx], + perm_main_pedersen[row_idx], + perm_main_slice[row_idx], + perm_main_mem_a[row_idx], + perm_main_mem_b[row_idx], + perm_main_mem_c[row_idx], + perm_main_mem_d[row_idx], + perm_main_mem_ind_addr_a[row_idx], + perm_main_mem_ind_addr_b[row_idx], + perm_main_mem_ind_addr_c[row_idx], + perm_main_mem_ind_addr_d[row_idx], + lookup_byte_lengths[row_idx], + lookup_byte_operations[row_idx], + lookup_cd_value[row_idx], + lookup_ret_value[row_idx], + lookup_opcode_gas[row_idx], + range_check_l2_gas_hi[row_idx], + range_check_l2_gas_lo[row_idx], + range_check_da_gas_hi[row_idx], + range_check_da_gas_lo[row_idx], + kernel_output_lookup[row_idx], + lookup_into_kernel[row_idx], + incl_main_tag_err[row_idx], + incl_mem_tag_err[row_idx], + lookup_mem_rng_chk_lo[row_idx], + lookup_mem_rng_chk_mid[row_idx], + lookup_mem_rng_chk_hi[row_idx], + lookup_pow_2_0[row_idx], + lookup_pow_2_1[row_idx], + lookup_u8_0[row_idx], + lookup_u8_1[row_idx], + lookup_u16_0[row_idx], + lookup_u16_1[row_idx], + lookup_u16_2[row_idx], + lookup_u16_3[row_idx], + lookup_u16_4[row_idx], + lookup_u16_5[row_idx], + lookup_u16_6[row_idx], + lookup_u16_7[row_idx], + lookup_u16_8[row_idx], + lookup_u16_9[row_idx], + lookup_u16_10[row_idx], + lookup_u16_11[row_idx], + lookup_u16_12[row_idx], + lookup_u16_13[row_idx], + lookup_u16_14[row_idx], + lookup_div_u16_0[row_idx], + lookup_div_u16_1[row_idx], + lookup_div_u16_2[row_idx], + lookup_div_u16_3[row_idx], + lookup_div_u16_4[row_idx], + lookup_div_u16_5[row_idx], + lookup_div_u16_6[row_idx], + lookup_div_u16_7[row_idx], + alu_a_hi_shift[row_idx], + alu_a_lo_shift[row_idx], + alu_b_hi_shift[row_idx], + alu_b_lo_shift[row_idx], + alu_cmp_rng_ctr_shift[row_idx], + alu_div_u16_r0_shift[row_idx], + alu_div_u16_r1_shift[row_idx], + alu_div_u16_r2_shift[row_idx], + alu_div_u16_r3_shift[row_idx], + alu_div_u16_r4_shift[row_idx], + alu_div_u16_r5_shift[row_idx], + alu_div_u16_r6_shift[row_idx], + alu_div_u16_r7_shift[row_idx], + alu_op_add_shift[row_idx], + alu_op_cast_prev_shift[row_idx], + alu_op_cast_shift[row_idx], + alu_op_div_shift[row_idx], + alu_op_mul_shift[row_idx], + alu_op_shl_shift[row_idx], + alu_op_shr_shift[row_idx], + alu_op_sub_shift[row_idx], + alu_p_sub_a_hi_shift[row_idx], + alu_p_sub_a_lo_shift[row_idx], + alu_p_sub_b_hi_shift[row_idx], + alu_p_sub_b_lo_shift[row_idx], + alu_sel_alu_shift[row_idx], + alu_sel_cmp_shift[row_idx], + alu_sel_div_rng_chk_shift[row_idx], + alu_sel_rng_chk_lookup_shift[row_idx], + alu_sel_rng_chk_shift[row_idx], + alu_u16_r0_shift[row_idx], + alu_u16_r1_shift[row_idx], + alu_u16_r2_shift[row_idx], + alu_u16_r3_shift[row_idx], + alu_u16_r4_shift[row_idx], + alu_u16_r5_shift[row_idx], + alu_u16_r6_shift[row_idx], + alu_u8_r0_shift[row_idx], + alu_u8_r1_shift[row_idx], + binary_acc_ia_shift[row_idx], + binary_acc_ib_shift[row_idx], + binary_acc_ic_shift[row_idx], + binary_mem_tag_ctr_shift[row_idx], + binary_op_id_shift[row_idx], + kernel_emit_l2_to_l1_msg_write_offset_shift[row_idx], + kernel_emit_note_hash_write_offset_shift[row_idx], + kernel_emit_nullifier_write_offset_shift[row_idx], + kernel_emit_unencrypted_log_write_offset_shift[row_idx], + kernel_l1_to_l2_msg_exists_write_offset_shift[row_idx], + kernel_note_hash_exist_write_offset_shift[row_idx], + kernel_nullifier_exists_write_offset_shift[row_idx], + kernel_nullifier_non_exists_write_offset_shift[row_idx], + kernel_side_effect_counter_shift[row_idx], + kernel_sload_write_offset_shift[row_idx], + kernel_sstore_write_offset_shift[row_idx], + main_da_gas_remaining_shift[row_idx], + main_internal_return_ptr_shift[row_idx], + main_l2_gas_remaining_shift[row_idx], + main_pc_shift[row_idx], + mem_glob_addr_shift[row_idx], + mem_rw_shift[row_idx], + mem_sel_mem_shift[row_idx], + mem_tag_shift[row_idx], + mem_tsp_shift[row_idx], + mem_val_shift[row_idx], + slice_addr_shift[row_idx], + slice_clk_shift[row_idx], + slice_cnt_shift[row_idx], + slice_col_offset_shift[row_idx], + slice_sel_cd_cpy_shift[row_idx], + slice_sel_mem_active_shift[row_idx], + slice_sel_return_shift[row_idx], + slice_sel_start_shift[row_idx], + slice_space_id_shift[row_idx] }); +} + +AvmFlavor::CommitmentLabels::CommitmentLabels() +{ + Base::main_clk = "MAIN_CLK"; + Base::main_sel_first = "MAIN_SEL_FIRST"; + Base::kernel_kernel_inputs = "KERNEL_KERNEL_INPUTS"; + Base::kernel_kernel_value_out = "KERNEL_KERNEL_VALUE_OUT"; + Base::kernel_kernel_side_effect_out = "KERNEL_KERNEL_SIDE_EFFECT_OUT"; + Base::kernel_kernel_metadata_out = "KERNEL_KERNEL_METADATA_OUT"; + Base::main_calldata = "MAIN_CALLDATA"; + Base::main_returndata = "MAIN_RETURNDATA"; + Base::alu_a_hi = "ALU_A_HI"; + Base::alu_a_lo = "ALU_A_LO"; + Base::alu_b_hi = "ALU_B_HI"; + Base::alu_b_lo = "ALU_B_LO"; + Base::alu_borrow = "ALU_BORROW"; + Base::alu_cf = "ALU_CF"; + Base::alu_clk = "ALU_CLK"; + Base::alu_cmp_rng_ctr = "ALU_CMP_RNG_CTR"; + Base::alu_div_u16_r0 = "ALU_DIV_U16_R0"; + Base::alu_div_u16_r1 = "ALU_DIV_U16_R1"; + Base::alu_div_u16_r2 = "ALU_DIV_U16_R2"; + Base::alu_div_u16_r3 = "ALU_DIV_U16_R3"; + Base::alu_div_u16_r4 = "ALU_DIV_U16_R4"; + Base::alu_div_u16_r5 = "ALU_DIV_U16_R5"; + Base::alu_div_u16_r6 = "ALU_DIV_U16_R6"; + Base::alu_div_u16_r7 = "ALU_DIV_U16_R7"; + Base::alu_divisor_hi = "ALU_DIVISOR_HI"; + Base::alu_divisor_lo = "ALU_DIVISOR_LO"; + Base::alu_ff_tag = "ALU_FF_TAG"; + Base::alu_ia = "ALU_IA"; + Base::alu_ib = "ALU_IB"; + Base::alu_ic = "ALU_IC"; + Base::alu_in_tag = "ALU_IN_TAG"; + Base::alu_op_add = "ALU_OP_ADD"; + Base::alu_op_cast = "ALU_OP_CAST"; + Base::alu_op_cast_prev = "ALU_OP_CAST_PREV"; + Base::alu_op_div = "ALU_OP_DIV"; + Base::alu_op_div_a_lt_b = "ALU_OP_DIV_A_LT_B"; + Base::alu_op_div_std = "ALU_OP_DIV_STD"; + Base::alu_op_eq = "ALU_OP_EQ"; + Base::alu_op_eq_diff_inv = "ALU_OP_EQ_DIFF_INV"; + Base::alu_op_lt = "ALU_OP_LT"; + Base::alu_op_lte = "ALU_OP_LTE"; + Base::alu_op_mul = "ALU_OP_MUL"; + Base::alu_op_not = "ALU_OP_NOT"; + Base::alu_op_shl = "ALU_OP_SHL"; + Base::alu_op_shr = "ALU_OP_SHR"; + Base::alu_op_sub = "ALU_OP_SUB"; + Base::alu_p_a_borrow = "ALU_P_A_BORROW"; + Base::alu_p_b_borrow = "ALU_P_B_BORROW"; + Base::alu_p_sub_a_hi = "ALU_P_SUB_A_HI"; + Base::alu_p_sub_a_lo = "ALU_P_SUB_A_LO"; + Base::alu_p_sub_b_hi = "ALU_P_SUB_B_HI"; + Base::alu_p_sub_b_lo = "ALU_P_SUB_B_LO"; + Base::alu_partial_prod_hi = "ALU_PARTIAL_PROD_HI"; + Base::alu_partial_prod_lo = "ALU_PARTIAL_PROD_LO"; + Base::alu_quotient_hi = "ALU_QUOTIENT_HI"; + Base::alu_quotient_lo = "ALU_QUOTIENT_LO"; + Base::alu_remainder = "ALU_REMAINDER"; + Base::alu_res_hi = "ALU_RES_HI"; + Base::alu_res_lo = "ALU_RES_LO"; + Base::alu_sel_alu = "ALU_SEL_ALU"; + Base::alu_sel_cmp = "ALU_SEL_CMP"; + Base::alu_sel_div_rng_chk = "ALU_SEL_DIV_RNG_CHK"; + Base::alu_sel_rng_chk = "ALU_SEL_RNG_CHK"; + Base::alu_sel_rng_chk_lookup = "ALU_SEL_RNG_CHK_LOOKUP"; + Base::alu_sel_shift_which = "ALU_SEL_SHIFT_WHICH"; + Base::alu_shift_lt_bit_len = "ALU_SHIFT_LT_BIT_LEN"; + Base::alu_t_sub_s_bits = "ALU_T_SUB_S_BITS"; + Base::alu_two_pow_s = "ALU_TWO_POW_S"; + Base::alu_two_pow_t_sub_s = "ALU_TWO_POW_T_SUB_S"; + Base::alu_u128_tag = "ALU_U128_TAG"; + Base::alu_u16_r0 = "ALU_U16_R0"; + Base::alu_u16_r1 = "ALU_U16_R1"; + Base::alu_u16_r10 = "ALU_U16_R10"; + Base::alu_u16_r11 = "ALU_U16_R11"; + Base::alu_u16_r12 = "ALU_U16_R12"; + Base::alu_u16_r13 = "ALU_U16_R13"; + Base::alu_u16_r14 = "ALU_U16_R14"; + Base::alu_u16_r2 = "ALU_U16_R2"; + Base::alu_u16_r3 = "ALU_U16_R3"; + Base::alu_u16_r4 = "ALU_U16_R4"; + Base::alu_u16_r5 = "ALU_U16_R5"; + Base::alu_u16_r6 = "ALU_U16_R6"; + Base::alu_u16_r7 = "ALU_U16_R7"; + Base::alu_u16_r8 = "ALU_U16_R8"; + Base::alu_u16_r9 = "ALU_U16_R9"; + Base::alu_u16_tag = "ALU_U16_TAG"; + Base::alu_u32_tag = "ALU_U32_TAG"; + Base::alu_u64_tag = "ALU_U64_TAG"; + Base::alu_u8_r0 = "ALU_U8_R0"; + Base::alu_u8_r1 = "ALU_U8_R1"; + Base::alu_u8_tag = "ALU_U8_TAG"; + Base::binary_acc_ia = "BINARY_ACC_IA"; + Base::binary_acc_ib = "BINARY_ACC_IB"; + Base::binary_acc_ic = "BINARY_ACC_IC"; + Base::binary_clk = "BINARY_CLK"; + Base::binary_ia_bytes = "BINARY_IA_BYTES"; + Base::binary_ib_bytes = "BINARY_IB_BYTES"; + Base::binary_ic_bytes = "BINARY_IC_BYTES"; + Base::binary_in_tag = "BINARY_IN_TAG"; + Base::binary_mem_tag_ctr = "BINARY_MEM_TAG_CTR"; + Base::binary_mem_tag_ctr_inv = "BINARY_MEM_TAG_CTR_INV"; + Base::binary_op_id = "BINARY_OP_ID"; + Base::binary_sel_bin = "BINARY_SEL_BIN"; + Base::binary_start = "BINARY_START"; + Base::byte_lookup_sel_bin = "BYTE_LOOKUP_SEL_BIN"; + Base::byte_lookup_table_byte_lengths = "BYTE_LOOKUP_TABLE_BYTE_LENGTHS"; + Base::byte_lookup_table_in_tags = "BYTE_LOOKUP_TABLE_IN_TAGS"; + Base::byte_lookup_table_input_a = "BYTE_LOOKUP_TABLE_INPUT_A"; + Base::byte_lookup_table_input_b = "BYTE_LOOKUP_TABLE_INPUT_B"; + Base::byte_lookup_table_op_id = "BYTE_LOOKUP_TABLE_OP_ID"; + Base::byte_lookup_table_output = "BYTE_LOOKUP_TABLE_OUTPUT"; + Base::conversion_clk = "CONVERSION_CLK"; + Base::conversion_input = "CONVERSION_INPUT"; + Base::conversion_num_limbs = "CONVERSION_NUM_LIMBS"; + Base::conversion_radix = "CONVERSION_RADIX"; + Base::conversion_sel_to_radix_le = "CONVERSION_SEL_TO_RADIX_LE"; + Base::gas_da_gas_fixed_table = "GAS_DA_GAS_FIXED_TABLE"; + Base::gas_l2_gas_fixed_table = "GAS_L2_GAS_FIXED_TABLE"; + Base::gas_sel_gas_cost = "GAS_SEL_GAS_COST"; + Base::keccakf1600_clk = "KECCAKF1600_CLK"; + Base::keccakf1600_input = "KECCAKF1600_INPUT"; + Base::keccakf1600_output = "KECCAKF1600_OUTPUT"; + Base::keccakf1600_sel_keccakf1600 = "KECCAKF1600_SEL_KECCAKF1600"; + Base::kernel_emit_l2_to_l1_msg_write_offset = "KERNEL_EMIT_L2_TO_L1_MSG_WRITE_OFFSET"; + Base::kernel_emit_note_hash_write_offset = "KERNEL_EMIT_NOTE_HASH_WRITE_OFFSET"; + Base::kernel_emit_nullifier_write_offset = "KERNEL_EMIT_NULLIFIER_WRITE_OFFSET"; + Base::kernel_emit_unencrypted_log_write_offset = "KERNEL_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET"; + Base::kernel_kernel_in_offset = "KERNEL_KERNEL_IN_OFFSET"; + Base::kernel_kernel_out_offset = "KERNEL_KERNEL_OUT_OFFSET"; + Base::kernel_l1_to_l2_msg_exists_write_offset = "KERNEL_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET"; + Base::kernel_note_hash_exist_write_offset = "KERNEL_NOTE_HASH_EXIST_WRITE_OFFSET"; + Base::kernel_nullifier_exists_write_offset = "KERNEL_NULLIFIER_EXISTS_WRITE_OFFSET"; + Base::kernel_nullifier_non_exists_write_offset = "KERNEL_NULLIFIER_NON_EXISTS_WRITE_OFFSET"; + Base::kernel_q_public_input_kernel_add_to_table = "KERNEL_Q_PUBLIC_INPUT_KERNEL_ADD_TO_TABLE"; + Base::kernel_q_public_input_kernel_out_add_to_table = "KERNEL_Q_PUBLIC_INPUT_KERNEL_OUT_ADD_TO_TABLE"; + Base::kernel_side_effect_counter = "KERNEL_SIDE_EFFECT_COUNTER"; + Base::kernel_sload_write_offset = "KERNEL_SLOAD_WRITE_OFFSET"; + Base::kernel_sstore_write_offset = "KERNEL_SSTORE_WRITE_OFFSET"; + Base::main_abs_da_rem_gas_hi = "MAIN_ABS_DA_REM_GAS_HI"; + Base::main_abs_da_rem_gas_lo = "MAIN_ABS_DA_REM_GAS_LO"; + Base::main_abs_l2_rem_gas_hi = "MAIN_ABS_L2_REM_GAS_HI"; + Base::main_abs_l2_rem_gas_lo = "MAIN_ABS_L2_REM_GAS_LO"; + Base::main_alu_in_tag = "MAIN_ALU_IN_TAG"; + Base::main_bin_op_id = "MAIN_BIN_OP_ID"; + Base::main_call_ptr = "MAIN_CALL_PTR"; + Base::main_da_gas_op_cost = "MAIN_DA_GAS_OP_COST"; + Base::main_da_gas_remaining = "MAIN_DA_GAS_REMAINING"; + Base::main_da_out_of_gas = "MAIN_DA_OUT_OF_GAS"; + Base::main_ia = "MAIN_IA"; + Base::main_ib = "MAIN_IB"; + Base::main_ic = "MAIN_IC"; + Base::main_id = "MAIN_ID"; + Base::main_id_zero = "MAIN_ID_ZERO"; + Base::main_ind_addr_a = "MAIN_IND_ADDR_A"; + Base::main_ind_addr_b = "MAIN_IND_ADDR_B"; + Base::main_ind_addr_c = "MAIN_IND_ADDR_C"; + Base::main_ind_addr_d = "MAIN_IND_ADDR_D"; + Base::main_internal_return_ptr = "MAIN_INTERNAL_RETURN_PTR"; + Base::main_inv = "MAIN_INV"; + Base::main_l2_gas_op_cost = "MAIN_L2_GAS_OP_COST"; + Base::main_l2_gas_remaining = "MAIN_L2_GAS_REMAINING"; + 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"; + Base::main_mem_addr_c = "MAIN_MEM_ADDR_C"; + Base::main_mem_addr_d = "MAIN_MEM_ADDR_D"; + Base::main_op_err = "MAIN_OP_ERR"; + Base::main_opcode_val = "MAIN_OPCODE_VAL"; + Base::main_pc = "MAIN_PC"; + Base::main_r_in_tag = "MAIN_R_IN_TAG"; + Base::main_rwa = "MAIN_RWA"; + Base::main_rwb = "MAIN_RWB"; + Base::main_rwc = "MAIN_RWC"; + Base::main_rwd = "MAIN_RWD"; + Base::main_sel_alu = "MAIN_SEL_ALU"; + Base::main_sel_bin = "MAIN_SEL_BIN"; + Base::main_sel_calldata = "MAIN_SEL_CALLDATA"; + Base::main_sel_gas_accounting_active = "MAIN_SEL_GAS_ACCOUNTING_ACTIVE"; + Base::main_sel_last = "MAIN_SEL_LAST"; + Base::main_sel_mem_op_a = "MAIN_SEL_MEM_OP_A"; + Base::main_sel_mem_op_activate_gas = "MAIN_SEL_MEM_OP_ACTIVATE_GAS"; + Base::main_sel_mem_op_b = "MAIN_SEL_MEM_OP_B"; + Base::main_sel_mem_op_c = "MAIN_SEL_MEM_OP_C"; + Base::main_sel_mem_op_d = "MAIN_SEL_MEM_OP_D"; + Base::main_sel_mov_ia_to_ic = "MAIN_SEL_MOV_IA_TO_IC"; + Base::main_sel_mov_ib_to_ic = "MAIN_SEL_MOV_IB_TO_IC"; + Base::main_sel_op_add = "MAIN_SEL_OP_ADD"; + Base::main_sel_op_address = "MAIN_SEL_OP_ADDRESS"; + Base::main_sel_op_and = "MAIN_SEL_OP_AND"; + Base::main_sel_op_block_number = "MAIN_SEL_OP_BLOCK_NUMBER"; + Base::main_sel_op_calldata_copy = "MAIN_SEL_OP_CALLDATA_COPY"; + Base::main_sel_op_cast = "MAIN_SEL_OP_CAST"; + Base::main_sel_op_chain_id = "MAIN_SEL_OP_CHAIN_ID"; + Base::main_sel_op_cmov = "MAIN_SEL_OP_CMOV"; + Base::main_sel_op_coinbase = "MAIN_SEL_OP_COINBASE"; + Base::main_sel_op_dagasleft = "MAIN_SEL_OP_DAGASLEFT"; + Base::main_sel_op_div = "MAIN_SEL_OP_DIV"; + Base::main_sel_op_emit_l2_to_l1_msg = "MAIN_SEL_OP_EMIT_L2_TO_L1_MSG"; + Base::main_sel_op_emit_note_hash = "MAIN_SEL_OP_EMIT_NOTE_HASH"; + Base::main_sel_op_emit_nullifier = "MAIN_SEL_OP_EMIT_NULLIFIER"; + Base::main_sel_op_emit_unencrypted_log = "MAIN_SEL_OP_EMIT_UNENCRYPTED_LOG"; + Base::main_sel_op_eq = "MAIN_SEL_OP_EQ"; + Base::main_sel_op_external_call = "MAIN_SEL_OP_EXTERNAL_CALL"; + Base::main_sel_op_external_return = "MAIN_SEL_OP_EXTERNAL_RETURN"; + Base::main_sel_op_fdiv = "MAIN_SEL_OP_FDIV"; + Base::main_sel_op_fee_per_da_gas = "MAIN_SEL_OP_FEE_PER_DA_GAS"; + Base::main_sel_op_fee_per_l2_gas = "MAIN_SEL_OP_FEE_PER_L2_GAS"; + Base::main_sel_op_function_selector = "MAIN_SEL_OP_FUNCTION_SELECTOR"; + Base::main_sel_op_get_contract_instance = "MAIN_SEL_OP_GET_CONTRACT_INSTANCE"; + Base::main_sel_op_halt = "MAIN_SEL_OP_HALT"; + Base::main_sel_op_internal_call = "MAIN_SEL_OP_INTERNAL_CALL"; + Base::main_sel_op_internal_return = "MAIN_SEL_OP_INTERNAL_RETURN"; + Base::main_sel_op_jump = "MAIN_SEL_OP_JUMP"; + Base::main_sel_op_jumpi = "MAIN_SEL_OP_JUMPI"; + Base::main_sel_op_keccak = "MAIN_SEL_OP_KECCAK"; + Base::main_sel_op_l1_to_l2_msg_exists = "MAIN_SEL_OP_L1_TO_L2_MSG_EXISTS"; + Base::main_sel_op_l2gasleft = "MAIN_SEL_OP_L2GASLEFT"; + Base::main_sel_op_lt = "MAIN_SEL_OP_LT"; + Base::main_sel_op_lte = "MAIN_SEL_OP_LTE"; + Base::main_sel_op_mov = "MAIN_SEL_OP_MOV"; + Base::main_sel_op_mul = "MAIN_SEL_OP_MUL"; + Base::main_sel_op_not = "MAIN_SEL_OP_NOT"; + Base::main_sel_op_note_hash_exists = "MAIN_SEL_OP_NOTE_HASH_EXISTS"; + Base::main_sel_op_nullifier_exists = "MAIN_SEL_OP_NULLIFIER_EXISTS"; + Base::main_sel_op_or = "MAIN_SEL_OP_OR"; + Base::main_sel_op_pedersen = "MAIN_SEL_OP_PEDERSEN"; + Base::main_sel_op_poseidon2 = "MAIN_SEL_OP_POSEIDON2"; + Base::main_sel_op_radix_le = "MAIN_SEL_OP_RADIX_LE"; + Base::main_sel_op_sender = "MAIN_SEL_OP_SENDER"; + Base::main_sel_op_sha256 = "MAIN_SEL_OP_SHA256"; + Base::main_sel_op_shl = "MAIN_SEL_OP_SHL"; + Base::main_sel_op_shr = "MAIN_SEL_OP_SHR"; + Base::main_sel_op_sload = "MAIN_SEL_OP_SLOAD"; + Base::main_sel_op_sstore = "MAIN_SEL_OP_SSTORE"; + Base::main_sel_op_storage_address = "MAIN_SEL_OP_STORAGE_ADDRESS"; + Base::main_sel_op_sub = "MAIN_SEL_OP_SUB"; + Base::main_sel_op_timestamp = "MAIN_SEL_OP_TIMESTAMP"; + Base::main_sel_op_transaction_fee = "MAIN_SEL_OP_TRANSACTION_FEE"; + Base::main_sel_op_version = "MAIN_SEL_OP_VERSION"; + Base::main_sel_op_xor = "MAIN_SEL_OP_XOR"; + Base::main_sel_q_kernel_lookup = "MAIN_SEL_Q_KERNEL_LOOKUP"; + Base::main_sel_q_kernel_output_lookup = "MAIN_SEL_Q_KERNEL_OUTPUT_LOOKUP"; + Base::main_sel_resolve_ind_addr_a = "MAIN_SEL_RESOLVE_IND_ADDR_A"; + Base::main_sel_resolve_ind_addr_b = "MAIN_SEL_RESOLVE_IND_ADDR_B"; + Base::main_sel_resolve_ind_addr_c = "MAIN_SEL_RESOLVE_IND_ADDR_C"; + Base::main_sel_resolve_ind_addr_d = "MAIN_SEL_RESOLVE_IND_ADDR_D"; + Base::main_sel_returndata = "MAIN_SEL_RETURNDATA"; + Base::main_sel_rng_16 = "MAIN_SEL_RNG_16"; + Base::main_sel_rng_8 = "MAIN_SEL_RNG_8"; + Base::main_sel_slice_gadget = "MAIN_SEL_SLICE_GADGET"; + Base::main_space_id = "MAIN_SPACE_ID"; + Base::main_tag_err = "MAIN_TAG_ERR"; + Base::main_w_in_tag = "MAIN_W_IN_TAG"; + Base::mem_addr = "MEM_ADDR"; + Base::mem_clk = "MEM_CLK"; + Base::mem_diff_hi = "MEM_DIFF_HI"; + Base::mem_diff_lo = "MEM_DIFF_LO"; + Base::mem_diff_mid = "MEM_DIFF_MID"; + Base::mem_glob_addr = "MEM_GLOB_ADDR"; + Base::mem_last = "MEM_LAST"; + Base::mem_lastAccess = "MEM_LAST_ACCESS"; + Base::mem_one_min_inv = "MEM_ONE_MIN_INV"; + Base::mem_r_in_tag = "MEM_R_IN_TAG"; + Base::mem_rw = "MEM_RW"; + Base::mem_sel_mem = "MEM_SEL_MEM"; + Base::mem_sel_mov_ia_to_ic = "MEM_SEL_MOV_IA_TO_IC"; + Base::mem_sel_mov_ib_to_ic = "MEM_SEL_MOV_IB_TO_IC"; + Base::mem_sel_op_a = "MEM_SEL_OP_A"; + Base::mem_sel_op_b = "MEM_SEL_OP_B"; + Base::mem_sel_op_c = "MEM_SEL_OP_C"; + Base::mem_sel_op_cmov = "MEM_SEL_OP_CMOV"; + Base::mem_sel_op_d = "MEM_SEL_OP_D"; + Base::mem_sel_op_slice = "MEM_SEL_OP_SLICE"; + Base::mem_sel_resolve_ind_addr_a = "MEM_SEL_RESOLVE_IND_ADDR_A"; + Base::mem_sel_resolve_ind_addr_b = "MEM_SEL_RESOLVE_IND_ADDR_B"; + Base::mem_sel_resolve_ind_addr_c = "MEM_SEL_RESOLVE_IND_ADDR_C"; + Base::mem_sel_resolve_ind_addr_d = "MEM_SEL_RESOLVE_IND_ADDR_D"; + Base::mem_sel_rng_chk = "MEM_SEL_RNG_CHK"; + Base::mem_skip_check_tag = "MEM_SKIP_CHECK_TAG"; + Base::mem_space_id = "MEM_SPACE_ID"; + Base::mem_tag = "MEM_TAG"; + Base::mem_tag_err = "MEM_TAG_ERR"; + Base::mem_tsp = "MEM_TSP"; + Base::mem_val = "MEM_VAL"; + Base::mem_w_in_tag = "MEM_W_IN_TAG"; + Base::pedersen_clk = "PEDERSEN_CLK"; + Base::pedersen_input = "PEDERSEN_INPUT"; + Base::pedersen_output = "PEDERSEN_OUTPUT"; + Base::pedersen_sel_pedersen = "PEDERSEN_SEL_PEDERSEN"; + Base::poseidon2_clk = "POSEIDON2_CLK"; + Base::poseidon2_input = "POSEIDON2_INPUT"; + Base::poseidon2_output = "POSEIDON2_OUTPUT"; + Base::poseidon2_sel_poseidon_perm = "POSEIDON2_SEL_POSEIDON_PERM"; + Base::powers_power_of_2 = "POWERS_POWER_OF_2"; + Base::sha256_clk = "SHA256_CLK"; + Base::sha256_input = "SHA256_INPUT"; + Base::sha256_output = "SHA256_OUTPUT"; + Base::sha256_sel_sha256_compression = "SHA256_SEL_SHA256_COMPRESSION"; + Base::sha256_state = "SHA256_STATE"; + Base::slice_addr = "SLICE_ADDR"; + Base::slice_clk = "SLICE_CLK"; + Base::slice_cnt = "SLICE_CNT"; + Base::slice_col_offset = "SLICE_COL_OFFSET"; + Base::slice_one_min_inv = "SLICE_ONE_MIN_INV"; + Base::slice_sel_cd_cpy = "SLICE_SEL_CD_CPY"; + Base::slice_sel_mem_active = "SLICE_SEL_MEM_ACTIVE"; + Base::slice_sel_return = "SLICE_SEL_RETURN"; + Base::slice_sel_start = "SLICE_SEL_START"; + Base::slice_space_id = "SLICE_SPACE_ID"; + Base::slice_val = "SLICE_VAL"; + Base::perm_slice_mem = "PERM_SLICE_MEM"; + Base::perm_main_alu = "PERM_MAIN_ALU"; + Base::perm_main_bin = "PERM_MAIN_BIN"; + Base::perm_main_conv = "PERM_MAIN_CONV"; + Base::perm_main_pos2_perm = "PERM_MAIN_POS2_PERM"; + Base::perm_main_pedersen = "PERM_MAIN_PEDERSEN"; + Base::perm_main_slice = "PERM_MAIN_SLICE"; + Base::perm_main_mem_a = "PERM_MAIN_MEM_A"; + Base::perm_main_mem_b = "PERM_MAIN_MEM_B"; + Base::perm_main_mem_c = "PERM_MAIN_MEM_C"; + Base::perm_main_mem_d = "PERM_MAIN_MEM_D"; + Base::perm_main_mem_ind_addr_a = "PERM_MAIN_MEM_IND_ADDR_A"; + Base::perm_main_mem_ind_addr_b = "PERM_MAIN_MEM_IND_ADDR_B"; + Base::perm_main_mem_ind_addr_c = "PERM_MAIN_MEM_IND_ADDR_C"; + Base::perm_main_mem_ind_addr_d = "PERM_MAIN_MEM_IND_ADDR_D"; + Base::lookup_byte_lengths = "LOOKUP_BYTE_LENGTHS"; + Base::lookup_byte_operations = "LOOKUP_BYTE_OPERATIONS"; + Base::lookup_cd_value = "LOOKUP_CD_VALUE"; + Base::lookup_ret_value = "LOOKUP_RET_VALUE"; + Base::lookup_opcode_gas = "LOOKUP_OPCODE_GAS"; + Base::range_check_l2_gas_hi = "RANGE_CHECK_L2_GAS_HI"; + Base::range_check_l2_gas_lo = "RANGE_CHECK_L2_GAS_LO"; + Base::range_check_da_gas_hi = "RANGE_CHECK_DA_GAS_HI"; + Base::range_check_da_gas_lo = "RANGE_CHECK_DA_GAS_LO"; + Base::kernel_output_lookup = "KERNEL_OUTPUT_LOOKUP"; + Base::lookup_into_kernel = "LOOKUP_INTO_KERNEL"; + Base::incl_main_tag_err = "INCL_MAIN_TAG_ERR"; + Base::incl_mem_tag_err = "INCL_MEM_TAG_ERR"; + Base::lookup_mem_rng_chk_lo = "LOOKUP_MEM_RNG_CHK_LO"; + Base::lookup_mem_rng_chk_mid = "LOOKUP_MEM_RNG_CHK_MID"; + Base::lookup_mem_rng_chk_hi = "LOOKUP_MEM_RNG_CHK_HI"; + Base::lookup_pow_2_0 = "LOOKUP_POW_2_0"; + Base::lookup_pow_2_1 = "LOOKUP_POW_2_1"; + Base::lookup_u8_0 = "LOOKUP_U8_0"; + Base::lookup_u8_1 = "LOOKUP_U8_1"; + Base::lookup_u16_0 = "LOOKUP_U16_0"; + Base::lookup_u16_1 = "LOOKUP_U16_1"; + Base::lookup_u16_2 = "LOOKUP_U16_2"; + Base::lookup_u16_3 = "LOOKUP_U16_3"; + Base::lookup_u16_4 = "LOOKUP_U16_4"; + Base::lookup_u16_5 = "LOOKUP_U16_5"; + Base::lookup_u16_6 = "LOOKUP_U16_6"; + Base::lookup_u16_7 = "LOOKUP_U16_7"; + Base::lookup_u16_8 = "LOOKUP_U16_8"; + Base::lookup_u16_9 = "LOOKUP_U16_9"; + Base::lookup_u16_10 = "LOOKUP_U16_10"; + Base::lookup_u16_11 = "LOOKUP_U16_11"; + Base::lookup_u16_12 = "LOOKUP_U16_12"; + Base::lookup_u16_13 = "LOOKUP_U16_13"; + Base::lookup_u16_14 = "LOOKUP_U16_14"; + Base::lookup_div_u16_0 = "LOOKUP_DIV_U16_0"; + Base::lookup_div_u16_1 = "LOOKUP_DIV_U16_1"; + Base::lookup_div_u16_2 = "LOOKUP_DIV_U16_2"; + Base::lookup_div_u16_3 = "LOOKUP_DIV_U16_3"; + Base::lookup_div_u16_4 = "LOOKUP_DIV_U16_4"; + Base::lookup_div_u16_5 = "LOOKUP_DIV_U16_5"; + Base::lookup_div_u16_6 = "LOOKUP_DIV_U16_6"; + Base::lookup_div_u16_7 = "LOOKUP_DIV_U16_7"; + Base::lookup_byte_lengths_counts = "LOOKUP_BYTE_LENGTHS_COUNTS"; + Base::lookup_byte_operations_counts = "LOOKUP_BYTE_OPERATIONS_COUNTS"; + Base::lookup_cd_value_counts = "LOOKUP_CD_VALUE_COUNTS"; + Base::lookup_ret_value_counts = "LOOKUP_RET_VALUE_COUNTS"; + Base::lookup_opcode_gas_counts = "LOOKUP_OPCODE_GAS_COUNTS"; + Base::range_check_l2_gas_hi_counts = "RANGE_CHECK_L2_GAS_HI_COUNTS"; + Base::range_check_l2_gas_lo_counts = "RANGE_CHECK_L2_GAS_LO_COUNTS"; + Base::range_check_da_gas_hi_counts = "RANGE_CHECK_DA_GAS_HI_COUNTS"; + Base::range_check_da_gas_lo_counts = "RANGE_CHECK_DA_GAS_LO_COUNTS"; + Base::kernel_output_lookup_counts = "KERNEL_OUTPUT_LOOKUP_COUNTS"; + Base::lookup_into_kernel_counts = "LOOKUP_INTO_KERNEL_COUNTS"; + Base::incl_main_tag_err_counts = "INCL_MAIN_TAG_ERR_COUNTS"; + Base::incl_mem_tag_err_counts = "INCL_MEM_TAG_ERR_COUNTS"; + Base::lookup_mem_rng_chk_lo_counts = "LOOKUP_MEM_RNG_CHK_LO_COUNTS"; + Base::lookup_mem_rng_chk_mid_counts = "LOOKUP_MEM_RNG_CHK_MID_COUNTS"; + Base::lookup_mem_rng_chk_hi_counts = "LOOKUP_MEM_RNG_CHK_HI_COUNTS"; + Base::lookup_pow_2_0_counts = "LOOKUP_POW_2_0_COUNTS"; + Base::lookup_pow_2_1_counts = "LOOKUP_POW_2_1_COUNTS"; + Base::lookup_u8_0_counts = "LOOKUP_U8_0_COUNTS"; + Base::lookup_u8_1_counts = "LOOKUP_U8_1_COUNTS"; + Base::lookup_u16_0_counts = "LOOKUP_U16_0_COUNTS"; + Base::lookup_u16_1_counts = "LOOKUP_U16_1_COUNTS"; + Base::lookup_u16_2_counts = "LOOKUP_U16_2_COUNTS"; + Base::lookup_u16_3_counts = "LOOKUP_U16_3_COUNTS"; + Base::lookup_u16_4_counts = "LOOKUP_U16_4_COUNTS"; + Base::lookup_u16_5_counts = "LOOKUP_U16_5_COUNTS"; + Base::lookup_u16_6_counts = "LOOKUP_U16_6_COUNTS"; + Base::lookup_u16_7_counts = "LOOKUP_U16_7_COUNTS"; + Base::lookup_u16_8_counts = "LOOKUP_U16_8_COUNTS"; + Base::lookup_u16_9_counts = "LOOKUP_U16_9_COUNTS"; + Base::lookup_u16_10_counts = "LOOKUP_U16_10_COUNTS"; + Base::lookup_u16_11_counts = "LOOKUP_U16_11_COUNTS"; + Base::lookup_u16_12_counts = "LOOKUP_U16_12_COUNTS"; + Base::lookup_u16_13_counts = "LOOKUP_U16_13_COUNTS"; + Base::lookup_u16_14_counts = "LOOKUP_U16_14_COUNTS"; + Base::lookup_div_u16_0_counts = "LOOKUP_DIV_U16_0_COUNTS"; + Base::lookup_div_u16_1_counts = "LOOKUP_DIV_U16_1_COUNTS"; + Base::lookup_div_u16_2_counts = "LOOKUP_DIV_U16_2_COUNTS"; + Base::lookup_div_u16_3_counts = "LOOKUP_DIV_U16_3_COUNTS"; + Base::lookup_div_u16_4_counts = "LOOKUP_DIV_U16_4_COUNTS"; + Base::lookup_div_u16_5_counts = "LOOKUP_DIV_U16_5_COUNTS"; + Base::lookup_div_u16_6_counts = "LOOKUP_DIV_U16_6_COUNTS"; + Base::lookup_div_u16_7_counts = "LOOKUP_DIV_U16_7_COUNTS"; +}; + +AvmFlavor::VerifierCommitments::VerifierCommitments(const std::shared_ptr& verification_key) +{ + main_clk = verification_key->main_clk; + main_sel_first = verification_key->main_sel_first; +} + +void AvmFlavor::Transcript::deserialize_full_transcript() +{ + size_t num_frs_read = 0; + circuit_size = deserialize_from_buffer(proof_data, num_frs_read); + size_t log_n = numeric::get_msb(circuit_size); + + for (auto& commitment : commitments) { + commitment = deserialize_from_buffer(proof_data, num_frs_read); + } + for (size_t i = 0; i < log_n; ++i) { + sumcheck_univariates.emplace_back(deserialize_from_buffer>( + Transcript::proof_data, num_frs_read)); + } + sumcheck_evaluations = + deserialize_from_buffer>(Transcript::proof_data, num_frs_read); + for (size_t i = 0; i < log_n; ++i) { + zm_cq_comms.push_back(deserialize_from_buffer(proof_data, num_frs_read)); + } + zm_cq_comm = deserialize_from_buffer(proof_data, num_frs_read); + zm_pi_comm = deserialize_from_buffer(proof_data, num_frs_read); +} + +void AvmFlavor::Transcript::serialize_full_transcript() +{ + size_t old_proof_length = proof_data.size(); + Transcript::proof_data.clear(); + size_t log_n = numeric::get_msb(circuit_size); + + serialize_to_buffer(circuit_size, Transcript::proof_data); + + for (const auto& commitment : commitments) { + serialize_to_buffer(commitment, Transcript::proof_data); + } + for (size_t i = 0; i < log_n; ++i) { + serialize_to_buffer(sumcheck_univariates[i], Transcript::proof_data); + } + serialize_to_buffer(sumcheck_evaluations, Transcript::proof_data); + for (size_t i = 0; i < log_n; ++i) { + serialize_to_buffer(zm_cq_comms[i], proof_data); + } + serialize_to_buffer(zm_cq_comm, proof_data); + serialize_to_buffer(zm_pi_comm, proof_data); + + // sanity check to make sure we generate the same length of proof as before. + ASSERT(proof_data.size() == old_proof_length); +} + +AvmFlavor::PartiallyEvaluatedMultivariates::PartiallyEvaluatedMultivariates(const size_t circuit_size) +{ + // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) + for (auto& poly : get_all()) { + poly = Polynomial(circuit_size / 2); + } +} + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index 62ea2eea347..d09cd22b099 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/commitment_schemes/kzg/kzg.hpp" @@ -305,493 +306,7 @@ class AvmFlavor { DEFINE_FLAVOR_MEMBERS(DataType, ALL_ENTITIES) - AllConstRefValues(const RefArray& il) - : main_clk(il[0]) - , main_sel_first(il[1]) - , kernel_kernel_inputs(il[2]) - , kernel_kernel_value_out(il[3]) - , kernel_kernel_side_effect_out(il[4]) - , kernel_kernel_metadata_out(il[5]) - , main_calldata(il[6]) - , main_returndata(il[7]) - , alu_a_hi(il[8]) - , alu_a_lo(il[9]) - , alu_b_hi(il[10]) - , alu_b_lo(il[11]) - , alu_borrow(il[12]) - , alu_cf(il[13]) - , alu_clk(il[14]) - , alu_cmp_rng_ctr(il[15]) - , alu_div_u16_r0(il[16]) - , alu_div_u16_r1(il[17]) - , alu_div_u16_r2(il[18]) - , alu_div_u16_r3(il[19]) - , alu_div_u16_r4(il[20]) - , alu_div_u16_r5(il[21]) - , alu_div_u16_r6(il[22]) - , alu_div_u16_r7(il[23]) - , alu_divisor_hi(il[24]) - , alu_divisor_lo(il[25]) - , alu_ff_tag(il[26]) - , alu_ia(il[27]) - , alu_ib(il[28]) - , alu_ic(il[29]) - , alu_in_tag(il[30]) - , alu_op_add(il[31]) - , alu_op_cast(il[32]) - , alu_op_cast_prev(il[33]) - , alu_op_div(il[34]) - , alu_op_div_a_lt_b(il[35]) - , alu_op_div_std(il[36]) - , alu_op_eq(il[37]) - , alu_op_eq_diff_inv(il[38]) - , alu_op_lt(il[39]) - , alu_op_lte(il[40]) - , alu_op_mul(il[41]) - , alu_op_not(il[42]) - , alu_op_shl(il[43]) - , alu_op_shr(il[44]) - , alu_op_sub(il[45]) - , alu_p_a_borrow(il[46]) - , alu_p_b_borrow(il[47]) - , alu_p_sub_a_hi(il[48]) - , alu_p_sub_a_lo(il[49]) - , alu_p_sub_b_hi(il[50]) - , alu_p_sub_b_lo(il[51]) - , alu_partial_prod_hi(il[52]) - , alu_partial_prod_lo(il[53]) - , alu_quotient_hi(il[54]) - , alu_quotient_lo(il[55]) - , alu_remainder(il[56]) - , alu_res_hi(il[57]) - , alu_res_lo(il[58]) - , alu_sel_alu(il[59]) - , alu_sel_cmp(il[60]) - , alu_sel_div_rng_chk(il[61]) - , alu_sel_rng_chk(il[62]) - , alu_sel_rng_chk_lookup(il[63]) - , alu_sel_shift_which(il[64]) - , alu_shift_lt_bit_len(il[65]) - , alu_t_sub_s_bits(il[66]) - , alu_two_pow_s(il[67]) - , alu_two_pow_t_sub_s(il[68]) - , alu_u128_tag(il[69]) - , alu_u16_r0(il[70]) - , alu_u16_r1(il[71]) - , alu_u16_r10(il[72]) - , alu_u16_r11(il[73]) - , alu_u16_r12(il[74]) - , alu_u16_r13(il[75]) - , alu_u16_r14(il[76]) - , alu_u16_r2(il[77]) - , alu_u16_r3(il[78]) - , alu_u16_r4(il[79]) - , alu_u16_r5(il[80]) - , alu_u16_r6(il[81]) - , alu_u16_r7(il[82]) - , alu_u16_r8(il[83]) - , alu_u16_r9(il[84]) - , alu_u16_tag(il[85]) - , alu_u32_tag(il[86]) - , alu_u64_tag(il[87]) - , alu_u8_r0(il[88]) - , alu_u8_r1(il[89]) - , alu_u8_tag(il[90]) - , binary_acc_ia(il[91]) - , binary_acc_ib(il[92]) - , binary_acc_ic(il[93]) - , binary_clk(il[94]) - , binary_ia_bytes(il[95]) - , binary_ib_bytes(il[96]) - , binary_ic_bytes(il[97]) - , binary_in_tag(il[98]) - , binary_mem_tag_ctr(il[99]) - , binary_mem_tag_ctr_inv(il[100]) - , binary_op_id(il[101]) - , binary_sel_bin(il[102]) - , binary_start(il[103]) - , byte_lookup_sel_bin(il[104]) - , byte_lookup_table_byte_lengths(il[105]) - , byte_lookup_table_in_tags(il[106]) - , byte_lookup_table_input_a(il[107]) - , byte_lookup_table_input_b(il[108]) - , byte_lookup_table_op_id(il[109]) - , byte_lookup_table_output(il[110]) - , conversion_clk(il[111]) - , conversion_input(il[112]) - , conversion_num_limbs(il[113]) - , conversion_radix(il[114]) - , conversion_sel_to_radix_le(il[115]) - , gas_da_gas_fixed_table(il[116]) - , gas_l2_gas_fixed_table(il[117]) - , gas_sel_gas_cost(il[118]) - , keccakf1600_clk(il[119]) - , keccakf1600_input(il[120]) - , keccakf1600_output(il[121]) - , keccakf1600_sel_keccakf1600(il[122]) - , kernel_emit_l2_to_l1_msg_write_offset(il[123]) - , kernel_emit_note_hash_write_offset(il[124]) - , kernel_emit_nullifier_write_offset(il[125]) - , kernel_emit_unencrypted_log_write_offset(il[126]) - , kernel_kernel_in_offset(il[127]) - , kernel_kernel_out_offset(il[128]) - , kernel_l1_to_l2_msg_exists_write_offset(il[129]) - , kernel_note_hash_exist_write_offset(il[130]) - , kernel_nullifier_exists_write_offset(il[131]) - , kernel_nullifier_non_exists_write_offset(il[132]) - , kernel_q_public_input_kernel_add_to_table(il[133]) - , kernel_q_public_input_kernel_out_add_to_table(il[134]) - , kernel_side_effect_counter(il[135]) - , kernel_sload_write_offset(il[136]) - , kernel_sstore_write_offset(il[137]) - , main_abs_da_rem_gas_hi(il[138]) - , main_abs_da_rem_gas_lo(il[139]) - , main_abs_l2_rem_gas_hi(il[140]) - , main_abs_l2_rem_gas_lo(il[141]) - , main_alu_in_tag(il[142]) - , main_bin_op_id(il[143]) - , main_call_ptr(il[144]) - , main_da_gas_op_cost(il[145]) - , main_da_gas_remaining(il[146]) - , main_da_out_of_gas(il[147]) - , main_ia(il[148]) - , main_ib(il[149]) - , main_ic(il[150]) - , main_id(il[151]) - , main_id_zero(il[152]) - , main_ind_addr_a(il[153]) - , main_ind_addr_b(il[154]) - , main_ind_addr_c(il[155]) - , main_ind_addr_d(il[156]) - , main_internal_return_ptr(il[157]) - , main_inv(il[158]) - , main_l2_gas_op_cost(il[159]) - , main_l2_gas_remaining(il[160]) - , main_l2_out_of_gas(il[161]) - , main_mem_addr_a(il[162]) - , main_mem_addr_b(il[163]) - , main_mem_addr_c(il[164]) - , main_mem_addr_d(il[165]) - , main_op_err(il[166]) - , main_opcode_val(il[167]) - , main_pc(il[168]) - , main_r_in_tag(il[169]) - , main_rwa(il[170]) - , main_rwb(il[171]) - , main_rwc(il[172]) - , main_rwd(il[173]) - , main_sel_alu(il[174]) - , main_sel_bin(il[175]) - , main_sel_calldata(il[176]) - , main_sel_gas_accounting_active(il[177]) - , main_sel_last(il[178]) - , main_sel_mem_op_a(il[179]) - , main_sel_mem_op_activate_gas(il[180]) - , main_sel_mem_op_b(il[181]) - , main_sel_mem_op_c(il[182]) - , main_sel_mem_op_d(il[183]) - , main_sel_mov_ia_to_ic(il[184]) - , main_sel_mov_ib_to_ic(il[185]) - , main_sel_op_add(il[186]) - , main_sel_op_address(il[187]) - , main_sel_op_and(il[188]) - , main_sel_op_block_number(il[189]) - , main_sel_op_calldata_copy(il[190]) - , main_sel_op_cast(il[191]) - , main_sel_op_chain_id(il[192]) - , main_sel_op_cmov(il[193]) - , main_sel_op_coinbase(il[194]) - , main_sel_op_dagasleft(il[195]) - , main_sel_op_div(il[196]) - , main_sel_op_emit_l2_to_l1_msg(il[197]) - , main_sel_op_emit_note_hash(il[198]) - , main_sel_op_emit_nullifier(il[199]) - , main_sel_op_emit_unencrypted_log(il[200]) - , main_sel_op_eq(il[201]) - , main_sel_op_external_call(il[202]) - , main_sel_op_external_return(il[203]) - , main_sel_op_fdiv(il[204]) - , main_sel_op_fee_per_da_gas(il[205]) - , main_sel_op_fee_per_l2_gas(il[206]) - , main_sel_op_function_selector(il[207]) - , main_sel_op_get_contract_instance(il[208]) - , main_sel_op_halt(il[209]) - , main_sel_op_internal_call(il[210]) - , main_sel_op_internal_return(il[211]) - , main_sel_op_jump(il[212]) - , main_sel_op_jumpi(il[213]) - , main_sel_op_keccak(il[214]) - , main_sel_op_l1_to_l2_msg_exists(il[215]) - , main_sel_op_l2gasleft(il[216]) - , main_sel_op_lt(il[217]) - , main_sel_op_lte(il[218]) - , main_sel_op_mov(il[219]) - , main_sel_op_mul(il[220]) - , main_sel_op_not(il[221]) - , main_sel_op_note_hash_exists(il[222]) - , main_sel_op_nullifier_exists(il[223]) - , main_sel_op_or(il[224]) - , main_sel_op_pedersen(il[225]) - , main_sel_op_poseidon2(il[226]) - , main_sel_op_radix_le(il[227]) - , main_sel_op_sender(il[228]) - , main_sel_op_sha256(il[229]) - , main_sel_op_shl(il[230]) - , main_sel_op_shr(il[231]) - , main_sel_op_sload(il[232]) - , main_sel_op_sstore(il[233]) - , main_sel_op_storage_address(il[234]) - , main_sel_op_sub(il[235]) - , main_sel_op_timestamp(il[236]) - , main_sel_op_transaction_fee(il[237]) - , main_sel_op_version(il[238]) - , main_sel_op_xor(il[239]) - , main_sel_q_kernel_lookup(il[240]) - , main_sel_q_kernel_output_lookup(il[241]) - , main_sel_resolve_ind_addr_a(il[242]) - , main_sel_resolve_ind_addr_b(il[243]) - , main_sel_resolve_ind_addr_c(il[244]) - , main_sel_resolve_ind_addr_d(il[245]) - , main_sel_returndata(il[246]) - , main_sel_rng_16(il[247]) - , main_sel_rng_8(il[248]) - , main_sel_slice_gadget(il[249]) - , main_space_id(il[250]) - , main_tag_err(il[251]) - , main_w_in_tag(il[252]) - , mem_addr(il[253]) - , mem_clk(il[254]) - , mem_diff_hi(il[255]) - , mem_diff_lo(il[256]) - , mem_diff_mid(il[257]) - , mem_glob_addr(il[258]) - , mem_last(il[259]) - , mem_lastAccess(il[260]) - , mem_one_min_inv(il[261]) - , mem_r_in_tag(il[262]) - , mem_rw(il[263]) - , mem_sel_mem(il[264]) - , mem_sel_mov_ia_to_ic(il[265]) - , mem_sel_mov_ib_to_ic(il[266]) - , mem_sel_op_a(il[267]) - , mem_sel_op_b(il[268]) - , mem_sel_op_c(il[269]) - , mem_sel_op_cmov(il[270]) - , mem_sel_op_d(il[271]) - , mem_sel_op_slice(il[272]) - , mem_sel_resolve_ind_addr_a(il[273]) - , mem_sel_resolve_ind_addr_b(il[274]) - , mem_sel_resolve_ind_addr_c(il[275]) - , mem_sel_resolve_ind_addr_d(il[276]) - , mem_sel_rng_chk(il[277]) - , mem_skip_check_tag(il[278]) - , mem_space_id(il[279]) - , mem_tag(il[280]) - , mem_tag_err(il[281]) - , mem_tsp(il[282]) - , mem_val(il[283]) - , mem_w_in_tag(il[284]) - , pedersen_clk(il[285]) - , pedersen_input(il[286]) - , pedersen_output(il[287]) - , pedersen_sel_pedersen(il[288]) - , poseidon2_clk(il[289]) - , poseidon2_input(il[290]) - , poseidon2_output(il[291]) - , poseidon2_sel_poseidon_perm(il[292]) - , powers_power_of_2(il[293]) - , sha256_clk(il[294]) - , sha256_input(il[295]) - , sha256_output(il[296]) - , sha256_sel_sha256_compression(il[297]) - , sha256_state(il[298]) - , slice_addr(il[299]) - , slice_clk(il[300]) - , slice_cnt(il[301]) - , slice_col_offset(il[302]) - , slice_one_min_inv(il[303]) - , slice_sel_cd_cpy(il[304]) - , slice_sel_mem_active(il[305]) - , slice_sel_return(il[306]) - , slice_sel_start(il[307]) - , slice_space_id(il[308]) - , slice_val(il[309]) - , lookup_byte_lengths_counts(il[310]) - , lookup_byte_operations_counts(il[311]) - , lookup_cd_value_counts(il[312]) - , lookup_ret_value_counts(il[313]) - , lookup_opcode_gas_counts(il[314]) - , range_check_l2_gas_hi_counts(il[315]) - , range_check_l2_gas_lo_counts(il[316]) - , range_check_da_gas_hi_counts(il[317]) - , range_check_da_gas_lo_counts(il[318]) - , kernel_output_lookup_counts(il[319]) - , lookup_into_kernel_counts(il[320]) - , incl_main_tag_err_counts(il[321]) - , incl_mem_tag_err_counts(il[322]) - , lookup_mem_rng_chk_lo_counts(il[323]) - , lookup_mem_rng_chk_mid_counts(il[324]) - , lookup_mem_rng_chk_hi_counts(il[325]) - , lookup_pow_2_0_counts(il[326]) - , lookup_pow_2_1_counts(il[327]) - , lookup_u8_0_counts(il[328]) - , lookup_u8_1_counts(il[329]) - , lookup_u16_0_counts(il[330]) - , lookup_u16_1_counts(il[331]) - , lookup_u16_2_counts(il[332]) - , lookup_u16_3_counts(il[333]) - , lookup_u16_4_counts(il[334]) - , lookup_u16_5_counts(il[335]) - , lookup_u16_6_counts(il[336]) - , lookup_u16_7_counts(il[337]) - , lookup_u16_8_counts(il[338]) - , lookup_u16_9_counts(il[339]) - , lookup_u16_10_counts(il[340]) - , lookup_u16_11_counts(il[341]) - , lookup_u16_12_counts(il[342]) - , lookup_u16_13_counts(il[343]) - , lookup_u16_14_counts(il[344]) - , lookup_div_u16_0_counts(il[345]) - , lookup_div_u16_1_counts(il[346]) - , lookup_div_u16_2_counts(il[347]) - , lookup_div_u16_3_counts(il[348]) - , lookup_div_u16_4_counts(il[349]) - , lookup_div_u16_5_counts(il[350]) - , lookup_div_u16_6_counts(il[351]) - , lookup_div_u16_7_counts(il[352]) - , perm_slice_mem(il[353]) - , perm_main_alu(il[354]) - , perm_main_bin(il[355]) - , perm_main_conv(il[356]) - , perm_main_pos2_perm(il[357]) - , perm_main_pedersen(il[358]) - , perm_main_slice(il[359]) - , perm_main_mem_a(il[360]) - , perm_main_mem_b(il[361]) - , perm_main_mem_c(il[362]) - , perm_main_mem_d(il[363]) - , perm_main_mem_ind_addr_a(il[364]) - , perm_main_mem_ind_addr_b(il[365]) - , perm_main_mem_ind_addr_c(il[366]) - , perm_main_mem_ind_addr_d(il[367]) - , lookup_byte_lengths(il[368]) - , lookup_byte_operations(il[369]) - , lookup_cd_value(il[370]) - , lookup_ret_value(il[371]) - , lookup_opcode_gas(il[372]) - , range_check_l2_gas_hi(il[373]) - , range_check_l2_gas_lo(il[374]) - , range_check_da_gas_hi(il[375]) - , range_check_da_gas_lo(il[376]) - , kernel_output_lookup(il[377]) - , lookup_into_kernel(il[378]) - , incl_main_tag_err(il[379]) - , incl_mem_tag_err(il[380]) - , lookup_mem_rng_chk_lo(il[381]) - , lookup_mem_rng_chk_mid(il[382]) - , lookup_mem_rng_chk_hi(il[383]) - , lookup_pow_2_0(il[384]) - , lookup_pow_2_1(il[385]) - , lookup_u8_0(il[386]) - , lookup_u8_1(il[387]) - , lookup_u16_0(il[388]) - , lookup_u16_1(il[389]) - , lookup_u16_2(il[390]) - , lookup_u16_3(il[391]) - , lookup_u16_4(il[392]) - , lookup_u16_5(il[393]) - , lookup_u16_6(il[394]) - , lookup_u16_7(il[395]) - , lookup_u16_8(il[396]) - , lookup_u16_9(il[397]) - , lookup_u16_10(il[398]) - , lookup_u16_11(il[399]) - , lookup_u16_12(il[400]) - , lookup_u16_13(il[401]) - , lookup_u16_14(il[402]) - , lookup_div_u16_0(il[403]) - , lookup_div_u16_1(il[404]) - , lookup_div_u16_2(il[405]) - , lookup_div_u16_3(il[406]) - , lookup_div_u16_4(il[407]) - , lookup_div_u16_5(il[408]) - , lookup_div_u16_6(il[409]) - , lookup_div_u16_7(il[410]) - , alu_a_hi_shift(il[411]) - , alu_a_lo_shift(il[412]) - , alu_b_hi_shift(il[413]) - , alu_b_lo_shift(il[414]) - , alu_cmp_rng_ctr_shift(il[415]) - , alu_div_u16_r0_shift(il[416]) - , alu_div_u16_r1_shift(il[417]) - , alu_div_u16_r2_shift(il[418]) - , alu_div_u16_r3_shift(il[419]) - , alu_div_u16_r4_shift(il[420]) - , alu_div_u16_r5_shift(il[421]) - , alu_div_u16_r6_shift(il[422]) - , alu_div_u16_r7_shift(il[423]) - , alu_op_add_shift(il[424]) - , alu_op_cast_prev_shift(il[425]) - , alu_op_cast_shift(il[426]) - , alu_op_div_shift(il[427]) - , alu_op_mul_shift(il[428]) - , alu_op_shl_shift(il[429]) - , alu_op_shr_shift(il[430]) - , alu_op_sub_shift(il[431]) - , alu_p_sub_a_hi_shift(il[432]) - , alu_p_sub_a_lo_shift(il[433]) - , alu_p_sub_b_hi_shift(il[434]) - , alu_p_sub_b_lo_shift(il[435]) - , alu_sel_alu_shift(il[436]) - , alu_sel_cmp_shift(il[437]) - , alu_sel_div_rng_chk_shift(il[438]) - , alu_sel_rng_chk_lookup_shift(il[439]) - , alu_sel_rng_chk_shift(il[440]) - , alu_u16_r0_shift(il[441]) - , alu_u16_r1_shift(il[442]) - , alu_u16_r2_shift(il[443]) - , alu_u16_r3_shift(il[444]) - , alu_u16_r4_shift(il[445]) - , alu_u16_r5_shift(il[446]) - , alu_u16_r6_shift(il[447]) - , alu_u8_r0_shift(il[448]) - , alu_u8_r1_shift(il[449]) - , binary_acc_ia_shift(il[450]) - , binary_acc_ib_shift(il[451]) - , binary_acc_ic_shift(il[452]) - , binary_mem_tag_ctr_shift(il[453]) - , binary_op_id_shift(il[454]) - , kernel_emit_l2_to_l1_msg_write_offset_shift(il[455]) - , kernel_emit_note_hash_write_offset_shift(il[456]) - , kernel_emit_nullifier_write_offset_shift(il[457]) - , kernel_emit_unencrypted_log_write_offset_shift(il[458]) - , kernel_l1_to_l2_msg_exists_write_offset_shift(il[459]) - , kernel_note_hash_exist_write_offset_shift(il[460]) - , kernel_nullifier_exists_write_offset_shift(il[461]) - , kernel_nullifier_non_exists_write_offset_shift(il[462]) - , kernel_side_effect_counter_shift(il[463]) - , kernel_sload_write_offset_shift(il[464]) - , kernel_sstore_write_offset_shift(il[465]) - , main_da_gas_remaining_shift(il[466]) - , main_internal_return_ptr_shift(il[467]) - , main_l2_gas_remaining_shift(il[468]) - , main_pc_shift(il[469]) - , mem_glob_addr_shift(il[470]) - , mem_rw_shift(il[471]) - , mem_sel_mem_shift(il[472]) - , mem_tag_shift(il[473]) - , mem_tsp_shift(il[474]) - , mem_val_shift(il[475]) - , slice_addr_shift(il[476]) - , slice_clk_shift(il[477]) - , slice_cnt_shift(il[478]) - , slice_col_offset_shift(il[479]) - , slice_sel_cd_cpy_shift(il[480]) - , slice_sel_mem_active_shift(il[481]) - , slice_sel_return_shift(il[482]) - , slice_sel_start_shift(il[483]) - , slice_space_id_shift(il[484]) - {} + AllConstRefValues(const RefArray& il); }; /** @@ -807,523 +322,20 @@ class AvmFlavor { ProverPolynomials& operator=(ProverPolynomials&& o) noexcept = default; ~ProverPolynomials() = default; - ProverPolynomials(ProvingKey& proving_key) - { - for (auto [prover_poly, key_poly] : zip_view(this->get_unshifted(), proving_key.get_all())) { - ASSERT(flavor_get_label(*this, prover_poly) == flavor_get_label(proving_key, key_poly)); - prover_poly = key_poly.share(); - } - for (auto [prover_poly, key_poly] : zip_view(this->get_shifted(), proving_key.get_to_be_shifted())) { - ASSERT(flavor_get_label(*this, prover_poly) == (flavor_get_label(proving_key, key_poly) + "_shift")); - prover_poly = key_poly.shifted(); - } - } + ProverPolynomials(ProvingKey& proving_key); [[nodiscard]] size_t get_polynomial_size() const { return kernel_kernel_inputs.size(); } /** * @brief Returns the evaluations of all prover polynomials at one point on the boolean hypercube, which * represents one row in the execution trace. */ - [[nodiscard]] AllConstRefValues get_row(size_t row_idx) const - { - return AllConstRefValues(RefArray{ main_clk[row_idx], - main_sel_first[row_idx], - kernel_kernel_inputs[row_idx], - kernel_kernel_value_out[row_idx], - kernel_kernel_side_effect_out[row_idx], - kernel_kernel_metadata_out[row_idx], - main_calldata[row_idx], - main_returndata[row_idx], - alu_a_hi[row_idx], - alu_a_lo[row_idx], - alu_b_hi[row_idx], - alu_b_lo[row_idx], - alu_borrow[row_idx], - alu_cf[row_idx], - alu_clk[row_idx], - alu_cmp_rng_ctr[row_idx], - alu_div_u16_r0[row_idx], - alu_div_u16_r1[row_idx], - alu_div_u16_r2[row_idx], - alu_div_u16_r3[row_idx], - alu_div_u16_r4[row_idx], - alu_div_u16_r5[row_idx], - alu_div_u16_r6[row_idx], - alu_div_u16_r7[row_idx], - alu_divisor_hi[row_idx], - alu_divisor_lo[row_idx], - alu_ff_tag[row_idx], - alu_ia[row_idx], - alu_ib[row_idx], - alu_ic[row_idx], - alu_in_tag[row_idx], - alu_op_add[row_idx], - alu_op_cast[row_idx], - alu_op_cast_prev[row_idx], - alu_op_div[row_idx], - alu_op_div_a_lt_b[row_idx], - alu_op_div_std[row_idx], - alu_op_eq[row_idx], - alu_op_eq_diff_inv[row_idx], - alu_op_lt[row_idx], - alu_op_lte[row_idx], - alu_op_mul[row_idx], - alu_op_not[row_idx], - alu_op_shl[row_idx], - alu_op_shr[row_idx], - alu_op_sub[row_idx], - alu_p_a_borrow[row_idx], - alu_p_b_borrow[row_idx], - alu_p_sub_a_hi[row_idx], - alu_p_sub_a_lo[row_idx], - alu_p_sub_b_hi[row_idx], - alu_p_sub_b_lo[row_idx], - alu_partial_prod_hi[row_idx], - alu_partial_prod_lo[row_idx], - alu_quotient_hi[row_idx], - alu_quotient_lo[row_idx], - alu_remainder[row_idx], - alu_res_hi[row_idx], - alu_res_lo[row_idx], - alu_sel_alu[row_idx], - alu_sel_cmp[row_idx], - alu_sel_div_rng_chk[row_idx], - alu_sel_rng_chk[row_idx], - alu_sel_rng_chk_lookup[row_idx], - alu_sel_shift_which[row_idx], - alu_shift_lt_bit_len[row_idx], - alu_t_sub_s_bits[row_idx], - alu_two_pow_s[row_idx], - alu_two_pow_t_sub_s[row_idx], - alu_u128_tag[row_idx], - alu_u16_r0[row_idx], - alu_u16_r1[row_idx], - alu_u16_r10[row_idx], - alu_u16_r11[row_idx], - alu_u16_r12[row_idx], - alu_u16_r13[row_idx], - alu_u16_r14[row_idx], - alu_u16_r2[row_idx], - alu_u16_r3[row_idx], - alu_u16_r4[row_idx], - alu_u16_r5[row_idx], - alu_u16_r6[row_idx], - alu_u16_r7[row_idx], - alu_u16_r8[row_idx], - alu_u16_r9[row_idx], - alu_u16_tag[row_idx], - alu_u32_tag[row_idx], - alu_u64_tag[row_idx], - alu_u8_r0[row_idx], - alu_u8_r1[row_idx], - alu_u8_tag[row_idx], - binary_acc_ia[row_idx], - binary_acc_ib[row_idx], - binary_acc_ic[row_idx], - binary_clk[row_idx], - binary_ia_bytes[row_idx], - binary_ib_bytes[row_idx], - binary_ic_bytes[row_idx], - binary_in_tag[row_idx], - binary_mem_tag_ctr[row_idx], - binary_mem_tag_ctr_inv[row_idx], - binary_op_id[row_idx], - binary_sel_bin[row_idx], - binary_start[row_idx], - byte_lookup_sel_bin[row_idx], - byte_lookup_table_byte_lengths[row_idx], - byte_lookup_table_in_tags[row_idx], - byte_lookup_table_input_a[row_idx], - byte_lookup_table_input_b[row_idx], - byte_lookup_table_op_id[row_idx], - byte_lookup_table_output[row_idx], - conversion_clk[row_idx], - conversion_input[row_idx], - conversion_num_limbs[row_idx], - conversion_radix[row_idx], - conversion_sel_to_radix_le[row_idx], - gas_da_gas_fixed_table[row_idx], - gas_l2_gas_fixed_table[row_idx], - gas_sel_gas_cost[row_idx], - keccakf1600_clk[row_idx], - keccakf1600_input[row_idx], - keccakf1600_output[row_idx], - keccakf1600_sel_keccakf1600[row_idx], - kernel_emit_l2_to_l1_msg_write_offset[row_idx], - kernel_emit_note_hash_write_offset[row_idx], - kernel_emit_nullifier_write_offset[row_idx], - kernel_emit_unencrypted_log_write_offset[row_idx], - kernel_kernel_in_offset[row_idx], - kernel_kernel_out_offset[row_idx], - kernel_l1_to_l2_msg_exists_write_offset[row_idx], - kernel_note_hash_exist_write_offset[row_idx], - kernel_nullifier_exists_write_offset[row_idx], - kernel_nullifier_non_exists_write_offset[row_idx], - kernel_q_public_input_kernel_add_to_table[row_idx], - kernel_q_public_input_kernel_out_add_to_table[row_idx], - kernel_side_effect_counter[row_idx], - kernel_sload_write_offset[row_idx], - kernel_sstore_write_offset[row_idx], - main_abs_da_rem_gas_hi[row_idx], - main_abs_da_rem_gas_lo[row_idx], - main_abs_l2_rem_gas_hi[row_idx], - main_abs_l2_rem_gas_lo[row_idx], - main_alu_in_tag[row_idx], - main_bin_op_id[row_idx], - main_call_ptr[row_idx], - main_da_gas_op_cost[row_idx], - main_da_gas_remaining[row_idx], - main_da_out_of_gas[row_idx], - main_ia[row_idx], - main_ib[row_idx], - main_ic[row_idx], - main_id[row_idx], - main_id_zero[row_idx], - main_ind_addr_a[row_idx], - main_ind_addr_b[row_idx], - main_ind_addr_c[row_idx], - main_ind_addr_d[row_idx], - main_internal_return_ptr[row_idx], - main_inv[row_idx], - main_l2_gas_op_cost[row_idx], - main_l2_gas_remaining[row_idx], - main_l2_out_of_gas[row_idx], - main_mem_addr_a[row_idx], - main_mem_addr_b[row_idx], - main_mem_addr_c[row_idx], - main_mem_addr_d[row_idx], - main_op_err[row_idx], - main_opcode_val[row_idx], - main_pc[row_idx], - main_r_in_tag[row_idx], - main_rwa[row_idx], - main_rwb[row_idx], - main_rwc[row_idx], - main_rwd[row_idx], - main_sel_alu[row_idx], - main_sel_bin[row_idx], - main_sel_calldata[row_idx], - main_sel_gas_accounting_active[row_idx], - main_sel_last[row_idx], - main_sel_mem_op_a[row_idx], - main_sel_mem_op_activate_gas[row_idx], - main_sel_mem_op_b[row_idx], - main_sel_mem_op_c[row_idx], - main_sel_mem_op_d[row_idx], - main_sel_mov_ia_to_ic[row_idx], - main_sel_mov_ib_to_ic[row_idx], - main_sel_op_add[row_idx], - main_sel_op_address[row_idx], - main_sel_op_and[row_idx], - main_sel_op_block_number[row_idx], - main_sel_op_calldata_copy[row_idx], - main_sel_op_cast[row_idx], - main_sel_op_chain_id[row_idx], - main_sel_op_cmov[row_idx], - main_sel_op_coinbase[row_idx], - main_sel_op_dagasleft[row_idx], - main_sel_op_div[row_idx], - main_sel_op_emit_l2_to_l1_msg[row_idx], - main_sel_op_emit_note_hash[row_idx], - main_sel_op_emit_nullifier[row_idx], - main_sel_op_emit_unencrypted_log[row_idx], - main_sel_op_eq[row_idx], - main_sel_op_external_call[row_idx], - main_sel_op_external_return[row_idx], - main_sel_op_fdiv[row_idx], - main_sel_op_fee_per_da_gas[row_idx], - main_sel_op_fee_per_l2_gas[row_idx], - main_sel_op_function_selector[row_idx], - main_sel_op_get_contract_instance[row_idx], - main_sel_op_halt[row_idx], - main_sel_op_internal_call[row_idx], - main_sel_op_internal_return[row_idx], - main_sel_op_jump[row_idx], - main_sel_op_jumpi[row_idx], - main_sel_op_keccak[row_idx], - main_sel_op_l1_to_l2_msg_exists[row_idx], - main_sel_op_l2gasleft[row_idx], - main_sel_op_lt[row_idx], - main_sel_op_lte[row_idx], - main_sel_op_mov[row_idx], - main_sel_op_mul[row_idx], - main_sel_op_not[row_idx], - main_sel_op_note_hash_exists[row_idx], - main_sel_op_nullifier_exists[row_idx], - main_sel_op_or[row_idx], - main_sel_op_pedersen[row_idx], - main_sel_op_poseidon2[row_idx], - main_sel_op_radix_le[row_idx], - main_sel_op_sender[row_idx], - main_sel_op_sha256[row_idx], - main_sel_op_shl[row_idx], - main_sel_op_shr[row_idx], - main_sel_op_sload[row_idx], - main_sel_op_sstore[row_idx], - main_sel_op_storage_address[row_idx], - main_sel_op_sub[row_idx], - main_sel_op_timestamp[row_idx], - main_sel_op_transaction_fee[row_idx], - main_sel_op_version[row_idx], - main_sel_op_xor[row_idx], - main_sel_q_kernel_lookup[row_idx], - main_sel_q_kernel_output_lookup[row_idx], - main_sel_resolve_ind_addr_a[row_idx], - main_sel_resolve_ind_addr_b[row_idx], - main_sel_resolve_ind_addr_c[row_idx], - main_sel_resolve_ind_addr_d[row_idx], - main_sel_returndata[row_idx], - main_sel_rng_16[row_idx], - main_sel_rng_8[row_idx], - main_sel_slice_gadget[row_idx], - main_space_id[row_idx], - main_tag_err[row_idx], - main_w_in_tag[row_idx], - mem_addr[row_idx], - mem_clk[row_idx], - mem_diff_hi[row_idx], - mem_diff_lo[row_idx], - mem_diff_mid[row_idx], - mem_glob_addr[row_idx], - mem_last[row_idx], - mem_lastAccess[row_idx], - mem_one_min_inv[row_idx], - mem_r_in_tag[row_idx], - mem_rw[row_idx], - mem_sel_mem[row_idx], - mem_sel_mov_ia_to_ic[row_idx], - mem_sel_mov_ib_to_ic[row_idx], - mem_sel_op_a[row_idx], - mem_sel_op_b[row_idx], - mem_sel_op_c[row_idx], - mem_sel_op_cmov[row_idx], - mem_sel_op_d[row_idx], - mem_sel_op_slice[row_idx], - mem_sel_resolve_ind_addr_a[row_idx], - mem_sel_resolve_ind_addr_b[row_idx], - mem_sel_resolve_ind_addr_c[row_idx], - mem_sel_resolve_ind_addr_d[row_idx], - mem_sel_rng_chk[row_idx], - mem_skip_check_tag[row_idx], - mem_space_id[row_idx], - mem_tag[row_idx], - mem_tag_err[row_idx], - mem_tsp[row_idx], - mem_val[row_idx], - mem_w_in_tag[row_idx], - pedersen_clk[row_idx], - pedersen_input[row_idx], - pedersen_output[row_idx], - pedersen_sel_pedersen[row_idx], - poseidon2_clk[row_idx], - poseidon2_input[row_idx], - poseidon2_output[row_idx], - poseidon2_sel_poseidon_perm[row_idx], - powers_power_of_2[row_idx], - sha256_clk[row_idx], - sha256_input[row_idx], - sha256_output[row_idx], - sha256_sel_sha256_compression[row_idx], - sha256_state[row_idx], - slice_addr[row_idx], - slice_clk[row_idx], - slice_cnt[row_idx], - slice_col_offset[row_idx], - slice_one_min_inv[row_idx], - slice_sel_cd_cpy[row_idx], - slice_sel_mem_active[row_idx], - slice_sel_return[row_idx], - slice_sel_start[row_idx], - slice_space_id[row_idx], - slice_val[row_idx], - lookup_byte_lengths_counts[row_idx], - lookup_byte_operations_counts[row_idx], - lookup_cd_value_counts[row_idx], - lookup_ret_value_counts[row_idx], - lookup_opcode_gas_counts[row_idx], - range_check_l2_gas_hi_counts[row_idx], - range_check_l2_gas_lo_counts[row_idx], - range_check_da_gas_hi_counts[row_idx], - range_check_da_gas_lo_counts[row_idx], - kernel_output_lookup_counts[row_idx], - lookup_into_kernel_counts[row_idx], - incl_main_tag_err_counts[row_idx], - incl_mem_tag_err_counts[row_idx], - lookup_mem_rng_chk_lo_counts[row_idx], - lookup_mem_rng_chk_mid_counts[row_idx], - lookup_mem_rng_chk_hi_counts[row_idx], - lookup_pow_2_0_counts[row_idx], - lookup_pow_2_1_counts[row_idx], - lookup_u8_0_counts[row_idx], - lookup_u8_1_counts[row_idx], - lookup_u16_0_counts[row_idx], - lookup_u16_1_counts[row_idx], - lookup_u16_2_counts[row_idx], - lookup_u16_3_counts[row_idx], - lookup_u16_4_counts[row_idx], - lookup_u16_5_counts[row_idx], - lookup_u16_6_counts[row_idx], - lookup_u16_7_counts[row_idx], - lookup_u16_8_counts[row_idx], - lookup_u16_9_counts[row_idx], - lookup_u16_10_counts[row_idx], - lookup_u16_11_counts[row_idx], - lookup_u16_12_counts[row_idx], - lookup_u16_13_counts[row_idx], - lookup_u16_14_counts[row_idx], - lookup_div_u16_0_counts[row_idx], - lookup_div_u16_1_counts[row_idx], - lookup_div_u16_2_counts[row_idx], - lookup_div_u16_3_counts[row_idx], - lookup_div_u16_4_counts[row_idx], - lookup_div_u16_5_counts[row_idx], - lookup_div_u16_6_counts[row_idx], - lookup_div_u16_7_counts[row_idx], - perm_slice_mem[row_idx], - perm_main_alu[row_idx], - perm_main_bin[row_idx], - perm_main_conv[row_idx], - perm_main_pos2_perm[row_idx], - perm_main_pedersen[row_idx], - perm_main_slice[row_idx], - perm_main_mem_a[row_idx], - perm_main_mem_b[row_idx], - perm_main_mem_c[row_idx], - perm_main_mem_d[row_idx], - perm_main_mem_ind_addr_a[row_idx], - perm_main_mem_ind_addr_b[row_idx], - perm_main_mem_ind_addr_c[row_idx], - perm_main_mem_ind_addr_d[row_idx], - lookup_byte_lengths[row_idx], - lookup_byte_operations[row_idx], - lookup_cd_value[row_idx], - lookup_ret_value[row_idx], - lookup_opcode_gas[row_idx], - range_check_l2_gas_hi[row_idx], - range_check_l2_gas_lo[row_idx], - range_check_da_gas_hi[row_idx], - range_check_da_gas_lo[row_idx], - kernel_output_lookup[row_idx], - lookup_into_kernel[row_idx], - incl_main_tag_err[row_idx], - incl_mem_tag_err[row_idx], - lookup_mem_rng_chk_lo[row_idx], - lookup_mem_rng_chk_mid[row_idx], - lookup_mem_rng_chk_hi[row_idx], - lookup_pow_2_0[row_idx], - lookup_pow_2_1[row_idx], - lookup_u8_0[row_idx], - lookup_u8_1[row_idx], - lookup_u16_0[row_idx], - lookup_u16_1[row_idx], - lookup_u16_2[row_idx], - lookup_u16_3[row_idx], - lookup_u16_4[row_idx], - lookup_u16_5[row_idx], - lookup_u16_6[row_idx], - lookup_u16_7[row_idx], - lookup_u16_8[row_idx], - lookup_u16_9[row_idx], - lookup_u16_10[row_idx], - lookup_u16_11[row_idx], - lookup_u16_12[row_idx], - lookup_u16_13[row_idx], - lookup_u16_14[row_idx], - lookup_div_u16_0[row_idx], - lookup_div_u16_1[row_idx], - lookup_div_u16_2[row_idx], - lookup_div_u16_3[row_idx], - lookup_div_u16_4[row_idx], - lookup_div_u16_5[row_idx], - lookup_div_u16_6[row_idx], - lookup_div_u16_7[row_idx], - alu_a_hi_shift[row_idx], - alu_a_lo_shift[row_idx], - alu_b_hi_shift[row_idx], - alu_b_lo_shift[row_idx], - alu_cmp_rng_ctr_shift[row_idx], - alu_div_u16_r0_shift[row_idx], - alu_div_u16_r1_shift[row_idx], - alu_div_u16_r2_shift[row_idx], - alu_div_u16_r3_shift[row_idx], - alu_div_u16_r4_shift[row_idx], - alu_div_u16_r5_shift[row_idx], - alu_div_u16_r6_shift[row_idx], - alu_div_u16_r7_shift[row_idx], - alu_op_add_shift[row_idx], - alu_op_cast_prev_shift[row_idx], - alu_op_cast_shift[row_idx], - alu_op_div_shift[row_idx], - alu_op_mul_shift[row_idx], - alu_op_shl_shift[row_idx], - alu_op_shr_shift[row_idx], - alu_op_sub_shift[row_idx], - alu_p_sub_a_hi_shift[row_idx], - alu_p_sub_a_lo_shift[row_idx], - alu_p_sub_b_hi_shift[row_idx], - alu_p_sub_b_lo_shift[row_idx], - alu_sel_alu_shift[row_idx], - alu_sel_cmp_shift[row_idx], - alu_sel_div_rng_chk_shift[row_idx], - alu_sel_rng_chk_lookup_shift[row_idx], - alu_sel_rng_chk_shift[row_idx], - alu_u16_r0_shift[row_idx], - alu_u16_r1_shift[row_idx], - alu_u16_r2_shift[row_idx], - alu_u16_r3_shift[row_idx], - alu_u16_r4_shift[row_idx], - alu_u16_r5_shift[row_idx], - alu_u16_r6_shift[row_idx], - alu_u8_r0_shift[row_idx], - alu_u8_r1_shift[row_idx], - binary_acc_ia_shift[row_idx], - binary_acc_ib_shift[row_idx], - binary_acc_ic_shift[row_idx], - binary_mem_tag_ctr_shift[row_idx], - binary_op_id_shift[row_idx], - kernel_emit_l2_to_l1_msg_write_offset_shift[row_idx], - kernel_emit_note_hash_write_offset_shift[row_idx], - kernel_emit_nullifier_write_offset_shift[row_idx], - kernel_emit_unencrypted_log_write_offset_shift[row_idx], - kernel_l1_to_l2_msg_exists_write_offset_shift[row_idx], - kernel_note_hash_exist_write_offset_shift[row_idx], - kernel_nullifier_exists_write_offset_shift[row_idx], - kernel_nullifier_non_exists_write_offset_shift[row_idx], - kernel_side_effect_counter_shift[row_idx], - kernel_sload_write_offset_shift[row_idx], - kernel_sstore_write_offset_shift[row_idx], - main_da_gas_remaining_shift[row_idx], - main_internal_return_ptr_shift[row_idx], - main_l2_gas_remaining_shift[row_idx], - main_pc_shift[row_idx], - mem_glob_addr_shift[row_idx], - mem_rw_shift[row_idx], - mem_sel_mem_shift[row_idx], - mem_tag_shift[row_idx], - mem_tsp_shift[row_idx], - mem_val_shift[row_idx], - slice_addr_shift[row_idx], - slice_clk_shift[row_idx], - slice_cnt_shift[row_idx], - slice_col_offset_shift[row_idx], - slice_sel_cd_cpy_shift[row_idx], - slice_sel_mem_active_shift[row_idx], - slice_sel_return_shift[row_idx], - slice_sel_start_shift[row_idx], - slice_space_id_shift[row_idx] }); - } + [[nodiscard]] AllConstRefValues get_row(size_t row_idx) const; }; class PartiallyEvaluatedMultivariates : public AllEntities { public: PartiallyEvaluatedMultivariates() = default; - PartiallyEvaluatedMultivariates(const size_t circuit_size) - { - // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) - for (auto& poly : get_all()) { - poly = Polynomial(circuit_size / 2); - } - } + PartiallyEvaluatedMultivariates(const size_t circuit_size); }; /** @@ -1356,420 +368,7 @@ class AvmFlavor { using Base = AllEntities; public: - CommitmentLabels() - { - Base::main_clk = "MAIN_CLK"; - Base::main_sel_first = "MAIN_SEL_FIRST"; - Base::kernel_kernel_inputs = "KERNEL_KERNEL_INPUTS"; - Base::kernel_kernel_value_out = "KERNEL_KERNEL_VALUE_OUT"; - Base::kernel_kernel_side_effect_out = "KERNEL_KERNEL_SIDE_EFFECT_OUT"; - Base::kernel_kernel_metadata_out = "KERNEL_KERNEL_METADATA_OUT"; - Base::main_calldata = "MAIN_CALLDATA"; - Base::main_returndata = "MAIN_RETURNDATA"; - Base::alu_a_hi = "ALU_A_HI"; - Base::alu_a_lo = "ALU_A_LO"; - Base::alu_b_hi = "ALU_B_HI"; - Base::alu_b_lo = "ALU_B_LO"; - Base::alu_borrow = "ALU_BORROW"; - Base::alu_cf = "ALU_CF"; - Base::alu_clk = "ALU_CLK"; - Base::alu_cmp_rng_ctr = "ALU_CMP_RNG_CTR"; - Base::alu_div_u16_r0 = "ALU_DIV_U16_R0"; - Base::alu_div_u16_r1 = "ALU_DIV_U16_R1"; - Base::alu_div_u16_r2 = "ALU_DIV_U16_R2"; - Base::alu_div_u16_r3 = "ALU_DIV_U16_R3"; - Base::alu_div_u16_r4 = "ALU_DIV_U16_R4"; - Base::alu_div_u16_r5 = "ALU_DIV_U16_R5"; - Base::alu_div_u16_r6 = "ALU_DIV_U16_R6"; - Base::alu_div_u16_r7 = "ALU_DIV_U16_R7"; - Base::alu_divisor_hi = "ALU_DIVISOR_HI"; - Base::alu_divisor_lo = "ALU_DIVISOR_LO"; - Base::alu_ff_tag = "ALU_FF_TAG"; - Base::alu_ia = "ALU_IA"; - Base::alu_ib = "ALU_IB"; - Base::alu_ic = "ALU_IC"; - Base::alu_in_tag = "ALU_IN_TAG"; - Base::alu_op_add = "ALU_OP_ADD"; - Base::alu_op_cast = "ALU_OP_CAST"; - Base::alu_op_cast_prev = "ALU_OP_CAST_PREV"; - Base::alu_op_div = "ALU_OP_DIV"; - Base::alu_op_div_a_lt_b = "ALU_OP_DIV_A_LT_B"; - Base::alu_op_div_std = "ALU_OP_DIV_STD"; - Base::alu_op_eq = "ALU_OP_EQ"; - Base::alu_op_eq_diff_inv = "ALU_OP_EQ_DIFF_INV"; - Base::alu_op_lt = "ALU_OP_LT"; - Base::alu_op_lte = "ALU_OP_LTE"; - Base::alu_op_mul = "ALU_OP_MUL"; - Base::alu_op_not = "ALU_OP_NOT"; - Base::alu_op_shl = "ALU_OP_SHL"; - Base::alu_op_shr = "ALU_OP_SHR"; - Base::alu_op_sub = "ALU_OP_SUB"; - Base::alu_p_a_borrow = "ALU_P_A_BORROW"; - Base::alu_p_b_borrow = "ALU_P_B_BORROW"; - Base::alu_p_sub_a_hi = "ALU_P_SUB_A_HI"; - Base::alu_p_sub_a_lo = "ALU_P_SUB_A_LO"; - Base::alu_p_sub_b_hi = "ALU_P_SUB_B_HI"; - Base::alu_p_sub_b_lo = "ALU_P_SUB_B_LO"; - Base::alu_partial_prod_hi = "ALU_PARTIAL_PROD_HI"; - Base::alu_partial_prod_lo = "ALU_PARTIAL_PROD_LO"; - Base::alu_quotient_hi = "ALU_QUOTIENT_HI"; - Base::alu_quotient_lo = "ALU_QUOTIENT_LO"; - Base::alu_remainder = "ALU_REMAINDER"; - Base::alu_res_hi = "ALU_RES_HI"; - Base::alu_res_lo = "ALU_RES_LO"; - Base::alu_sel_alu = "ALU_SEL_ALU"; - Base::alu_sel_cmp = "ALU_SEL_CMP"; - Base::alu_sel_div_rng_chk = "ALU_SEL_DIV_RNG_CHK"; - Base::alu_sel_rng_chk = "ALU_SEL_RNG_CHK"; - Base::alu_sel_rng_chk_lookup = "ALU_SEL_RNG_CHK_LOOKUP"; - Base::alu_sel_shift_which = "ALU_SEL_SHIFT_WHICH"; - Base::alu_shift_lt_bit_len = "ALU_SHIFT_LT_BIT_LEN"; - Base::alu_t_sub_s_bits = "ALU_T_SUB_S_BITS"; - Base::alu_two_pow_s = "ALU_TWO_POW_S"; - Base::alu_two_pow_t_sub_s = "ALU_TWO_POW_T_SUB_S"; - Base::alu_u128_tag = "ALU_U128_TAG"; - Base::alu_u16_r0 = "ALU_U16_R0"; - Base::alu_u16_r1 = "ALU_U16_R1"; - Base::alu_u16_r10 = "ALU_U16_R10"; - Base::alu_u16_r11 = "ALU_U16_R11"; - Base::alu_u16_r12 = "ALU_U16_R12"; - Base::alu_u16_r13 = "ALU_U16_R13"; - Base::alu_u16_r14 = "ALU_U16_R14"; - Base::alu_u16_r2 = "ALU_U16_R2"; - Base::alu_u16_r3 = "ALU_U16_R3"; - Base::alu_u16_r4 = "ALU_U16_R4"; - Base::alu_u16_r5 = "ALU_U16_R5"; - Base::alu_u16_r6 = "ALU_U16_R6"; - Base::alu_u16_r7 = "ALU_U16_R7"; - Base::alu_u16_r8 = "ALU_U16_R8"; - Base::alu_u16_r9 = "ALU_U16_R9"; - Base::alu_u16_tag = "ALU_U16_TAG"; - Base::alu_u32_tag = "ALU_U32_TAG"; - Base::alu_u64_tag = "ALU_U64_TAG"; - Base::alu_u8_r0 = "ALU_U8_R0"; - Base::alu_u8_r1 = "ALU_U8_R1"; - Base::alu_u8_tag = "ALU_U8_TAG"; - Base::binary_acc_ia = "BINARY_ACC_IA"; - Base::binary_acc_ib = "BINARY_ACC_IB"; - Base::binary_acc_ic = "BINARY_ACC_IC"; - Base::binary_clk = "BINARY_CLK"; - Base::binary_ia_bytes = "BINARY_IA_BYTES"; - Base::binary_ib_bytes = "BINARY_IB_BYTES"; - Base::binary_ic_bytes = "BINARY_IC_BYTES"; - Base::binary_in_tag = "BINARY_IN_TAG"; - Base::binary_mem_tag_ctr = "BINARY_MEM_TAG_CTR"; - Base::binary_mem_tag_ctr_inv = "BINARY_MEM_TAG_CTR_INV"; - Base::binary_op_id = "BINARY_OP_ID"; - Base::binary_sel_bin = "BINARY_SEL_BIN"; - Base::binary_start = "BINARY_START"; - Base::byte_lookup_sel_bin = "BYTE_LOOKUP_SEL_BIN"; - Base::byte_lookup_table_byte_lengths = "BYTE_LOOKUP_TABLE_BYTE_LENGTHS"; - Base::byte_lookup_table_in_tags = "BYTE_LOOKUP_TABLE_IN_TAGS"; - Base::byte_lookup_table_input_a = "BYTE_LOOKUP_TABLE_INPUT_A"; - Base::byte_lookup_table_input_b = "BYTE_LOOKUP_TABLE_INPUT_B"; - Base::byte_lookup_table_op_id = "BYTE_LOOKUP_TABLE_OP_ID"; - Base::byte_lookup_table_output = "BYTE_LOOKUP_TABLE_OUTPUT"; - Base::conversion_clk = "CONVERSION_CLK"; - Base::conversion_input = "CONVERSION_INPUT"; - Base::conversion_num_limbs = "CONVERSION_NUM_LIMBS"; - Base::conversion_radix = "CONVERSION_RADIX"; - Base::conversion_sel_to_radix_le = "CONVERSION_SEL_TO_RADIX_LE"; - Base::gas_da_gas_fixed_table = "GAS_DA_GAS_FIXED_TABLE"; - Base::gas_l2_gas_fixed_table = "GAS_L2_GAS_FIXED_TABLE"; - Base::gas_sel_gas_cost = "GAS_SEL_GAS_COST"; - Base::keccakf1600_clk = "KECCAKF1600_CLK"; - Base::keccakf1600_input = "KECCAKF1600_INPUT"; - Base::keccakf1600_output = "KECCAKF1600_OUTPUT"; - Base::keccakf1600_sel_keccakf1600 = "KECCAKF1600_SEL_KECCAKF1600"; - Base::kernel_emit_l2_to_l1_msg_write_offset = "KERNEL_EMIT_L2_TO_L1_MSG_WRITE_OFFSET"; - Base::kernel_emit_note_hash_write_offset = "KERNEL_EMIT_NOTE_HASH_WRITE_OFFSET"; - Base::kernel_emit_nullifier_write_offset = "KERNEL_EMIT_NULLIFIER_WRITE_OFFSET"; - Base::kernel_emit_unencrypted_log_write_offset = "KERNEL_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET"; - Base::kernel_kernel_in_offset = "KERNEL_KERNEL_IN_OFFSET"; - Base::kernel_kernel_out_offset = "KERNEL_KERNEL_OUT_OFFSET"; - Base::kernel_l1_to_l2_msg_exists_write_offset = "KERNEL_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET"; - Base::kernel_note_hash_exist_write_offset = "KERNEL_NOTE_HASH_EXIST_WRITE_OFFSET"; - Base::kernel_nullifier_exists_write_offset = "KERNEL_NULLIFIER_EXISTS_WRITE_OFFSET"; - Base::kernel_nullifier_non_exists_write_offset = "KERNEL_NULLIFIER_NON_EXISTS_WRITE_OFFSET"; - Base::kernel_q_public_input_kernel_add_to_table = "KERNEL_Q_PUBLIC_INPUT_KERNEL_ADD_TO_TABLE"; - Base::kernel_q_public_input_kernel_out_add_to_table = "KERNEL_Q_PUBLIC_INPUT_KERNEL_OUT_ADD_TO_TABLE"; - Base::kernel_side_effect_counter = "KERNEL_SIDE_EFFECT_COUNTER"; - Base::kernel_sload_write_offset = "KERNEL_SLOAD_WRITE_OFFSET"; - Base::kernel_sstore_write_offset = "KERNEL_SSTORE_WRITE_OFFSET"; - Base::main_abs_da_rem_gas_hi = "MAIN_ABS_DA_REM_GAS_HI"; - Base::main_abs_da_rem_gas_lo = "MAIN_ABS_DA_REM_GAS_LO"; - Base::main_abs_l2_rem_gas_hi = "MAIN_ABS_L2_REM_GAS_HI"; - Base::main_abs_l2_rem_gas_lo = "MAIN_ABS_L2_REM_GAS_LO"; - Base::main_alu_in_tag = "MAIN_ALU_IN_TAG"; - Base::main_bin_op_id = "MAIN_BIN_OP_ID"; - Base::main_call_ptr = "MAIN_CALL_PTR"; - Base::main_da_gas_op_cost = "MAIN_DA_GAS_OP_COST"; - Base::main_da_gas_remaining = "MAIN_DA_GAS_REMAINING"; - Base::main_da_out_of_gas = "MAIN_DA_OUT_OF_GAS"; - Base::main_ia = "MAIN_IA"; - Base::main_ib = "MAIN_IB"; - Base::main_ic = "MAIN_IC"; - Base::main_id = "MAIN_ID"; - Base::main_id_zero = "MAIN_ID_ZERO"; - Base::main_ind_addr_a = "MAIN_IND_ADDR_A"; - Base::main_ind_addr_b = "MAIN_IND_ADDR_B"; - Base::main_ind_addr_c = "MAIN_IND_ADDR_C"; - Base::main_ind_addr_d = "MAIN_IND_ADDR_D"; - Base::main_internal_return_ptr = "MAIN_INTERNAL_RETURN_PTR"; - Base::main_inv = "MAIN_INV"; - Base::main_l2_gas_op_cost = "MAIN_L2_GAS_OP_COST"; - Base::main_l2_gas_remaining = "MAIN_L2_GAS_REMAINING"; - 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"; - Base::main_mem_addr_c = "MAIN_MEM_ADDR_C"; - Base::main_mem_addr_d = "MAIN_MEM_ADDR_D"; - Base::main_op_err = "MAIN_OP_ERR"; - Base::main_opcode_val = "MAIN_OPCODE_VAL"; - Base::main_pc = "MAIN_PC"; - Base::main_r_in_tag = "MAIN_R_IN_TAG"; - Base::main_rwa = "MAIN_RWA"; - Base::main_rwb = "MAIN_RWB"; - Base::main_rwc = "MAIN_RWC"; - Base::main_rwd = "MAIN_RWD"; - Base::main_sel_alu = "MAIN_SEL_ALU"; - Base::main_sel_bin = "MAIN_SEL_BIN"; - Base::main_sel_calldata = "MAIN_SEL_CALLDATA"; - Base::main_sel_gas_accounting_active = "MAIN_SEL_GAS_ACCOUNTING_ACTIVE"; - Base::main_sel_last = "MAIN_SEL_LAST"; - Base::main_sel_mem_op_a = "MAIN_SEL_MEM_OP_A"; - Base::main_sel_mem_op_activate_gas = "MAIN_SEL_MEM_OP_ACTIVATE_GAS"; - Base::main_sel_mem_op_b = "MAIN_SEL_MEM_OP_B"; - Base::main_sel_mem_op_c = "MAIN_SEL_MEM_OP_C"; - Base::main_sel_mem_op_d = "MAIN_SEL_MEM_OP_D"; - Base::main_sel_mov_ia_to_ic = "MAIN_SEL_MOV_IA_TO_IC"; - Base::main_sel_mov_ib_to_ic = "MAIN_SEL_MOV_IB_TO_IC"; - Base::main_sel_op_add = "MAIN_SEL_OP_ADD"; - Base::main_sel_op_address = "MAIN_SEL_OP_ADDRESS"; - Base::main_sel_op_and = "MAIN_SEL_OP_AND"; - Base::main_sel_op_block_number = "MAIN_SEL_OP_BLOCK_NUMBER"; - Base::main_sel_op_calldata_copy = "MAIN_SEL_OP_CALLDATA_COPY"; - Base::main_sel_op_cast = "MAIN_SEL_OP_CAST"; - Base::main_sel_op_chain_id = "MAIN_SEL_OP_CHAIN_ID"; - Base::main_sel_op_cmov = "MAIN_SEL_OP_CMOV"; - Base::main_sel_op_coinbase = "MAIN_SEL_OP_COINBASE"; - Base::main_sel_op_dagasleft = "MAIN_SEL_OP_DAGASLEFT"; - Base::main_sel_op_div = "MAIN_SEL_OP_DIV"; - Base::main_sel_op_emit_l2_to_l1_msg = "MAIN_SEL_OP_EMIT_L2_TO_L1_MSG"; - Base::main_sel_op_emit_note_hash = "MAIN_SEL_OP_EMIT_NOTE_HASH"; - Base::main_sel_op_emit_nullifier = "MAIN_SEL_OP_EMIT_NULLIFIER"; - Base::main_sel_op_emit_unencrypted_log = "MAIN_SEL_OP_EMIT_UNENCRYPTED_LOG"; - Base::main_sel_op_eq = "MAIN_SEL_OP_EQ"; - Base::main_sel_op_external_call = "MAIN_SEL_OP_EXTERNAL_CALL"; - Base::main_sel_op_external_return = "MAIN_SEL_OP_EXTERNAL_RETURN"; - Base::main_sel_op_fdiv = "MAIN_SEL_OP_FDIV"; - Base::main_sel_op_fee_per_da_gas = "MAIN_SEL_OP_FEE_PER_DA_GAS"; - Base::main_sel_op_fee_per_l2_gas = "MAIN_SEL_OP_FEE_PER_L2_GAS"; - Base::main_sel_op_function_selector = "MAIN_SEL_OP_FUNCTION_SELECTOR"; - Base::main_sel_op_get_contract_instance = "MAIN_SEL_OP_GET_CONTRACT_INSTANCE"; - Base::main_sel_op_halt = "MAIN_SEL_OP_HALT"; - Base::main_sel_op_internal_call = "MAIN_SEL_OP_INTERNAL_CALL"; - Base::main_sel_op_internal_return = "MAIN_SEL_OP_INTERNAL_RETURN"; - Base::main_sel_op_jump = "MAIN_SEL_OP_JUMP"; - Base::main_sel_op_jumpi = "MAIN_SEL_OP_JUMPI"; - Base::main_sel_op_keccak = "MAIN_SEL_OP_KECCAK"; - Base::main_sel_op_l1_to_l2_msg_exists = "MAIN_SEL_OP_L1_TO_L2_MSG_EXISTS"; - Base::main_sel_op_l2gasleft = "MAIN_SEL_OP_L2GASLEFT"; - Base::main_sel_op_lt = "MAIN_SEL_OP_LT"; - Base::main_sel_op_lte = "MAIN_SEL_OP_LTE"; - Base::main_sel_op_mov = "MAIN_SEL_OP_MOV"; - Base::main_sel_op_mul = "MAIN_SEL_OP_MUL"; - Base::main_sel_op_not = "MAIN_SEL_OP_NOT"; - Base::main_sel_op_note_hash_exists = "MAIN_SEL_OP_NOTE_HASH_EXISTS"; - Base::main_sel_op_nullifier_exists = "MAIN_SEL_OP_NULLIFIER_EXISTS"; - Base::main_sel_op_or = "MAIN_SEL_OP_OR"; - Base::main_sel_op_pedersen = "MAIN_SEL_OP_PEDERSEN"; - Base::main_sel_op_poseidon2 = "MAIN_SEL_OP_POSEIDON2"; - Base::main_sel_op_radix_le = "MAIN_SEL_OP_RADIX_LE"; - Base::main_sel_op_sender = "MAIN_SEL_OP_SENDER"; - Base::main_sel_op_sha256 = "MAIN_SEL_OP_SHA256"; - Base::main_sel_op_shl = "MAIN_SEL_OP_SHL"; - Base::main_sel_op_shr = "MAIN_SEL_OP_SHR"; - Base::main_sel_op_sload = "MAIN_SEL_OP_SLOAD"; - Base::main_sel_op_sstore = "MAIN_SEL_OP_SSTORE"; - Base::main_sel_op_storage_address = "MAIN_SEL_OP_STORAGE_ADDRESS"; - Base::main_sel_op_sub = "MAIN_SEL_OP_SUB"; - Base::main_sel_op_timestamp = "MAIN_SEL_OP_TIMESTAMP"; - Base::main_sel_op_transaction_fee = "MAIN_SEL_OP_TRANSACTION_FEE"; - Base::main_sel_op_version = "MAIN_SEL_OP_VERSION"; - Base::main_sel_op_xor = "MAIN_SEL_OP_XOR"; - Base::main_sel_q_kernel_lookup = "MAIN_SEL_Q_KERNEL_LOOKUP"; - Base::main_sel_q_kernel_output_lookup = "MAIN_SEL_Q_KERNEL_OUTPUT_LOOKUP"; - Base::main_sel_resolve_ind_addr_a = "MAIN_SEL_RESOLVE_IND_ADDR_A"; - Base::main_sel_resolve_ind_addr_b = "MAIN_SEL_RESOLVE_IND_ADDR_B"; - Base::main_sel_resolve_ind_addr_c = "MAIN_SEL_RESOLVE_IND_ADDR_C"; - Base::main_sel_resolve_ind_addr_d = "MAIN_SEL_RESOLVE_IND_ADDR_D"; - Base::main_sel_returndata = "MAIN_SEL_RETURNDATA"; - Base::main_sel_rng_16 = "MAIN_SEL_RNG_16"; - Base::main_sel_rng_8 = "MAIN_SEL_RNG_8"; - Base::main_sel_slice_gadget = "MAIN_SEL_SLICE_GADGET"; - Base::main_space_id = "MAIN_SPACE_ID"; - Base::main_tag_err = "MAIN_TAG_ERR"; - Base::main_w_in_tag = "MAIN_W_IN_TAG"; - Base::mem_addr = "MEM_ADDR"; - Base::mem_clk = "MEM_CLK"; - Base::mem_diff_hi = "MEM_DIFF_HI"; - Base::mem_diff_lo = "MEM_DIFF_LO"; - Base::mem_diff_mid = "MEM_DIFF_MID"; - Base::mem_glob_addr = "MEM_GLOB_ADDR"; - Base::mem_last = "MEM_LAST"; - Base::mem_lastAccess = "MEM_LAST_ACCESS"; - Base::mem_one_min_inv = "MEM_ONE_MIN_INV"; - Base::mem_r_in_tag = "MEM_R_IN_TAG"; - Base::mem_rw = "MEM_RW"; - Base::mem_sel_mem = "MEM_SEL_MEM"; - Base::mem_sel_mov_ia_to_ic = "MEM_SEL_MOV_IA_TO_IC"; - Base::mem_sel_mov_ib_to_ic = "MEM_SEL_MOV_IB_TO_IC"; - Base::mem_sel_op_a = "MEM_SEL_OP_A"; - Base::mem_sel_op_b = "MEM_SEL_OP_B"; - Base::mem_sel_op_c = "MEM_SEL_OP_C"; - Base::mem_sel_op_cmov = "MEM_SEL_OP_CMOV"; - Base::mem_sel_op_d = "MEM_SEL_OP_D"; - Base::mem_sel_op_slice = "MEM_SEL_OP_SLICE"; - Base::mem_sel_resolve_ind_addr_a = "MEM_SEL_RESOLVE_IND_ADDR_A"; - Base::mem_sel_resolve_ind_addr_b = "MEM_SEL_RESOLVE_IND_ADDR_B"; - Base::mem_sel_resolve_ind_addr_c = "MEM_SEL_RESOLVE_IND_ADDR_C"; - Base::mem_sel_resolve_ind_addr_d = "MEM_SEL_RESOLVE_IND_ADDR_D"; - Base::mem_sel_rng_chk = "MEM_SEL_RNG_CHK"; - Base::mem_skip_check_tag = "MEM_SKIP_CHECK_TAG"; - Base::mem_space_id = "MEM_SPACE_ID"; - Base::mem_tag = "MEM_TAG"; - Base::mem_tag_err = "MEM_TAG_ERR"; - Base::mem_tsp = "MEM_TSP"; - Base::mem_val = "MEM_VAL"; - Base::mem_w_in_tag = "MEM_W_IN_TAG"; - Base::pedersen_clk = "PEDERSEN_CLK"; - Base::pedersen_input = "PEDERSEN_INPUT"; - Base::pedersen_output = "PEDERSEN_OUTPUT"; - Base::pedersen_sel_pedersen = "PEDERSEN_SEL_PEDERSEN"; - Base::poseidon2_clk = "POSEIDON2_CLK"; - Base::poseidon2_input = "POSEIDON2_INPUT"; - Base::poseidon2_output = "POSEIDON2_OUTPUT"; - Base::poseidon2_sel_poseidon_perm = "POSEIDON2_SEL_POSEIDON_PERM"; - Base::powers_power_of_2 = "POWERS_POWER_OF_2"; - Base::sha256_clk = "SHA256_CLK"; - Base::sha256_input = "SHA256_INPUT"; - Base::sha256_output = "SHA256_OUTPUT"; - Base::sha256_sel_sha256_compression = "SHA256_SEL_SHA256_COMPRESSION"; - Base::sha256_state = "SHA256_STATE"; - Base::slice_addr = "SLICE_ADDR"; - Base::slice_clk = "SLICE_CLK"; - Base::slice_cnt = "SLICE_CNT"; - Base::slice_col_offset = "SLICE_COL_OFFSET"; - Base::slice_one_min_inv = "SLICE_ONE_MIN_INV"; - Base::slice_sel_cd_cpy = "SLICE_SEL_CD_CPY"; - Base::slice_sel_mem_active = "SLICE_SEL_MEM_ACTIVE"; - Base::slice_sel_return = "SLICE_SEL_RETURN"; - Base::slice_sel_start = "SLICE_SEL_START"; - Base::slice_space_id = "SLICE_SPACE_ID"; - Base::slice_val = "SLICE_VAL"; - Base::perm_slice_mem = "PERM_SLICE_MEM"; - Base::perm_main_alu = "PERM_MAIN_ALU"; - Base::perm_main_bin = "PERM_MAIN_BIN"; - Base::perm_main_conv = "PERM_MAIN_CONV"; - Base::perm_main_pos2_perm = "PERM_MAIN_POS2_PERM"; - Base::perm_main_pedersen = "PERM_MAIN_PEDERSEN"; - Base::perm_main_slice = "PERM_MAIN_SLICE"; - Base::perm_main_mem_a = "PERM_MAIN_MEM_A"; - Base::perm_main_mem_b = "PERM_MAIN_MEM_B"; - Base::perm_main_mem_c = "PERM_MAIN_MEM_C"; - Base::perm_main_mem_d = "PERM_MAIN_MEM_D"; - Base::perm_main_mem_ind_addr_a = "PERM_MAIN_MEM_IND_ADDR_A"; - Base::perm_main_mem_ind_addr_b = "PERM_MAIN_MEM_IND_ADDR_B"; - Base::perm_main_mem_ind_addr_c = "PERM_MAIN_MEM_IND_ADDR_C"; - Base::perm_main_mem_ind_addr_d = "PERM_MAIN_MEM_IND_ADDR_D"; - Base::lookup_byte_lengths = "LOOKUP_BYTE_LENGTHS"; - Base::lookup_byte_operations = "LOOKUP_BYTE_OPERATIONS"; - Base::lookup_cd_value = "LOOKUP_CD_VALUE"; - Base::lookup_ret_value = "LOOKUP_RET_VALUE"; - Base::lookup_opcode_gas = "LOOKUP_OPCODE_GAS"; - Base::range_check_l2_gas_hi = "RANGE_CHECK_L2_GAS_HI"; - Base::range_check_l2_gas_lo = "RANGE_CHECK_L2_GAS_LO"; - Base::range_check_da_gas_hi = "RANGE_CHECK_DA_GAS_HI"; - Base::range_check_da_gas_lo = "RANGE_CHECK_DA_GAS_LO"; - Base::kernel_output_lookup = "KERNEL_OUTPUT_LOOKUP"; - Base::lookup_into_kernel = "LOOKUP_INTO_KERNEL"; - Base::incl_main_tag_err = "INCL_MAIN_TAG_ERR"; - Base::incl_mem_tag_err = "INCL_MEM_TAG_ERR"; - Base::lookup_mem_rng_chk_lo = "LOOKUP_MEM_RNG_CHK_LO"; - Base::lookup_mem_rng_chk_mid = "LOOKUP_MEM_RNG_CHK_MID"; - Base::lookup_mem_rng_chk_hi = "LOOKUP_MEM_RNG_CHK_HI"; - Base::lookup_pow_2_0 = "LOOKUP_POW_2_0"; - Base::lookup_pow_2_1 = "LOOKUP_POW_2_1"; - Base::lookup_u8_0 = "LOOKUP_U8_0"; - Base::lookup_u8_1 = "LOOKUP_U8_1"; - Base::lookup_u16_0 = "LOOKUP_U16_0"; - Base::lookup_u16_1 = "LOOKUP_U16_1"; - Base::lookup_u16_2 = "LOOKUP_U16_2"; - Base::lookup_u16_3 = "LOOKUP_U16_3"; - Base::lookup_u16_4 = "LOOKUP_U16_4"; - Base::lookup_u16_5 = "LOOKUP_U16_5"; - Base::lookup_u16_6 = "LOOKUP_U16_6"; - Base::lookup_u16_7 = "LOOKUP_U16_7"; - Base::lookup_u16_8 = "LOOKUP_U16_8"; - Base::lookup_u16_9 = "LOOKUP_U16_9"; - Base::lookup_u16_10 = "LOOKUP_U16_10"; - Base::lookup_u16_11 = "LOOKUP_U16_11"; - Base::lookup_u16_12 = "LOOKUP_U16_12"; - Base::lookup_u16_13 = "LOOKUP_U16_13"; - Base::lookup_u16_14 = "LOOKUP_U16_14"; - Base::lookup_div_u16_0 = "LOOKUP_DIV_U16_0"; - Base::lookup_div_u16_1 = "LOOKUP_DIV_U16_1"; - Base::lookup_div_u16_2 = "LOOKUP_DIV_U16_2"; - Base::lookup_div_u16_3 = "LOOKUP_DIV_U16_3"; - Base::lookup_div_u16_4 = "LOOKUP_DIV_U16_4"; - Base::lookup_div_u16_5 = "LOOKUP_DIV_U16_5"; - Base::lookup_div_u16_6 = "LOOKUP_DIV_U16_6"; - Base::lookup_div_u16_7 = "LOOKUP_DIV_U16_7"; - Base::lookup_byte_lengths_counts = "LOOKUP_BYTE_LENGTHS_COUNTS"; - Base::lookup_byte_operations_counts = "LOOKUP_BYTE_OPERATIONS_COUNTS"; - Base::lookup_cd_value_counts = "LOOKUP_CD_VALUE_COUNTS"; - Base::lookup_ret_value_counts = "LOOKUP_RET_VALUE_COUNTS"; - Base::lookup_opcode_gas_counts = "LOOKUP_OPCODE_GAS_COUNTS"; - Base::range_check_l2_gas_hi_counts = "RANGE_CHECK_L2_GAS_HI_COUNTS"; - Base::range_check_l2_gas_lo_counts = "RANGE_CHECK_L2_GAS_LO_COUNTS"; - Base::range_check_da_gas_hi_counts = "RANGE_CHECK_DA_GAS_HI_COUNTS"; - Base::range_check_da_gas_lo_counts = "RANGE_CHECK_DA_GAS_LO_COUNTS"; - Base::kernel_output_lookup_counts = "KERNEL_OUTPUT_LOOKUP_COUNTS"; - Base::lookup_into_kernel_counts = "LOOKUP_INTO_KERNEL_COUNTS"; - Base::incl_main_tag_err_counts = "INCL_MAIN_TAG_ERR_COUNTS"; - Base::incl_mem_tag_err_counts = "INCL_MEM_TAG_ERR_COUNTS"; - Base::lookup_mem_rng_chk_lo_counts = "LOOKUP_MEM_RNG_CHK_LO_COUNTS"; - Base::lookup_mem_rng_chk_mid_counts = "LOOKUP_MEM_RNG_CHK_MID_COUNTS"; - Base::lookup_mem_rng_chk_hi_counts = "LOOKUP_MEM_RNG_CHK_HI_COUNTS"; - Base::lookup_pow_2_0_counts = "LOOKUP_POW_2_0_COUNTS"; - Base::lookup_pow_2_1_counts = "LOOKUP_POW_2_1_COUNTS"; - Base::lookup_u8_0_counts = "LOOKUP_U8_0_COUNTS"; - Base::lookup_u8_1_counts = "LOOKUP_U8_1_COUNTS"; - Base::lookup_u16_0_counts = "LOOKUP_U16_0_COUNTS"; - Base::lookup_u16_1_counts = "LOOKUP_U16_1_COUNTS"; - Base::lookup_u16_2_counts = "LOOKUP_U16_2_COUNTS"; - Base::lookup_u16_3_counts = "LOOKUP_U16_3_COUNTS"; - Base::lookup_u16_4_counts = "LOOKUP_U16_4_COUNTS"; - Base::lookup_u16_5_counts = "LOOKUP_U16_5_COUNTS"; - Base::lookup_u16_6_counts = "LOOKUP_U16_6_COUNTS"; - Base::lookup_u16_7_counts = "LOOKUP_U16_7_COUNTS"; - Base::lookup_u16_8_counts = "LOOKUP_U16_8_COUNTS"; - Base::lookup_u16_9_counts = "LOOKUP_U16_9_COUNTS"; - Base::lookup_u16_10_counts = "LOOKUP_U16_10_COUNTS"; - Base::lookup_u16_11_counts = "LOOKUP_U16_11_COUNTS"; - Base::lookup_u16_12_counts = "LOOKUP_U16_12_COUNTS"; - Base::lookup_u16_13_counts = "LOOKUP_U16_13_COUNTS"; - Base::lookup_u16_14_counts = "LOOKUP_U16_14_COUNTS"; - Base::lookup_div_u16_0_counts = "LOOKUP_DIV_U16_0_COUNTS"; - Base::lookup_div_u16_1_counts = "LOOKUP_DIV_U16_1_COUNTS"; - Base::lookup_div_u16_2_counts = "LOOKUP_DIV_U16_2_COUNTS"; - Base::lookup_div_u16_3_counts = "LOOKUP_DIV_U16_3_COUNTS"; - Base::lookup_div_u16_4_counts = "LOOKUP_DIV_U16_4_COUNTS"; - Base::lookup_div_u16_5_counts = "LOOKUP_DIV_U16_5_COUNTS"; - Base::lookup_div_u16_6_counts = "LOOKUP_DIV_U16_6_COUNTS"; - Base::lookup_div_u16_7_counts = "LOOKUP_DIV_U16_7_COUNTS"; - }; + CommitmentLabels(); }; class VerifierCommitments : public AllEntities { @@ -1777,11 +376,7 @@ class AvmFlavor { using Base = AllEntities; public: - VerifierCommitments(const std::shared_ptr& verification_key) - { - main_clk = verification_key->main_clk; - main_sel_first = verification_key->main_sel_first; - } + VerifierCommitments(const std::shared_ptr& verification_key); }; class Transcript : public NativeTranscript { @@ -1802,53 +397,8 @@ class AvmFlavor { : NativeTranscript(proof) {} - void deserialize_full_transcript() - { - size_t num_frs_read = 0; - circuit_size = deserialize_from_buffer(proof_data, num_frs_read); - size_t log_n = numeric::get_msb(circuit_size); - - for (auto& commitment : commitments) { - commitment = deserialize_from_buffer(proof_data, num_frs_read); - } - for (size_t i = 0; i < log_n; ++i) { - sumcheck_univariates.emplace_back( - deserialize_from_buffer>(Transcript::proof_data, - num_frs_read)); - } - sumcheck_evaluations = - deserialize_from_buffer>(Transcript::proof_data, num_frs_read); - for (size_t i = 0; i < log_n; ++i) { - zm_cq_comms.push_back(deserialize_from_buffer(proof_data, num_frs_read)); - } - zm_cq_comm = deserialize_from_buffer(proof_data, num_frs_read); - zm_pi_comm = deserialize_from_buffer(proof_data, num_frs_read); - } - - void serialize_full_transcript() - { - size_t old_proof_length = proof_data.size(); - Transcript::proof_data.clear(); - size_t log_n = numeric::get_msb(circuit_size); - - serialize_to_buffer(circuit_size, Transcript::proof_data); - - for (const auto& commitment : commitments) { - serialize_to_buffer(commitment, Transcript::proof_data); - } - for (size_t i = 0; i < log_n; ++i) { - serialize_to_buffer(sumcheck_univariates[i], Transcript::proof_data); - } - serialize_to_buffer(sumcheck_evaluations, Transcript::proof_data); - for (size_t i = 0; i < log_n; ++i) { - serialize_to_buffer(zm_cq_comms[i], proof_data); - } - serialize_to_buffer(zm_cq_comm, proof_data); - serialize_to_buffer(zm_pi_comm, proof_data); - - // sanity check to make sure we generate the same length of proof as before. - ASSERT(proof_data.size() == old_proof_length); - } + void deserialize_full_transcript(); + void serialize_full_transcript(); }; }; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor_settings.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor_settings.hpp index d901afcc8b4..98b3085f4ff 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor_settings.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor_settings.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/commitment_schemes/kzg/kzg.hpp" diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.cpp index 5e62d6d07d6..77080e1da20 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.cpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #include "barretenberg/vm/generated/avm_full_row.hpp" #include "barretenberg/vm/generated/avm_flavor_settings.hpp" diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.hpp index ba078c93ba1..dbc72265711 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_full_row.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp index 9cc9cc81876..4a66e1c337a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #include "barretenberg/vm/generated/avm_prover.hpp" #include "barretenberg/commitment_schemes/claim.hpp" @@ -11,7 +12,7 @@ #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" -#include "barretenberg/vm/avm_trace/stats.hpp" +#include "barretenberg/vm/stats.hpp" namespace bb { diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.hpp index 35d9f927cbb..0afc62a0987 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index e31a545d167..023e00f61ad 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #include "barretenberg/vm/generated/avm_verifier.hpp" #include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" @@ -79,99 +80,9 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.perm_slice_mem); - commitments.perm_main_alu = transcript->template receive_from_prover(commitment_labels.perm_main_alu); - commitments.perm_main_bin = transcript->template receive_from_prover(commitment_labels.perm_main_bin); - commitments.perm_main_conv = transcript->template receive_from_prover(commitment_labels.perm_main_conv); - commitments.perm_main_pos2_perm = - transcript->template receive_from_prover(commitment_labels.perm_main_pos2_perm); - commitments.perm_main_pedersen = - transcript->template receive_from_prover(commitment_labels.perm_main_pedersen); - commitments.perm_main_slice = - transcript->template receive_from_prover(commitment_labels.perm_main_slice); - commitments.perm_main_mem_a = - transcript->template receive_from_prover(commitment_labels.perm_main_mem_a); - commitments.perm_main_mem_b = - transcript->template receive_from_prover(commitment_labels.perm_main_mem_b); - commitments.perm_main_mem_c = - transcript->template receive_from_prover(commitment_labels.perm_main_mem_c); - commitments.perm_main_mem_d = - transcript->template receive_from_prover(commitment_labels.perm_main_mem_d); - commitments.perm_main_mem_ind_addr_a = - transcript->template receive_from_prover(commitment_labels.perm_main_mem_ind_addr_a); - commitments.perm_main_mem_ind_addr_b = - transcript->template receive_from_prover(commitment_labels.perm_main_mem_ind_addr_b); - commitments.perm_main_mem_ind_addr_c = - transcript->template receive_from_prover(commitment_labels.perm_main_mem_ind_addr_c); - commitments.perm_main_mem_ind_addr_d = - transcript->template receive_from_prover(commitment_labels.perm_main_mem_ind_addr_d); - commitments.lookup_byte_lengths = - transcript->template receive_from_prover(commitment_labels.lookup_byte_lengths); - commitments.lookup_byte_operations = - transcript->template receive_from_prover(commitment_labels.lookup_byte_operations); - commitments.lookup_cd_value = - transcript->template receive_from_prover(commitment_labels.lookup_cd_value); - commitments.lookup_ret_value = - transcript->template receive_from_prover(commitment_labels.lookup_ret_value); - commitments.lookup_opcode_gas = - transcript->template receive_from_prover(commitment_labels.lookup_opcode_gas); - commitments.range_check_l2_gas_hi = - transcript->template receive_from_prover(commitment_labels.range_check_l2_gas_hi); - commitments.range_check_l2_gas_lo = - transcript->template receive_from_prover(commitment_labels.range_check_l2_gas_lo); - commitments.range_check_da_gas_hi = - transcript->template receive_from_prover(commitment_labels.range_check_da_gas_hi); - commitments.range_check_da_gas_lo = - transcript->template receive_from_prover(commitment_labels.range_check_da_gas_lo); - commitments.kernel_output_lookup = - transcript->template receive_from_prover(commitment_labels.kernel_output_lookup); - commitments.lookup_into_kernel = - transcript->template receive_from_prover(commitment_labels.lookup_into_kernel); - commitments.incl_main_tag_err = - transcript->template receive_from_prover(commitment_labels.incl_main_tag_err); - commitments.incl_mem_tag_err = - transcript->template receive_from_prover(commitment_labels.incl_mem_tag_err); - commitments.lookup_mem_rng_chk_lo = - transcript->template receive_from_prover(commitment_labels.lookup_mem_rng_chk_lo); - commitments.lookup_mem_rng_chk_mid = - transcript->template receive_from_prover(commitment_labels.lookup_mem_rng_chk_mid); - commitments.lookup_mem_rng_chk_hi = - transcript->template receive_from_prover(commitment_labels.lookup_mem_rng_chk_hi); - commitments.lookup_pow_2_0 = transcript->template receive_from_prover(commitment_labels.lookup_pow_2_0); - commitments.lookup_pow_2_1 = transcript->template receive_from_prover(commitment_labels.lookup_pow_2_1); - commitments.lookup_u8_0 = transcript->template receive_from_prover(commitment_labels.lookup_u8_0); - commitments.lookup_u8_1 = transcript->template receive_from_prover(commitment_labels.lookup_u8_1); - commitments.lookup_u16_0 = transcript->template receive_from_prover(commitment_labels.lookup_u16_0); - commitments.lookup_u16_1 = transcript->template receive_from_prover(commitment_labels.lookup_u16_1); - commitments.lookup_u16_2 = transcript->template receive_from_prover(commitment_labels.lookup_u16_2); - commitments.lookup_u16_3 = transcript->template receive_from_prover(commitment_labels.lookup_u16_3); - commitments.lookup_u16_4 = transcript->template receive_from_prover(commitment_labels.lookup_u16_4); - commitments.lookup_u16_5 = transcript->template receive_from_prover(commitment_labels.lookup_u16_5); - commitments.lookup_u16_6 = transcript->template receive_from_prover(commitment_labels.lookup_u16_6); - commitments.lookup_u16_7 = transcript->template receive_from_prover(commitment_labels.lookup_u16_7); - commitments.lookup_u16_8 = transcript->template receive_from_prover(commitment_labels.lookup_u16_8); - commitments.lookup_u16_9 = transcript->template receive_from_prover(commitment_labels.lookup_u16_9); - commitments.lookup_u16_10 = transcript->template receive_from_prover(commitment_labels.lookup_u16_10); - commitments.lookup_u16_11 = transcript->template receive_from_prover(commitment_labels.lookup_u16_11); - commitments.lookup_u16_12 = transcript->template receive_from_prover(commitment_labels.lookup_u16_12); - commitments.lookup_u16_13 = transcript->template receive_from_prover(commitment_labels.lookup_u16_13); - commitments.lookup_u16_14 = transcript->template receive_from_prover(commitment_labels.lookup_u16_14); - commitments.lookup_div_u16_0 = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_0); - commitments.lookup_div_u16_1 = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_1); - commitments.lookup_div_u16_2 = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_2); - commitments.lookup_div_u16_3 = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_3); - commitments.lookup_div_u16_4 = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_4); - commitments.lookup_div_u16_5 = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_5); - commitments.lookup_div_u16_6 = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_6); - commitments.lookup_div_u16_7 = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_7); + for (auto [label, commitment] : zip_view(commitment_labels.get_derived(), commitments.get_derived())) { + commitment = transcript->template receive_from_prover(label); + } // Execute Sumcheck Verifier const size_t log_circuit_size = numeric::get_msb(circuit_size); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.hpp index fc7495d9abd..32b506075d3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.hpp @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/plonk/proof_system/types/proof.hpp" diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/stats.cpp b/barretenberg/cpp/src/barretenberg/vm/stats.cpp similarity index 96% rename from barretenberg/cpp/src/barretenberg/vm/avm_trace/stats.cpp rename to barretenberg/cpp/src/barretenberg/vm/stats.cpp index 1c337c76a8f..9d2c65ddbfe 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/stats.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/stats.cpp @@ -1,4 +1,4 @@ -#include "barretenberg/vm/avm_trace/stats.hpp" +#include "barretenberg/vm/stats.hpp" #include #include diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/stats.hpp b/barretenberg/cpp/src/barretenberg/vm/stats.hpp similarity index 100% rename from barretenberg/cpp/src/barretenberg/vm/avm_trace/stats.hpp rename to barretenberg/cpp/src/barretenberg/vm/stats.hpp diff --git a/bb-pilcom/bb-pil-backend/src/circuit_builder.rs b/bb-pilcom/bb-pil-backend/src/circuit_builder.rs index 2d42e542135..75d18e0e90c 100644 --- a/bb-pilcom/bb-pil-backend/src/circuit_builder.rs +++ b/bb-pilcom/bb-pil-backend/src/circuit_builder.rs @@ -13,6 +13,8 @@ pub trait CircuitBuilder { to_be_shifted: &[String], ); + fn create_circuit_builder_cpp(&mut self, name: &str, all_cols_without_inverses: &[String]); + fn create_full_row_hpp(&mut self, name: &str, all_cols: &[String]); fn create_full_row_cpp(&mut self, name: &str, all_cols: &[String]); } @@ -55,6 +57,31 @@ impl CircuitBuilder for BBFiles { ); } + fn create_circuit_builder_cpp(&mut self, name: &str, all_cols_without_inverses: &[String]) { + let mut handlebars = Handlebars::new(); + + let data = &json!({ + "name": name, + "all_cols_without_inverses": all_cols_without_inverses, + }); + + handlebars + .register_template_string( + "circuit_builder.cpp", + std::str::from_utf8(include_bytes!("../templates/circuit_builder.cpp.hbs")) + .unwrap(), + ) + .unwrap(); + + let circuit_cpp = handlebars.render("circuit_builder.cpp", data).unwrap(); + + self.write_file( + &self.circuit, + &format!("{}_circuit_builder.cpp", snake_case(name)), + &circuit_cpp, + ); + } + fn create_full_row_hpp(&mut self, name: &str, all_cols: &[String]) { let mut handlebars = Handlebars::new(); diff --git a/bb-pilcom/bb-pil-backend/src/flavor_builder.rs b/bb-pilcom/bb-pil-backend/src/flavor_builder.rs index ff818ab19cb..8c97f9f5ce7 100644 --- a/bb-pilcom/bb-pil-backend/src/flavor_builder.rs +++ b/bb-pilcom/bb-pil-backend/src/flavor_builder.rs @@ -19,6 +19,20 @@ pub trait FlavorBuilder { all_cols_and_shifts: &[String], ); + fn create_flavor_cpp( + &mut self, + name: &str, + relation_file_names: &[String], + lookups: &[String], + fixed: &[String], + witness: &[String], + witness_without_inverses: &[String], + all_cols: &[String], + to_be_shifted: &[String], + shifted: &[String], + all_cols_and_shifts: &[String], + ); + fn create_flavor_settings_hpp(&mut self, name: &str); } @@ -73,6 +87,55 @@ impl FlavorBuilder for BBFiles { ); } + fn create_flavor_cpp( + &mut self, + name: &str, + relation_file_names: &[String], + lookups: &[String], + fixed: &[String], + witness: &[String], + witness_without_inverses: &[String], + all_cols: &[String], + to_be_shifted: &[String], + shifted: &[String], + all_cols_and_shifts: &[String], + ) { + let mut handlebars = Handlebars::new(); + + let data = &json!({ + "name": name, + "relation_file_names": relation_file_names, + "lookups": lookups, + "fixed": fixed, + "witness": witness, + "all_cols": all_cols, + "to_be_shifted": to_be_shifted, + "shifted": shifted, + "all_cols_and_shifts": all_cols_and_shifts, + "witness_without_inverses": witness_without_inverses, + }); + + handlebars_helper!(join: |*args| + args.iter().map(|v| v.as_array().unwrap().to_owned()).collect_vec().concat() + ); + handlebars.register_helper("join", Box::new(join)); + + handlebars + .register_template_string( + "flavor.cpp", + std::str::from_utf8(include_bytes!("../templates/flavor.cpp.hbs")).unwrap(), + ) + .unwrap(); + + let flavor_cpp = handlebars.render("flavor.cpp", data).unwrap(); + + self.write_file( + &self.flavor, + &format!("{}_flavor.cpp", snake_case(name)), + &flavor_cpp, + ); + } + fn create_flavor_settings_hpp(&mut self, name: &str) { let mut handlebars = Handlebars::new(); diff --git a/bb-pilcom/bb-pil-backend/src/vm_builder.rs b/bb-pilcom/bb-pil-backend/src/vm_builder.rs index 63696cba570..ebc4e9687f4 100644 --- a/bb-pilcom/bb-pil-backend/src/vm_builder.rs +++ b/bb-pilcom/bb-pil-backend/src/vm_builder.rs @@ -118,7 +118,7 @@ pub fn analyzed_to_cpp( bb_files.create_full_row_hpp(file_name, &all_cols); bb_files.create_full_row_cpp(file_name, &all_cols); - // ----------------------- Create the circuit builder file ----------------------- + // ----------------------- Create the circuit builder files ----------------------- bb_files.create_circuit_builder_hpp( file_name, &relations, @@ -127,8 +127,9 @@ pub fn analyzed_to_cpp( &all_cols, &to_be_shifted, ); + bb_files.create_circuit_builder_cpp(file_name, &all_cols_without_inverses); - // ----------------------- Create the flavor file ----------------------- + // ----------------------- Create the flavor files ----------------------- bb_files.create_flavor_hpp( file_name, &relations, @@ -142,6 +143,19 @@ pub fn analyzed_to_cpp( &all_cols_with_shifts, ); + bb_files.create_flavor_cpp( + file_name, + &relations, + &inverses, + &fixed, + &witness, + &witnesses_without_inverses, + &all_cols, + &to_be_shifted, + &shifted, + &all_cols_with_shifts, + ); + bb_files.create_flavor_settings_hpp(file_name); // ----------------------- Create the composer files ----------------------- diff --git a/bb-pilcom/bb-pil-backend/templates/circuit_builder.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/circuit_builder.cpp.hbs new file mode 100644 index 00000000000..7c17d820fb5 --- /dev/null +++ b/bb-pilcom/bb-pil-backend/templates/circuit_builder.cpp.hbs @@ -0,0 +1,122 @@ +// AUTOGENERATED FILE +#include "barretenberg/vm/generated/{{snakeCase name}}_circuit_builder.hpp" + +#include + +#include "barretenberg/common/constexpr_utils.hpp" +#include "barretenberg/common/thread.hpp" +#include "barretenberg/common/throw_or_abort.hpp" +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" +#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" + +namespace bb { + +{{name}}CircuitBuilder::ProverPolynomials {{name}}CircuitBuilder::compute_polynomials() const { + const auto num_rows = get_circuit_subgroup_size(); + ProverPolynomials polys; + + // Allocate mem for each column + for (auto& poly : polys.get_all()) { + poly = Polynomial(num_rows); + } + + for (size_t i = 0; i < rows.size(); i++) { + {{#each all_cols_without_inverses as |poly|}} + polys.{{poly}}[i] = rows[i].{{poly}}; + {{/each}} + } + + for (auto [shifted, to_be_shifted] : zip_view(polys.get_shifted(), polys.get_to_be_shifted())) { + shifted = to_be_shifted.shifted(); + } + + return polys; +} + +bool {{name}}CircuitBuilder::check_circuit() const { + const FF gamma = FF::random_element(); + const FF beta = FF::random_element(); + bb::RelationParameters params{ + .eta = 0, + .beta = beta, + .gamma = gamma, + .public_input_delta = 0, + .lookup_grand_product_delta = 0, + .beta_sqr = 0, + .beta_cube = 0, + .eccvm_set_permutation_delta = 0, + }; + + auto polys = compute_polynomials(); + const size_t num_rows = polys.get_polynomial_size(); + + // Checks that we will run. + using SignalErrorFn = const std::function&; + std::vector> checks; + + // Add relation checks. + bb::constexpr_for<0, std::tuple_size_v<{{name}}Flavor::MainRelations>, 1>([&]() { + using Relation = std::tuple_element_t; + checks.push_back([&](SignalErrorFn signal_error) { + typename Relation::SumcheckArrayOfValuesOverSubrelations result; + for (auto& r : result) { + r = 0; + } + constexpr size_t NUM_SUBRELATIONS = result.size(); + + for (size_t r = 0; r < num_rows; ++r) { + Relation::accumulate(result, polys.get_row(r), {}, 1); + for (size_t j = 0; j < NUM_SUBRELATIONS; ++j) { + if (result[j] != 0) { + signal_error(format("Relation ", + Relation::NAME, + ", subrelation ", + Relation::get_subrelation_label(j), + " failed at row ", + r)); + } + } + } + }); + }); + + // Add calculation of logderivatives and lookup/permutation checks. + bb::constexpr_for<0, std::tuple_size_v<{{name}}Flavor::LookupRelations>, 1>([&]() { + using Relation = std::tuple_element_t; + checks.push_back([&, num_rows](SignalErrorFn signal_error) { + // Check the logderivative relation + bb::compute_logderivative_inverse(polys, params, num_rows); + + typename Relation::SumcheckArrayOfValuesOverSubrelations lookup_result; + + for (auto& r : lookup_result) { + r = 0; + } + for (size_t r = 0; r < num_rows; ++r) { + Relation::accumulate(lookup_result, polys.get_row(r), params, 1); + } + for (auto r : lookup_result) { + if (r != 0) { + signal_error(format("Lookup ", Relation::NAME, " failed.")); + } + } + }); + }); + + std::string errors; + std::mutex m; + auto signal_error = [&](const std::string& error) { + std::lock_guard lock(m); + errors += error + "\n"; + }; + bb::parallel_for(checks.size(), [&](size_t i) { checks[i](signal_error); }); + if (!errors.empty()) { + throw_or_abort(errors); + } + + return errors.empty(); +} + +} // namespace bb \ No newline at end of file diff --git a/bb-pilcom/bb-pil-backend/templates/circuit_builder.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/circuit_builder.hpp.hbs index e4d2f08534f..ee9593d9879 100644 --- a/bb-pilcom/bb-pil-backend/templates/circuit_builder.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/circuit_builder.hpp.hbs @@ -1,17 +1,9 @@ // AUTOGENERATED FILE #pragma once -#include #include -#include "barretenberg/common/constexpr_utils.hpp" -#include "barretenberg/common/thread.hpp" -#include "barretenberg/common/throw_or_abort.hpp" -#include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/stdlib_circuit_builders/circuit_builder_base.hpp" -#include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" -#include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" -#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/vm/generated/{{snakeCase name}}_full_row.hpp" #include "barretenberg/vm/generated/{{snakeCase name}}_flavor.hpp" @@ -34,117 +26,13 @@ class {{name}}CircuitBuilder { void set_trace(std::vector&& trace) { rows = std::move(trace); } - ProverPolynomials compute_polynomials() { - const auto num_rows = get_circuit_subgroup_size(); - ProverPolynomials polys; + ProverPolynomials compute_polynomials() const; - // Allocate mem for each column - for (auto& poly : polys.get_all()) { - poly = Polynomial(num_rows); - } - - for (size_t i = 0; i < rows.size(); i++) { - {{#each all_cols_without_inverses as |poly|}} - polys.{{poly}}[i] = rows[i].{{poly}}; - {{/each}} - } - - for (auto [shifted, to_be_shifted] : zip_view(polys.get_shifted(), polys.get_to_be_shifted())) { - shifted = to_be_shifted.shifted(); - } - - return polys; - } - - [[maybe_unused]] bool check_circuit() - { - const FF gamma = FF::random_element(); - const FF beta = FF::random_element(); - bb::RelationParameters params{ - .eta = 0, - .beta = beta, - .gamma = gamma, - .public_input_delta = 0, - .lookup_grand_product_delta = 0, - .beta_sqr = 0, - .beta_cube = 0, - .eccvm_set_permutation_delta = 0, - }; - - auto polys = compute_polynomials(); - const size_t num_rows = polys.get_polynomial_size(); - - // Checks that we will run. - using SignalErrorFn = const std::function&; - std::vector> checks; - - // Add relation checks. - bb::constexpr_for<0, std::tuple_size_v<{{name}}Flavor::MainRelations>, 1>([&]() { - using Relation = std::tuple_element_t; - checks.push_back([&](SignalErrorFn signal_error) { - typename Relation::SumcheckArrayOfValuesOverSubrelations result; - for (auto& r : result) { - r = 0; - } - constexpr size_t NUM_SUBRELATIONS = result.size(); - - for (size_t r = 0; r < num_rows; ++r) { - Relation::accumulate(result, polys.get_row(r), {}, 1); - for (size_t j = 0; j < NUM_SUBRELATIONS; ++j) { - if (result[j] != 0) { - signal_error(format("Relation ", - Relation::NAME, - ", subrelation ", - Relation::get_subrelation_label(j), - " failed at row ", - r)); - } - } - } - }); - }); - - // Add calculation of logderivatives and lookup/permutation checks. - bb::constexpr_for<0, std::tuple_size_v<{{name}}Flavor::LookupRelations>, 1>([&]() { - using Relation = std::tuple_element_t; - checks.push_back([&, num_rows](SignalErrorFn signal_error) { - // Check the logderivative relation - bb::compute_logderivative_inverse(polys, params, num_rows); - - typename Relation::SumcheckArrayOfValuesOverSubrelations lookup_result; - - for (auto& r : lookup_result) { - r = 0; - } - for (size_t r = 0; r < num_rows; ++r) { - Relation::accumulate(lookup_result, polys.get_row(r), params, 1); - } - for (auto r : lookup_result) { - if (r != 0) { - signal_error(format("Lookup ", Relation::NAME, " failed.")); - } - } - }); - }); - - std::string errors; - auto signal_error = [&](const std::string& error) { - // Thread safety first! - static std::mutex m; - std::lock_guard lock(m); - errors += error + "\n"; - }; - bb::parallel_for(checks.size(), [&](size_t i) { checks[i](signal_error); }); - if (!errors.empty()) { - throw_or_abort(errors); - } - - return errors.empty(); - } + bool check_circuit() const; - [[nodiscard]] size_t get_num_gates() const { return rows.size(); } + size_t get_num_gates() const { return rows.size(); } - [[nodiscard]] size_t get_circuit_subgroup_size() const + size_t get_circuit_subgroup_size() const { const size_t num_rows = get_num_gates(); const auto num_rows_log2 = static_cast(numeric::get_msb64(num_rows)); diff --git a/bb-pilcom/bb-pil-backend/templates/composer.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/composer.cpp.hbs index ddb2743c125..c46c6f14f0d 100644 --- a/bb-pilcom/bb-pil-backend/templates/composer.cpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/composer.cpp.hbs @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #include "barretenberg/vm/generated/{{snakeCase name}}_composer.hpp" #include "barretenberg/plonk_honk_shared/composer/composer_lib.hpp" diff --git a/bb-pilcom/bb-pil-backend/templates/composer.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/composer.hpp.hbs index fdbca47244e..4ef93ca2e21 100644 --- a/bb-pilcom/bb-pil-backend/templates/composer.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/composer.hpp.hbs @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/plonk_honk_shared/composer/composer_lib.hpp" diff --git a/bb-pilcom/bb-pil-backend/templates/flavor.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/flavor.cpp.hbs new file mode 100644 index 00000000000..90db25415d4 --- /dev/null +++ b/bb-pilcom/bb-pil-backend/templates/flavor.cpp.hbs @@ -0,0 +1,112 @@ +// AUTOGENERATED FILE +#include "barretenberg/vm/generated/{{snakeCase name}}_flavor.hpp" + +namespace bb { + +{{name}}Flavor::AllConstRefValues::AllConstRefValues(const RefArray& il) : + {{#each (join fixed witness_without_inverses lookups shifted) as |item|}} + {{item}}(il[{{@index}}]){{#unless @last}},{{/unless}} + {{/each}} + {} + +{{name}}Flavor::ProverPolynomials::ProverPolynomials(ProvingKey& proving_key) +{ + for (auto [prover_poly, key_poly] : zip_view(this->get_unshifted(), proving_key.get_all())) { + ASSERT(flavor_get_label(*this, prover_poly) == flavor_get_label(proving_key, key_poly)); + prover_poly = key_poly.share(); + } + for (auto [prover_poly, key_poly] : zip_view(this->get_shifted(), proving_key.get_to_be_shifted())) { + ASSERT(flavor_get_label(*this, prover_poly) == (flavor_get_label(proving_key, key_poly) + "_shift")); + prover_poly = key_poly.shifted(); + } +} + +{{name}}Flavor::AllConstRefValues {{name}}Flavor::ProverPolynomials::get_row(size_t row_idx) const +{ + {{!-- + // TODO: try to make something like this work. + // Right now it's too risky because it relies on the order of the columns in `get_all()`. + RefArray all_cols = get_all(); + std::array refs; + for (size_t i = 0; i < refs.size(); ++i) { + refs[i] = &all_cols[i][row_idx]; + } + // Note: the order of the constructor must match the order of the columns in `get_all()`! + return AllConstRefValues(refs); + --}} + return AllConstRefValues(RefArray{ + {{#each (join fixed witness_without_inverses lookups shifted) as |item|}} + {{item}}[row_idx]{{#unless @last}},{{/unless}} + {{/each}} + }); +} + +{{name}}Flavor::CommitmentLabels::CommitmentLabels() +{ + {{#each all_cols as |item|}} + Base::{{item}} = "{{shoutySnakeCase item}}"; + {{/each}} +}; + +{{name}}Flavor::VerifierCommitments::VerifierCommitments(const std::shared_ptr& verification_key) +{ + {{#each fixed as |item|}} + {{item}} = verification_key->{{item}}; + {{/each}} +} + +void {{name}}Flavor::Transcript::deserialize_full_transcript() { + size_t num_frs_read = 0; + circuit_size = deserialize_from_buffer(proof_data, num_frs_read); + size_t log_n = numeric::get_msb(circuit_size); + + for (auto& commitment : commitments) { + commitment = deserialize_from_buffer(proof_data, num_frs_read); + } + for (size_t i = 0; i < log_n; ++i) { + sumcheck_univariates.emplace_back( + deserialize_from_buffer>( + Transcript::proof_data, num_frs_read)); + } + sumcheck_evaluations = deserialize_from_buffer>( + Transcript::proof_data, num_frs_read); + for (size_t i = 0; i < log_n; ++i) { + zm_cq_comms.push_back(deserialize_from_buffer(proof_data, num_frs_read)); + } + zm_cq_comm = deserialize_from_buffer(proof_data, num_frs_read); + zm_pi_comm = deserialize_from_buffer(proof_data, num_frs_read); +} + +void {{name}}Flavor::Transcript::serialize_full_transcript() { + size_t old_proof_length = proof_data.size(); + Transcript::proof_data.clear(); + size_t log_n = numeric::get_msb(circuit_size); + + serialize_to_buffer(circuit_size, Transcript::proof_data); + + for (const auto& commitment : commitments) { + serialize_to_buffer(commitment, Transcript::proof_data); + } + for (size_t i = 0; i < log_n; ++i) { + serialize_to_buffer(sumcheck_univariates[i], Transcript::proof_data); + } + serialize_to_buffer(sumcheck_evaluations, Transcript::proof_data); + for (size_t i = 0; i < log_n; ++i) { + serialize_to_buffer(zm_cq_comms[i], proof_data); + } + serialize_to_buffer(zm_cq_comm, proof_data); + serialize_to_buffer(zm_pi_comm, proof_data); + + // sanity check to make sure we generate the same length of proof as before. + ASSERT(proof_data.size() == old_proof_length); +} + +{{name}}Flavor::PartiallyEvaluatedMultivariates::PartiallyEvaluatedMultivariates(const size_t circuit_size) +{ + // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) + for (auto& poly : get_all()) { + poly = Polynomial(circuit_size / 2); + } +} + +} // namespace bb \ No newline at end of file diff --git a/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs index c6d3c9c7c12..cccbda0a1ac 100644 --- a/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/flavor.hpp.hbs @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/commitment_schemes/kzg/kzg.hpp" @@ -150,7 +151,7 @@ class {{name}}Flavor { }; public: - class ProvingKey : public ProvingKey{{name}}_, WitnessEntities, CommitmentKey> { + class ProvingKey : public ProvingKeyAvm_, WitnessEntities, CommitmentKey> { public: // Expose constructors on the base class using Base = ProvingKey{{name}}_, WitnessEntities, CommitmentKey>; @@ -182,11 +183,7 @@ class {{name}}Flavor { --}} DEFINE_FLAVOR_MEMBERS(DataType, ALL_ENTITIES) - AllConstRefValues(const RefArray& il) : - {{#each (join fixed witness_without_inverses lookups shifted) as |item|}} - {{item}}(il[{{@index}}]){{#unless @last}},{{/unless}} - {{/each}} - {} + AllConstRefValues(const RefArray& il); }; /** @@ -202,54 +199,20 @@ class {{name}}Flavor { ProverPolynomials& operator=(ProverPolynomials&& o) noexcept = default; ~ProverPolynomials() = default; - ProverPolynomials(ProvingKey& proving_key) - { - for (auto [prover_poly, key_poly] : zip_view(this->get_unshifted(), proving_key.get_all())) { - ASSERT(flavor_get_label(*this, prover_poly) == flavor_get_label(proving_key, key_poly)); - prover_poly = key_poly.share(); - } - for (auto [prover_poly, key_poly] : zip_view(this->get_shifted(), proving_key.get_to_be_shifted())) { - ASSERT(flavor_get_label(*this, prover_poly) == (flavor_get_label(proving_key, key_poly) + "_shift")); - prover_poly = key_poly.shifted(); - } - } + ProverPolynomials(ProvingKey& proving_key); [[nodiscard]] size_t get_polynomial_size() const { return {{witness.0}}.size(); } /** * @brief Returns the evaluations of all prover polynomials at one point on the boolean hypercube, which * represents one row in the execution trace. */ - [[nodiscard]] AllConstRefValues get_row(size_t row_idx) const - { - {{!-- - // TODO: try to make something like this work. - // Right now it's too risky because it relies on the order of the columns in `get_all()`. - RefArray all_cols = get_all(); - std::array refs; - for (size_t i = 0; i < refs.size(); ++i) { - refs[i] = &all_cols[i][row_idx]; - } - // Note: the order of the constructor must match the order of the columns in `get_all()`! - return AllConstRefValues(refs); - --}} - return AllConstRefValues(RefArray{ - {{#each (join fixed witness_without_inverses lookups shifted) as |item|}} - {{item}}[row_idx]{{#unless @last}},{{/unless}} - {{/each}} - }); - } + [[nodiscard]] AllConstRefValues get_row(size_t row_idx) const; }; class PartiallyEvaluatedMultivariates : public AllEntities { public: PartiallyEvaluatedMultivariates() = default; - PartiallyEvaluatedMultivariates(const size_t circuit_size) - { - // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) - for (auto& poly : get_all()) { - poly = Polynomial(circuit_size / 2); - } - } + PartiallyEvaluatedMultivariates(const size_t circuit_size); }; /** @@ -283,12 +246,7 @@ class {{name}}Flavor { using Base = AllEntities; public: - CommitmentLabels() - { - {{#each all_cols as |item|}} - Base::{{item}} = "{{shoutySnakeCase item}}"; - {{/each}} - }; + CommitmentLabels(); }; class VerifierCommitments : public AllEntities { @@ -296,12 +254,7 @@ class {{name}}Flavor { using Base = AllEntities; public: - VerifierCommitments(const std::shared_ptr& verification_key) - { - {{#each fixed as |item|}} - {{item}} = verification_key->{{item}}; - {{/each}} - } + VerifierCommitments(const std::shared_ptr& verification_key); }; class Transcript : public NativeTranscript { @@ -322,53 +275,8 @@ class {{name}}Flavor { : NativeTranscript(proof) {} - void deserialize_full_transcript() - { - size_t num_frs_read = 0; - circuit_size = deserialize_from_buffer(proof_data, num_frs_read); - size_t log_n = numeric::get_msb(circuit_size); - - for (auto& commitment : commitments) { - commitment = deserialize_from_buffer(proof_data, num_frs_read); - } - for (size_t i = 0; i < log_n; ++i) { - sumcheck_univariates.emplace_back( - deserialize_from_buffer>( - Transcript::proof_data, num_frs_read)); - } - sumcheck_evaluations = deserialize_from_buffer>( - Transcript::proof_data, num_frs_read); - for (size_t i = 0; i < log_n; ++i) { - zm_cq_comms.push_back(deserialize_from_buffer(proof_data, num_frs_read)); - } - zm_cq_comm = deserialize_from_buffer(proof_data, num_frs_read); - zm_pi_comm = deserialize_from_buffer(proof_data, num_frs_read); - } - - void serialize_full_transcript() - { - size_t old_proof_length = proof_data.size(); - Transcript::proof_data.clear(); - size_t log_n = numeric::get_msb(circuit_size); - - serialize_to_buffer(circuit_size, Transcript::proof_data); - - for (const auto& commitment : commitments) { - serialize_to_buffer(commitment, Transcript::proof_data); - } - for (size_t i = 0; i < log_n; ++i) { - serialize_to_buffer(sumcheck_univariates[i], Transcript::proof_data); - } - serialize_to_buffer(sumcheck_evaluations, Transcript::proof_data); - for (size_t i = 0; i < log_n; ++i) { - serialize_to_buffer(zm_cq_comms[i], proof_data); - } - serialize_to_buffer(zm_cq_comm, proof_data); - serialize_to_buffer(zm_pi_comm, proof_data); - - // sanity check to make sure we generate the same length of proof as before. - ASSERT(proof_data.size() == old_proof_length); - } + void deserialize_full_transcript(); + void serialize_full_transcript(); }; }; diff --git a/bb-pilcom/bb-pil-backend/templates/flavor_settings.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/flavor_settings.hpp.hbs index b8d48acc71e..93039d496a5 100644 --- a/bb-pilcom/bb-pil-backend/templates/flavor_settings.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/flavor_settings.hpp.hbs @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/commitment_schemes/kzg/kzg.hpp" diff --git a/bb-pilcom/bb-pil-backend/templates/full_row.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/full_row.cpp.hbs index 978e8f1b613..a748e9f8c3c 100644 --- a/bb-pilcom/bb-pil-backend/templates/full_row.cpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/full_row.cpp.hbs @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #include "barretenberg/vm/generated/{{snakeCase name}}_full_row.hpp" #include "barretenberg/vm/generated/{{snakeCase name}}_flavor_settings.hpp" diff --git a/bb-pilcom/bb-pil-backend/templates/full_row.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/full_row.hpp.hbs index a9e7f6d3174..fe79a16f252 100644 --- a/bb-pilcom/bb-pil-backend/templates/full_row.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/full_row.hpp.hbs @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include diff --git a/bb-pilcom/bb-pil-backend/templates/lookup.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/lookup.hpp.hbs index a63eb410e60..d5edfc93bcf 100644 --- a/bb-pilcom/bb-pil-backend/templates/lookup.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/lookup.hpp.hbs @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" diff --git a/bb-pilcom/bb-pil-backend/templates/permutation.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/permutation.hpp.hbs index a854f55a524..ef5522ad6c3 100644 --- a/bb-pilcom/bb-pil-backend/templates/permutation.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/permutation.hpp.hbs @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" diff --git a/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs index 42eb158c95a..eccfec4a515 100644 --- a/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #include "barretenberg/vm/generated/{{snakeCase name}}_prover.hpp" #include "barretenberg/commitment_schemes/claim.hpp" @@ -11,7 +12,7 @@ #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" -#include "barretenberg/vm/{{snakeCase name}}_trace/stats.hpp" +#include "barretenberg/vm/stats.hpp" namespace bb { diff --git a/bb-pilcom/bb-pil-backend/templates/prover.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/prover.hpp.hbs index 1ea0f418681..5b3853cce9c 100644 --- a/bb-pilcom/bb-pil-backend/templates/prover.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/prover.hpp.hbs @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" diff --git a/bb-pilcom/bb-pil-backend/templates/relation.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/relation.hpp.hbs index 4b80b824cf6..b6a7ed2c58c 100644 --- a/bb-pilcom/bb-pil-backend/templates/relation.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/relation.hpp.hbs @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/relations/relation_parameters.hpp" diff --git a/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs index b87d27aa177..f52178d063a 100644 --- a/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #include "barretenberg/vm/generated/{{snakeCase name}}_verifier.hpp" #include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" @@ -79,9 +80,9 @@ bool {{name}}Verifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.{{inv}}); - {{/each}} + for (auto [label, commitment] : zip_view(commitment_labels.get_derived(), commitments.get_derived())) { + commitment = transcript->template receive_from_prover(label); + } // Execute Sumcheck Verifier const size_t log_circuit_size = numeric::get_msb(circuit_size); diff --git a/bb-pilcom/bb-pil-backend/templates/verifier.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/verifier.hpp.hbs index 11e150b6f02..fc9acfc1ce1 100644 --- a/bb-pilcom/bb-pil-backend/templates/verifier.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/verifier.hpp.hbs @@ -1,3 +1,4 @@ +// AUTOGENERATED FILE #pragma once #include "barretenberg/plonk/proof_system/types/proof.hpp" From 20c555a85142ed54b691296740ba6b22d81750c0 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Wed, 31 Jul 2024 17:47:19 -0300 Subject: [PATCH 26/35] chore: Log name of current e2e test (#7637) Logs as INFO the name of the current e2e test. Otherwise the logs give no indication of when one test has finished and the next one starts. --- yarn-project/end-to-end/package.json | 5 +++-- yarn-project/end-to-end/src/shared/jest_setup.ts | 13 +++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 yarn-project/end-to-end/src/shared/jest_setup.ts diff --git a/yarn-project/end-to-end/package.json b/yarn-project/end-to-end/package.json index 76f52fa0989..8139d01cfe9 100644 --- a/yarn-project/end-to-end/package.json +++ b/yarn-project/end-to-end/package.json @@ -113,7 +113,8 @@ "jest": { "slowTestThreshold": 300, "setupFilesAfterEnv": [ - "jest-extended/all" + "jest-extended/all", + "./shared/jest_setup.ts" ], "extensionsToTreatAsEsm": [ ".ts" @@ -145,4 +146,4 @@ "testRegex": "./src/.*\\.test\\.(js|mjs|ts)$", "rootDir": "./src" } -} +} \ No newline at end of file diff --git a/yarn-project/end-to-end/src/shared/jest_setup.ts b/yarn-project/end-to-end/src/shared/jest_setup.ts new file mode 100644 index 00000000000..6c2c8d88097 --- /dev/null +++ b/yarn-project/end-to-end/src/shared/jest_setup.ts @@ -0,0 +1,13 @@ +import { createDebugLogger } from '@aztec/aztec.js'; + +import { beforeEach, expect } from '@jest/globals'; +import { basename } from 'path'; + +beforeEach(() => { + const { testPath, currentTestName } = expect.getState(); + if (!testPath || !currentTestName) { + return; + } + const logger = createDebugLogger(`aztec:${basename(testPath).replace('.test.ts', '')}`); + logger.info(`Running test: ${currentTestName}`); +}); From 790ea5aadb212408ff609763898b54db4e45a784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Thu, 1 Aug 2024 00:52:37 +0200 Subject: [PATCH 27/35] fix: key-rotation related issues in `TokenWithRefunds` (#7631) Fixes #7323 Fixes #7324 Fixes #7326 --- .../aztec-nr/aztec/src/note/utils.nr | 12 +- .../private_fpc_contract/src/main.nr | 8 +- .../token_with_refunds_contract/src/main.nr | 401 +++++++++++++++--- .../src/test/basic.nr | 82 ++-- .../src/test/utils.nr | 49 ++- .../token_with_refunds_contract/src/types.nr | 1 + .../src/types/balances_map.nr | 92 ++-- .../src/types/token_note.nr | 14 +- .../src/types/transparent_note.nr | 88 ++++ .../end-to-end/src/e2e_fees/fees_test.ts | 7 +- .../src/e2e_fees/private_refunds.test.ts | 29 +- 11 files changed, 557 insertions(+), 226 deletions(-) create mode 100644 noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/transparent_note.nr diff --git a/noir-projects/aztec-nr/aztec/src/note/utils.nr b/noir-projects/aztec-nr/aztec/src/note/utils.nr index 5e8ff069687..094fdc81476 100644 --- a/noir-projects/aztec-nr/aztec/src/note/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/note/utils.nr @@ -12,21 +12,21 @@ use dep::protocol_types::{ }; use dep::std::{embedded_curve_ops::multi_scalar_mul, hash::from_field_unsafe}; -pub fn compute_slotted_note_hash_raw(storage_slot: Field, note_hiding_point: Point) -> Field { +pub fn compute_slotted_note_hiding_point_raw(storage_slot: Field, note_hiding_point: Point) -> Point { + // 1. We derive the storage slot point by multiplying the storage slot with the generator G_slot. // We use the unsafe version because the multi_scalar_mul will constrain the scalars. let storage_slot_scalar = from_field_unsafe(storage_slot); let storage_slot_point = multi_scalar_mul([G_slot], [storage_slot_scalar]); - let slotted_note_hiding_point = storage_slot_point + note_hiding_point; - let slotted_note_hash = slotted_note_hiding_point.x; - slotted_note_hash + // 2. Then we compute the slotted note hiding point by adding the storage slot point to the note hiding point. + storage_slot_point + note_hiding_point } pub fn compute_slotted_note_hash(note: Note) -> Field where Note: NoteInterface { let header = note.get_header(); - let note_hash = note.compute_note_hiding_point(); + let note_hiding_point = note.compute_note_hiding_point(); - compute_slotted_note_hash_raw(header.storage_slot, note_hash) + compute_slotted_note_hiding_point_raw(header.storage_slot, note_hiding_point).x } pub fn compute_siloed_nullifier( diff --git a/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr index 238ae7f4fca..60abc87e0ba 100644 --- a/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr @@ -9,14 +9,14 @@ contract PrivateFPC { #[aztec(storage)] struct Storage { other_asset: SharedImmutable, - admin_npk_m_hash: SharedImmutable + admin: SharedImmutable, } #[aztec(public)] #[aztec(initializer)] - fn constructor(other_asset: AztecAddress, admin_npk_m_hash: Field) { + fn constructor(other_asset: AztecAddress, admin: AztecAddress) { storage.other_asset.initialize(other_asset); - storage.admin_npk_m_hash.initialize(admin_npk_m_hash); + storage.admin.initialize(admin); } #[aztec(private)] @@ -32,7 +32,7 @@ contract PrivateFPC { emit_randomness_as_unencrypted_log(&mut context, fee_payer_randomness); TokenWithRefunds::at(asset).setup_refund( - storage.admin_npk_m_hash.read_private(), + storage.admin.read_private(), context.msg_sender(), amount, user_randomness, diff --git a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr index 9a943af45e7..5cde52d8ef1 100644 --- a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr @@ -1,31 +1,68 @@ +// docs:start:token_all +// docs:start:imports mod types; mod test; -// Minimal token implementation that supports `AuthWit` accounts and private refunds +// Copy of standard token contract enhanced with refund functionality. contract TokenWithRefunds { + // Libs + use dep::compressed_string::FieldCompressedString; + use dep::aztec::{ - note::utils::compute_slotted_note_hash_raw, hash::compute_secret_hash, + hash::compute_secret_hash, prelude::{NoteGetterOptions, Map, PublicMutable, SharedImmutable, PrivateSet, AztecAddress}, - protocol_types::{abis::function_selector::FunctionSelector, point::Point, hash::pedersen_hash}, - oracle::unsafe_rand::unsafe_rand, - encrypted_logs::encrypted_note_emission::{encode_and_encrypt_note, encode_and_encrypt_note_with_keys} + encrypted_logs::{ + encrypted_note_emission::{ + encode_and_encrypt_note, encode_and_encrypt_note_with_keys, + encode_and_encrypt_note_with_keys_unconstrained + }, + encrypted_event_emission::{encode_and_encrypt_event, encode_and_encrypt_event_with_keys_unconstrained} + } }; - use dep::authwit::{auth::{assert_current_call_valid_authwit, assert_current_call_valid_authwit_public}}; - use crate::types::{token_note::{TokenNote, TOKEN_NOTE_LEN}, balances_map::BalancesMap}; + // docs:start:import_authwit + use dep::authwit::auth::{assert_current_call_valid_authwit, assert_current_call_valid_authwit_public, compute_authwit_nullifier}; + // docs:end:import_authwit + + use crate::types::{transparent_note::TransparentNote, token_note::{TokenNote, TOKEN_NOTE_LEN}, balances_map::BalancesMap}; + // docs:end::imports + + // TODO(#7425): Rename back to `Transfer` + #[aztec(event)] + struct Transfer2 { + from: AztecAddress, + to: AztecAddress, + amount: Field, + } + + // docs:start:storage_struct #[aztec(storage)] struct Storage { + // docs:start:storage_admin admin: PublicMutable, + // docs:end:storage_admin + // docs:start:storage_minters minters: Map>, + // docs:end:storage_minters + // docs:start:storage_balances balances: BalancesMap, + // docs:end:storage_balances total_supply: PublicMutable, + // docs:start:storage_pending_shields + pending_shields: PrivateSet, + // docs:end:storage_pending_shields + public_balances: Map>, symbol: SharedImmutable, name: SharedImmutable, + // docs:start:storage_decimals decimals: SharedImmutable, + // docs:end:storage_decimals } + // docs:end:storage_struct + // docs:start:constructor #[aztec(public)] #[aztec(initializer)] fn constructor(admin: AztecAddress, name: str<31>, symbol: str<31>, decimals: u8) { @@ -34,128 +71,367 @@ contract TokenWithRefunds { storage.minters.at(admin).write(true); storage.name.initialize(FieldCompressedString::from_string(name)); storage.symbol.initialize(FieldCompressedString::from_string(symbol)); + // docs:start:initialize_decimals storage.decimals.initialize(decimals); + // docs:end:initialize_decimals } + // docs:end:constructor + // docs:start:set_admin #[aztec(public)] fn set_admin(new_admin: AztecAddress) { assert(storage.admin.read().eq(context.msg_sender()), "caller is not admin"); + // docs:start:write_admin storage.admin.write(new_admin); + // docs:end:write_admin } + // docs:end:set_admin #[aztec(public)] + #[aztec(view)] fn public_get_name() -> pub FieldCompressedString { storage.name.read_public() } #[aztec(private)] + #[aztec(view)] fn private_get_name() -> pub FieldCompressedString { storage.name.read_private() } - unconstrained fn un_get_name() -> pub [u8; 31] { - storage.name.read_public().to_bytes() - } - #[aztec(public)] + #[aztec(view)] fn public_get_symbol() -> pub FieldCompressedString { storage.symbol.read_public() } #[aztec(private)] + #[aztec(view)] fn private_get_symbol() -> pub FieldCompressedString { storage.symbol.read_private() } - unconstrained fn un_get_symbol() -> pub [u8; 31] { - storage.symbol.read_public().to_bytes() - } - #[aztec(public)] + #[aztec(view)] fn public_get_decimals() -> pub u8 { + // docs:start:read_decimals_public storage.decimals.read_public() + // docs:end:read_decimals_public } #[aztec(private)] + #[aztec(view)] fn private_get_decimals() -> pub u8 { + // docs:start:read_decimals_private storage.decimals.read_private() + // docs:end:read_decimals_private } - unconstrained fn un_get_decimals() -> pub u8 { - storage.decimals.read_public() + // docs:start:admin + #[aztec(public)] + #[aztec(view)] + fn admin() -> Field { + storage.admin.read().to_field() } + // docs:end:admin + // docs:start:is_minter + #[aztec(public)] + #[aztec(view)] + fn is_minter(minter: AztecAddress) -> bool { + storage.minters.at(minter).read() + } + // docs:end:is_minter + + // docs:start:total_supply + #[aztec(public)] + #[aztec(view)] + fn total_supply() -> Field { + storage.total_supply.read().to_integer() + } + // docs:end:total_supply + + // docs:start:balance_of_public + #[aztec(public)] + #[aztec(view)] + fn balance_of_public(owner: AztecAddress) -> Field { + storage.public_balances.at(owner).read().to_integer() + } + // docs:end:balance_of_public + + // docs:start:set_minter #[aztec(public)] fn set_minter(minter: AztecAddress, approve: bool) { + // docs:start:read_admin assert(storage.admin.read().eq(context.msg_sender()), "caller is not admin"); + // docs:end:read_admin + // docs:start:write_minter storage.minters.at(minter).write(approve); + // docs:end:write_minter + } + // docs:end:set_minter + + // docs:start:mint_public + #[aztec(public)] + fn mint_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 + let amount = U128::from_integer(amount); + let new_balance = storage.public_balances.at(to).read().add(amount); + let supply = storage.total_supply.read().add(amount); + + storage.public_balances.at(to).write(new_balance); + storage.total_supply.write(supply); } + // docs:end:mint_public + + // docs:start:mint_private + #[aztec(public)] + fn mint_private(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 + + // TODO: Nuke this - test functions do not belong to token contract! #[aztec(private)] fn privately_mint_private_note(amount: Field) { let caller = context.msg_sender(); - let header = context.get_header(); - let caller_npk_m_hash = header.get_npk_m_hash(&mut context, caller); - storage.balances.add(caller_npk_m_hash, U128::from_integer(amount)).emit(encode_and_encrypt_note(&mut context, caller, caller)); + storage.balances.add(caller, U128::from_integer(amount)).emit(encode_and_encrypt_note(&mut context, caller, caller)); + TokenWithRefunds::at(context.this_address()).assert_minter_and_mint(context.msg_sender(), amount).enqueue(&mut context); } #[aztec(public)] + #[aztec(internal)] fn assert_minter_and_mint(minter: AztecAddress, amount: Field) { assert(storage.minters.at(minter).read(), "caller is not minter"); let supply = storage.total_supply.read() + U128::from_integer(amount); storage.total_supply.write(supply); } + // docs:start:shield + #[aztec(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 + #[aztec(public)] + fn transfer_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 { + assert(nonce == 0, "invalid nonce"); + } + + let amount = U128::from_integer(amount); + let from_balance = storage.public_balances.at(from).read().sub(amount); + storage.public_balances.at(from).write(from_balance); + + let to_balance = storage.public_balances.at(to).read().add(amount); + storage.public_balances.at(to).write(to_balance); + } + // docs:end:transfer_public + + // docs:start:burn_public + #[aztec(public)] + fn burn_public(from: AztecAddress, amount: Field, nonce: Field) { + // docs:start:assert_current_call_valid_authwit_public + if (!from.eq(context.msg_sender())) { + assert_current_call_valid_authwit_public(&mut context, from); + } else { + assert(nonce == 0, "invalid nonce"); + } + // docs:end:assert_current_call_valid_authwit_public + + let amount = U128::from_integer(amount); + let from_balance = storage.public_balances.at(from).read().sub(amount); + storage.public_balances.at(from).write(from_balance); + + let new_supply = storage.total_supply.read().sub(amount); + storage.total_supply.write(new_supply); + } + // docs:end:burn_public + + // docs:start:redeem_shield #[aztec(private)] - fn transfer_from(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { + fn redeem_shield(to: AztecAddress, amount: Field, secret: Field) { + let pending_shields = storage.pending_shields; + let secret_hash = compute_secret_hash(secret); + // Get 1 note (set_limit(1)) which has amount stored in field with index 0 (select(0, amount)) and secret_hash + // stored in field with index 1 (select(1, secret_hash)). + let mut options = NoteGetterOptions::new(); + options = options.select(TransparentNote::properties().amount, amount, Option::none()).select( + TransparentNote::properties().secret_hash, + secret_hash, + Option::none() + ).set_limit(1); + let notes = pending_shields.get_notes(options); + let note = notes.get_unchecked(0); + // Remove the note from the pending shields set + pending_shields.remove(note); + + // 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(); + storage.balances.add(to, U128::from_integer(amount)).emit(encode_and_encrypt_note(&mut context, from, to)); + } + // docs:end:redeem_shield + + // docs:start:unshield + #[aztec(private)] + fn unshield(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { if (!from.eq(context.msg_sender())) { assert_current_call_valid_authwit(&mut context, from); } else { assert(nonce == 0, "invalid nonce"); } + storage.balances.sub(from, U128::from_integer(amount)).emit(encode_and_encrypt_note(&mut context, from, from)); + + TokenWithRefunds::at(context.this_address())._increase_public_balance(to, amount).enqueue(&mut context); + } + // docs:end:unshield + + // docs:start:transfer + #[aztec(private)] + fn transfer(to: AztecAddress, amount: Field) { + let from = context.msg_sender(); + + // By fetching the keys here, we can avoid doing an extra read from the storage, since from_ovpk would + // be needed twice. let header = context.get_header(); let from_ovpk = header.get_ovpk_m(&mut context, from); let from_ivpk = header.get_ivpk_m(&mut context, from); - let from_npk_m_hash = header.get_npk_m_hash(&mut context, from); let to_ivpk = header.get_ivpk_m(&mut context, to); - let to_npk_m_hash = header.get_npk_m_hash(&mut context, to); let amount = U128::from_integer(amount); - storage.balances.sub(from_npk_m_hash, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, from_ivpk, from)); - storage.balances.add(to_npk_m_hash, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, to_ivpk, to)); + storage.balances.sub(from, amount).emit(encode_and_encrypt_note_with_keys_unconstrained(&mut context, from_ovpk, from_ivpk, from)); + storage.balances.add(to, amount).emit(encode_and_encrypt_note_with_keys_unconstrained(&mut context, from_ovpk, to_ivpk, to)); + + Transfer2 { from, to, amount: amount.to_field() }.emit(encode_and_encrypt_event_with_keys_unconstrained(&mut context, from_ovpk, to_ivpk, to)); } + // docs:end:transfer + /** + * Cancel a private authentication witness. + * @param inner_hash The inner hash of the authwit to cancel. + */ + // docs:start:cancel_authwit #[aztec(private)] - fn transfer(to: AztecAddress, amount: Field) { - let from = context.msg_sender(); + fn cancel_authwit(inner_hash: Field) { + let on_behalf_of = context.msg_sender(); + let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash); + context.push_nullifier(nullifier, 0); + } + // docs:end:cancel_authwit + + // docs:start:transfer_from + #[aztec(private)] + fn transfer_from(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); + } else { + assert(nonce == 0, "invalid nonce"); + } + // docs:end:assert_current_call_valid_authwit + + // By fetching the keys here, we can avoid doing an extra read from the storage, since from_ovpk would + // be needed twice. let header = context.get_header(); let from_ovpk = header.get_ovpk_m(&mut context, from); let from_ivpk = header.get_ivpk_m(&mut context, from); - let from_npk_m_hash = header.get_npk_m_hash(&mut context, from); let to_ivpk = header.get_ivpk_m(&mut context, to); - let to_npk_m_hash = header.get_npk_m_hash(&mut context, to); let amount = U128::from_integer(amount); - storage.balances.sub(from_npk_m_hash, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, from_ivpk, from)); - storage.balances.add(to_npk_m_hash, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, to_ivpk, to)); + // docs:start:increase_private_balance + // docs:start:encrypted + storage.balances.sub(from, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, from_ivpk, from)); + // docs:end:encrypted + // docs:end:increase_private_balance + storage.balances.add(to, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, to_ivpk, to)); } + // docs:end:transfer_from + // docs:start:burn #[aztec(private)] - fn balance_of_private(owner: AztecAddress) -> pub Field { - let header = context.get_header(); - let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); - storage.balances.to_unconstrained().balance_of(owner_npk_m_hash).to_integer() + fn burn(from: AztecAddress, amount: Field, nonce: Field) { + if (!from.eq(context.msg_sender())) { + assert_current_call_valid_authwit(&mut context, from); + } else { + assert(nonce == 0, "invalid nonce"); + } + + storage.balances.sub(from, U128::from_integer(amount)).emit(encode_and_encrypt_note(&mut context, from, from)); + + TokenWithRefunds::at(context.this_address())._reduce_total_supply(amount).enqueue(&mut context); } + // docs:end:burn + + /// Internal /// - unconstrained fn balance_of_unconstrained(owner_npk_m_hash: Field) -> pub Field { - storage.balances.balance_of(owner_npk_m_hash).to_integer() + // docs:start:increase_public_balance + #[aztec(public)] + #[aztec(internal)] + fn _increase_public_balance(to: AztecAddress, amount: Field) { + let new_balance = storage.public_balances.at(to).read().add(U128::from_integer(amount)); + storage.public_balances.at(to).write(new_balance); } + // docs:end:increase_public_balance + + // docs:start:reduce_total_supply + #[aztec(public)] + #[aztec(internal)] + fn _reduce_total_supply(amount: Field) { + // Only to be called from burn. + let new_supply = storage.total_supply.read().sub(U128::from_integer(amount)); + storage.total_supply.write(new_supply); + } + // docs:end:reduce_total_supply + + /// Unconstrained /// + + // docs:start:balance_of_private + unconstrained fn balance_of_private(owner: AztecAddress) -> pub Field { + storage.balances.balance_of(owner).to_field() + } + // docs:end:balance_of_private + + // REFUNDS SPECIFIC FUNCTIONALITY FOLLOWS + use dep::aztec::{ + note::utils::compute_slotted_note_hiding_point_raw, prelude::FunctionSelector, + protocol_types::{storage::map::derive_storage_slot_in_map, point::Point} + }; #[aztec(private)] fn setup_refund( - fee_payer_npk_m_hash: Field, // NpkMHash of the entity which will receive the fee note. + fee_payer: AztecAddress, // Address of the entity which will receive the fee note. user: AztecAddress, // A user for which we are setting up the fee refund. funded_amount: Field, // The amount the user funded the fee payer with (represents fee limit). user_randomness: Field, // A randomness to mix in with the generated refund note for the sponsored user. @@ -165,8 +441,9 @@ contract TokenWithRefunds { // the authwit flow here and check that the user really permitted fee_payer to set up a refund on their behalf. assert_current_call_valid_authwit(&mut context, user); - // 2. Get all the relevant user keys + // 2. Get all the relevant keys let header = context.get_header(); + let fee_payer_npk_m_hash = header.get_npk_m_hash(&mut context, fee_payer); let user_npk_m_hash = header.get_npk_m_hash(&mut context, user); let user_ovpk = header.get_ovpk_m(&mut context, user); let user_ivpk = header.get_ivpk_m(&mut context, user); @@ -174,8 +451,7 @@ contract TokenWithRefunds { // 3. Deduct the funded amount from the user's balance - this is a maximum fee a user is willing to pay // (called fee limit in aztec spec). The difference between fee limit and the actual tx fee will be refunded // to the user in the `complete_refund(...)` function. - // TODO(#7324), TODO(#7323): using npk_m_hash here is vulnerable in 2 ways described in the linked issues. - storage.balances.sub(user_npk_m_hash, U128::from_integer(funded_amount)).emit(encode_and_encrypt_note_with_keys(&mut context, user_ovpk, user_ivpk, user)); + storage.balances.sub(user, U128::from_integer(funded_amount)).emit(encode_and_encrypt_note_with_keys(&mut context, user_ovpk, user_ivpk, user)); // 4. We generate the refund points. let (fee_payer_point, user_point) = TokenNote::generate_refund_points( @@ -186,13 +462,20 @@ contract TokenWithRefunds { fee_payer_randomness ); - // 5. Set the public teardown function to `complete_refund(...)`. Public teardown is the only time when a public + // 5. Now we "manually" compute the slots and the slotted note hiding points + let fee_payer_balances_slot = derive_storage_slot_in_map(TokenWithRefunds::storage().balances.slot, fee_payer); + let user_balances_slot = derive_storage_slot_in_map(TokenWithRefunds::storage().balances.slot, user); + + let slotted_fee_payer_point = compute_slotted_note_hiding_point_raw(fee_payer_balances_slot, fee_payer_point); + let slotted_user_point = compute_slotted_note_hiding_point_raw(user_balances_slot, user_point); + + // 6. 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(), FunctionSelector::from_signature("complete_refund((Field,Field,bool),(Field,Field,bool))"), [ - fee_payer_point.x, fee_payer_point.y, fee_payer_point.is_infinite as Field, user_point.x, user_point.y, user_point.is_infinite as Field + slotted_fee_payer_point.x, slotted_fee_payer_point.y, slotted_fee_payer_point.is_infinite as Field, slotted_user_point.x, slotted_user_point.y, slotted_user_point.is_infinite as Field ] ); } @@ -203,35 +486,13 @@ contract TokenWithRefunds { // 1. We get the final note hiding points by calling a `complete_refund` function on the note. // We use 1:1 exchange rate between fee juice and token. So using `tx_fee` is enough let tx_fee = context.transaction_fee(); - let (fee_payer_note_hiding_point, user_note_hiding_point) = TokenNote::complete_refund(fee_payer_point, user_point, tx_fee); + let (fee_payer_note_hash, user_note_hash) = TokenNote::complete_refund(fee_payer_point, user_point, tx_fee); // 2. At last we emit the note hashes. - context.push_note_hash(fee_payer_note_hiding_point.x); - context.push_note_hash(user_note_hiding_point.x); + context.push_note_hash(fee_payer_note_hash); + context.push_note_hash(user_note_hash); // --> Once the tx is settled user and fee recipient can add the notes to their pixies. } - - /// Internal /// - - #[aztec(public)] - #[aztec(internal)] - fn _reduce_total_supply(amount: Field) { - // Only to be called from burn. - let new_supply = storage.total_supply.read().sub(U128::from_integer(amount)); - storage.total_supply.write(new_supply); - } - - /// Unconstrained /// - - unconstrained fn admin() -> pub Field { - storage.admin.read().to_field() - } - - unconstrained fn is_minter(minter: AztecAddress) -> pub bool { - storage.minters.at(minter).read() - } - - unconstrained fn total_supply() -> pub Field { - storage.total_supply.read().to_integer() - } + // END OF REFUNDS SPECIFIC FUNCTIONALITY } +// docs:end:token_all \ No newline at end of file diff --git a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/basic.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/basic.nr index 98510f8a443..af5837f0711 100644 --- a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/basic.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/basic.nr @@ -1,100 +1,70 @@ -use crate::test::utils; +use crate::{test::utils, TokenWithRefunds, types::token_note::TokenNote}; + use dep::aztec::{ test::helpers::cheatcodes, oracle::unsafe_rand::unsafe_rand, hash::compute_secret_hash, - prelude::NoteHeader + prelude::NoteHeader, protocol_types::storage::map::derive_storage_slot_in_map }; -use crate::TokenWithRefunds; -use crate::types::token_note::TokenNote; use dep::authwit::cheatcodes as authwit_cheatcodes; -#[test] -unconstrained fn transfer_success() { - let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(true); - - let transfer_amount = 1_000; - - let transfer_private_from_call_interface = TokenWithRefunds::at(token_contract_address).transfer_from(owner, recipient, transfer_amount, 1); - - authwit_cheatcodes::add_private_authwit_from_call_interface(owner, recipient, transfer_private_from_call_interface); - - env.impersonate(recipient); - // Transfer tokens - env.call_private_void(transfer_private_from_call_interface); - // Check balances - utils::check_private_balance( - &mut env.private(), - token_contract_address, - owner, - mint_amount - transfer_amount - ); - utils::check_private_balance( - &mut env.private(), - token_contract_address, - recipient, - transfer_amount - ); -} - #[test] unconstrained fn setup_refund_success() { let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(true); + // Renaming owner and recipient to match naming in TokenWithRefunds + let user = owner; + let fee_payer = recipient; + let funded_amount = 1_000; let user_randomness = 42; let fee_payer_randomness = 123; let mut context = env.private(); - let recipient_npk_m_hash = context.get_header().get_npk_m_hash(&mut context, recipient); let setup_refund_from_call_interface = TokenWithRefunds::at(token_contract_address).setup_refund( - recipient_npk_m_hash, // fee payer - owner, // sponsored user + fee_payer, + user, funded_amount, user_randomness, fee_payer_randomness ); - authwit_cheatcodes::add_private_authwit_from_call_interface(owner, recipient, setup_refund_from_call_interface); + authwit_cheatcodes::add_private_authwit_from_call_interface(user, fee_payer, setup_refund_from_call_interface); - env.impersonate(recipient); + env.impersonate(fee_payer); env.call_private_void(setup_refund_from_call_interface); let mut context = env.private(); - let owner_npk_m_hash = context.get_header().get_npk_m_hash(&mut context, owner); - let recipient_npk_m_hash = context.get_header().get_npk_m_hash(&mut context, recipient); + let user_npk_m_hash = context.get_header().get_npk_m_hash(&mut context, user); + let fee_payer_npk_m_hash = context.get_header().get_npk_m_hash(&mut context, fee_payer); + + let fee_payer_balances_slot = derive_storage_slot_in_map(TokenWithRefunds::storage().balances.slot, fee_payer); + let user_balances_slot = derive_storage_slot_in_map(TokenWithRefunds::storage().balances.slot, user); - // when the refund was set up, we would've broken the note worth mint_amount, and added back a note worth - // mint_amount - funded_amount - // then when completing the refund, we would've constructed a hash corresponding to a note worth - // funded_amount - transaction_fee - // we "know" the transaction fee was 1 (it is hardcoded in TXE oracle) - // but we need to notify TXE of the note (preimage) + // When the refund was set up, we would've spent the note worth mint_amount, and inserted a note worth + //`mint_amount - funded_amount`. When completing the refund, we would've constructed a hash corresponding to a note + // worth `funded_amount - transaction_fee`. We "know" the transaction fee was 1 (it is hardcoded in TXE oracle) + // but we need to notify TXE of the note (preimage). env.store_note_in_cache( &mut TokenNote { amount: U128::from_integer(funded_amount - 1), - npk_m_hash: owner_npk_m_hash, + npk_m_hash: user_npk_m_hash, randomness: user_randomness, header: NoteHeader::empty() }, - TokenWithRefunds::storage().balances.slot, + user_balances_slot, token_contract_address ); env.store_note_in_cache( &mut TokenNote { amount: U128::from_integer(1), - npk_m_hash: recipient_npk_m_hash, + npk_m_hash: fee_payer_npk_m_hash, randomness: fee_payer_randomness, header: NoteHeader::empty() }, - TokenWithRefunds::storage().balances.slot, + fee_payer_balances_slot, token_contract_address ); - utils::check_private_balance( - &mut env.private(), - token_contract_address, - owner, - mint_amount - 1 - ); - utils::check_private_balance(&mut env.private(), token_contract_address, recipient, 1) + utils::check_private_balance(token_contract_address, user, mint_amount - 1); + utils::check_private_balance(token_contract_address, fee_payer, 1) } diff --git a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/utils.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/utils.nr index b2dfd177921..770c87dba8d 100644 --- a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/utils.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/utils.nr @@ -1,12 +1,10 @@ use dep::aztec::{ hash::compute_secret_hash, prelude::AztecAddress, test::helpers::{cheatcodes, test_environment::TestEnvironment}, - note::{note_getter::{MAX_NOTES_PER_PAGE, view_notes}, note_viewer_options::NoteViewerOptions}, - oracle::{execution::get_contract_address, unsafe_rand::unsafe_rand, storage::storage_read}, - context::PrivateContext + oracle::{execution::get_contract_address, unsafe_rand::unsafe_rand} }; -use crate::{types::{token_note::TokenNote}, TokenWithRefunds}; +use crate::{types::{token_note::TokenNote, transparent_note::TransparentNote}, TokenWithRefunds}; pub fn setup(with_account_contracts: bool) -> (&mut TestEnvironment, AztecAddress, AztecAddress, AztecAddress) { // Setup env, generate keys @@ -35,36 +33,47 @@ pub fn setup(with_account_contracts: bool) -> (&mut TestEnvironment, AztecAddres ); let token_contract = env.deploy_self("TokenWithRefunds").with_public_initializer(initializer_call_interface); let token_contract_address = token_contract.to_address(); - env.advance_block_by(6); + env.advance_block_by(1); (&mut env, token_contract_address, owner, recipient) } pub fn setup_and_mint(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 = 10_000; - let mint_private_call_interface = TokenWithRefunds::at(token_contract_address).privately_mint_private_note(mint_amount); - env.call_private_void(mint_private_call_interface); + let mint_amount = 10000; + // Mint some tokens + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + let mint_private_call_interface = TokenWithRefunds::at(token_contract_address).mint_private(mint_amount, secret_hash); + env.call_public(mint_private_call_interface); + + let mint_public_call_interface = TokenWithRefunds::at(token_contract_address).mint_public(owner, mint_amount); + env.call_public(mint_public_call_interface); + + // Time travel so we can read keys from the registry env.advance_block_by(6); - check_private_balance(&mut env.private(), token_contract_address, owner, mint_amount); + // docs:start:txe_test_store_note + // Store a note in the cache so we can redeem it + env.store_note_in_cache( + &mut TransparentNote::new(mint_amount, secret_hash), + TokenWithRefunds::storage().pending_shields.slot, + token_contract_address + ); + // docs:end:txe_test_store_note + + // Redeem our shielded tokens + let redeem_shield_call_interface = TokenWithRefunds::at(token_contract_address).redeem_shield(owner, mint_amount, secret); + env.call_private_void(redeem_shield_call_interface); (env, token_contract_address, owner, recipient, mint_amount) } -pub fn check_private_balance( - context: &mut PrivateContext, - token_contract_address: AztecAddress, - address: AztecAddress, - address_amount: Field -) { +pub fn check_private_balance(token_contract_address: AztecAddress, address: AztecAddress, address_amount: Field) { let current_contract_address = get_contract_address(); cheatcodes::set_contract_address(token_contract_address); - - let header = context.get_header(); - let owner_npk_m_hash = header.get_npk_m_hash(context, address); - - let balance_of_private = TokenWithRefunds::balance_of_unconstrained(owner_npk_m_hash); + // Direct call to unconstrained + let balance_of_private = TokenWithRefunds::balance_of_private(address); assert(balance_of_private == address_amount, "Private balance is not correct"); cheatcodes::set_contract_address(current_contract_address); } diff --git a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types.nr index ac754901ded..e162c8cae13 100644 --- a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types.nr @@ -1,2 +1,3 @@ mod balances_map; mod token_note; +mod transparent_note; diff --git a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/balances_map.nr index d70e62fa91c..63a0092ea5c 100644 --- a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/balances_map.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/balances_map.nr @@ -1,59 +1,56 @@ -use dep::aztec::prelude::{ - AztecAddress, NoteGetterOptions, NoteViewerOptions, NoteHeader, NoteInterface, PrivateContext, - PrivateSet, Map -}; +use dep::aztec::prelude::{AztecAddress, NoteGetterOptions, NoteViewerOptions, NoteHeader, NoteInterface, PrivateSet, Map}; use dep::aztec::{ - hash::pedersen_hash, protocol_types::constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, + context::{PrivateContext, UnconstrainedContext}, hash::pedersen_hash, + protocol_types::constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, note::{ - note_getter::view_notes, note_getter_options::{SortOrder, Comparator}, - note_emission::OuterNoteEmission -}, - context::UnconstrainedContext + note_getter::view_notes, note_getter_options::SortOrder, + note_emission::{NoteEmission, OuterNoteEmission} +} }; -use crate::types::token_note::{TokenNote, OwnedNote}; +use crate::types::{token_note::{TokenNote, OwnedNote}}; struct BalancesMap { - map: PrivateSet + map: Map, Context> } impl BalancesMap { pub fn new(context: Context, storage_slot: Field) -> Self { assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); - Self { map: PrivateSet::new(context, storage_slot) } + Self { + map: Map::new( + context, + storage_slot, + |context, slot| PrivateSet::new(context, slot) + ) + } } } impl BalancesMap { - unconstrained fn balance_of( + unconstrained pub fn balance_of( self: Self, - owner_npk_m_hash: Field + owner: AztecAddress ) -> U128 where T: NoteInterface + OwnedNote { - self.balance_of_with_offset(owner_npk_m_hash, 0) + self.balance_of_with_offset(owner, 0) } - unconstrained fn balance_of_with_offset( + unconstrained pub fn balance_of_with_offset( self: Self, - owner_npk_m_hash: Field, + owner: AztecAddress, offset: u32 ) -> U128 where T: NoteInterface + OwnedNote { let mut balance = U128::from_integer(0); + // docs:start:view_notes let mut options = NoteViewerOptions::new(); - - let notes = self.map.view_notes( - options.select( - T::get_owner_selector(), - owner_npk_m_hash, - Option::some(Comparator.EQ) - ) - ); - + let notes = self.map.at(owner).view_notes(options.set_offset(offset)); + // docs:end:view_notes for i in 0..options.limit { if i < notes.len() { balance = balance + notes.get_unchecked(i).get_amount(); } } if (notes.len() == options.limit) { - balance = balance + self.balance_of_with_offset(owner_npk_m_hash, offset + options.limit); + balance = balance + self.balance_of_with_offset(owner, offset + options.limit); } balance @@ -61,33 +58,36 @@ impl BalancesMap { } impl BalancesMap { - - pub fn to_unconstrained(self: Self) -> BalancesMap { - BalancesMap { map: PrivateSet::new(UnconstrainedContext::new(), self.map.storage_slot) } - } - pub fn add( self: Self, - owner_npk_m_hash: Field, + owner: AztecAddress, addend: U128 ) -> OuterNoteEmission where T: NoteInterface + OwnedNote + Eq { - let mut addend_note = T::new(addend, owner_npk_m_hash); - OuterNoteEmission::new(Option::some(self.map.insert(&mut addend_note))) + if addend == U128::from_integer(0) { + OuterNoteEmission::new(Option::none()) + } else { + let context = self.map.context; + let header = context.get_header(); + + // We fetch the nullifier public key hash from the registry / from our PXE + let owner_npk_m_hash = header.get_npk_m_hash(context, owner); + let mut addend_note = T::new(addend, owner_npk_m_hash); + + // docs:start:insert + OuterNoteEmission::new(Option::some(self.map.at(owner).insert(&mut addend_note))) + // docs:end:insert + } } pub fn sub( self: Self, - owner_npk_m_hash: Field, + owner: AztecAddress, subtrahend: U128 ) -> OuterNoteEmission where T: NoteInterface + OwnedNote + Eq { - let mut options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend); - let notes = self.map.get_notes( - options.select( - T::get_owner_selector(), - owner_npk_m_hash, - Option::some(Comparator.EQ) - ) - ); + // docs:start:get_notes + let options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend); + let notes = self.map.at(owner).get_notes(options); + // docs:end:get_notes let mut minuend: U128 = U128::from_integer(0); for i in 0..options.limit { @@ -99,7 +99,7 @@ impl BalancesMap { // which require knowledge of the secret key (currently the users encryption key). // The contract logic must ensure that the spending key is used as well. // docs:start:remove - self.map.remove(note); + self.map.at(owner).remove(note); // docs:end:remove minuend = minuend + note.get_amount(); @@ -111,7 +111,7 @@ impl BalancesMap { // without the == true, it includes 'minuend.ge(subtrahend)' as part of the error. assert(minuend >= subtrahend, "Balance too low"); - self.add(owner_npk_m_hash, minuend - subtrahend) + self.add(owner, minuend - subtrahend) } } diff --git a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr index c5251008c0f..5ba2b46b4ed 100644 --- a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr @@ -27,7 +27,7 @@ trait PrivatelyRefundable { incomplete_fee_payer_point: Point, incomplete_user_point: Point, transaction_fee: Field - ) -> (Point, Point); + ) -> (Field, Field); } global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. @@ -216,7 +216,6 @@ impl PrivatelyRefundable for TokenNote { // 3. We do the necessary conversion for values relevant for the sponsored user point. // We use the unsafe version because the multi_scalar_mul will constrain the scalars. let funded_amount_scalar = from_field_unsafe(funded_amount); - // TODO(#7324), TODO(#7323): using npk_m_hash here is vulnerable in 2 ways described in the linked issues. let user_npk_m_hash_scalar = from_field_unsafe(user_npk_m_hash); let user_randomness_scalar = from_field_unsafe(user_randomness); @@ -230,7 +229,7 @@ impl PrivatelyRefundable for TokenNote { (incomplete_fee_payer_point, incomplete_user_point) } - fn complete_refund(incomplete_fee_payer_point: Point, incomplete_user_point: Point, transaction_fee: Field) -> (Point, Point) { + fn complete_refund(incomplete_fee_payer_point: Point, incomplete_user_point: Point, transaction_fee: Field) -> (Field, Field) { // 1. We convert the transaction fee to high and low limbs to be able to use BB API. // We use the unsafe version because the multi_scalar_mul will constrain the scalars. let transaction_fee_scalar = from_field_unsafe(transaction_fee); @@ -248,7 +247,12 @@ impl PrivatelyRefundable for TokenNote { assert_eq(user_point.is_infinite, false); - // Finally we return the points which represent the note hiding points. - (fee_payer_point, user_point) + // 4. We no longer need to do any elliptic curve operations with the points so we collapse them to the final + // note hashes. + let fee_payer_note_hash = fee_payer_point.x; + let user_note_hash = user_point.x; + + // 5. Finally we return the hashes. + (fee_payer_note_hash, user_note_hash) } } diff --git a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/transparent_note.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/transparent_note.nr new file mode 100644 index 00000000000..e3b028c722a --- /dev/null +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/transparent_note.nr @@ -0,0 +1,88 @@ +// docs:start:token_types_all +use dep::aztec::{ + note::{note_getter_options::PropertySelector, utils::compute_note_hash_for_consumption}, + prelude::{NoteHeader, NoteInterface, PrivateContext}, + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, hash::poseidon2_hash} +}; + +global TRANSPARENT_NOTE_LEN: Field = 2; +// TRANSPARENT_NOTE_LEN * 32 + 32(storage_slot as bytes) + 32(note_type_id as bytes) +global TRANSPARENT_NOTE_BYTES_LEN: Field = 2 * 32 + 64; + +// 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). +#[aztec(note)] +struct TransparentNote { + amount: Field, + secret_hash: Field, +} + +struct TransparentNoteProperties { + amount: PropertySelector, + secret_hash: PropertySelector, +} + +impl NoteInterface for TransparentNote { + + // Custom serialization to avoid disclosing the secret field + fn serialize_content(self) -> [Field; TRANSPARENT_NOTE_LEN] { + [self.amount, self.secret_hash] + } + + // Custom deserialization since we don't have access to the secret plaintext + fn deserialize_content(serialized_note: [Field; TRANSPARENT_NOTE_LEN]) -> Self { + TransparentNote { + amount: serialized_note[0], + secret_hash: serialized_note[1], + header: NoteHeader::empty(), + } + } + + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386): Ensure nullifier collisions are prevented + fn compute_note_hash_and_nullifier(self, _context: &mut PrivateContext) -> (Field, Field) { + self.compute_note_hash_and_nullifier_without_context() + } + + // 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_note_hash_and_nullifier_without_context(self) -> (Field, Field) { + let note_hash_for_nullify = compute_note_hash_for_consumption(self); + let nullifier = poseidon2_hash([ + note_hash_for_nullify, + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]); + (note_hash_for_nullify, nullifier) + } +} + +impl TransparentNote { + // CONSTRUCTORS + pub fn new(amount: Field, secret_hash: Field) -> Self { + TransparentNote { amount, secret_hash, header: NoteHeader::empty() } + } + + // CUSTOM FUNCTIONS FOR THIS NOTE TYPE + // Custom serialization forces us to manually create the metadata struct and its getter + pub fn properties() -> TransparentNoteProperties { + TransparentNoteProperties { + amount: PropertySelector { index: 0, offset: 0, length: 32 }, + secret_hash: PropertySelector { index: 1, offset: 0, length: 32 } + } + } +} + +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 \ No newline at end of file diff --git a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts index a3e0792c435..daa55f0dc1d 100644 --- a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts @@ -261,9 +261,12 @@ export class FeesTest { .deployed(); this.logger.info(`TokenWithRefunds deployed at ${tokenWithRefunds.address}`); - const adminKeyHash = this.bobWallet.getCompleteAddress().publicKeys.masterNullifierPublicKey.hash(); - const privateFPCSent = PrivateFPCContract.deploy(this.bobWallet, tokenWithRefunds.address, adminKeyHash).send(); + const privateFPCSent = PrivateFPCContract.deploy( + this.bobWallet, + tokenWithRefunds.address, + this.bobWallet.getAddress(), + ).send(); const privateFPC = await privateFPCSent.deployed(); this.logger.info(`PrivateFPC deployed at ${privateFPC.address}`); diff --git a/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts b/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts index bfee50babff..8549dcee1c2 100644 --- a/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts @@ -7,6 +7,7 @@ import { type Wallet, } from '@aztec/aztec.js'; import { Fr, type GasSettings } from '@aztec/circuits.js'; +import { deriveStorageSlotInMap } from '@aztec/circuits.js/hash'; import { FunctionSelector, FunctionType } from '@aztec/foundation/abi'; import { poseidon2Hash } from '@aztec/foundation/crypto'; import { type PrivateFPCContract, TokenWithRefundsContract } from '@aztec/noir-contracts.js'; @@ -48,13 +49,8 @@ describe('e2e_fees/private_refunds', () => { ]); }); - // This will get re-enabled in a PR up the stack. - it.skip('can do private payments and refunds', async () => { - // 1. We get the hash of Bob's master nullifier public key. The corresponding nullifier secret key can later on - // be used to nullify/spend the note that contains the npk_m_hash. - // TODO(#7324): The values in complete address are currently not updated after the keys are rotated so this does - // not work with key rotation as the key might be the old one and then we would fetch a new one in the contract. - const bobNpkMHash = t.bobWallet.getCompleteAddress().publicKeys.masterNullifierPublicKey.hash(); + it('can do private payments and refunds', async () => { + // 1. We generate randomness for Alice and derive randomness for Bob. const aliceRandomness = Fr.random(); // Called user_randomness in contracts const bobRandomness = poseidon2Hash([aliceRandomness]); // Called fee_payer_randomness in contracts @@ -70,7 +66,7 @@ describe('e2e_fees/private_refunds', () => { aliceWallet, aliceRandomness, bobRandomness, - bobNpkMHash, // We use Bob's npk_m_hash in the notes that contain the transaction fee. + t.bobWallet.getAddress(), // Bob is the recipient of the fee notes. ), }, }) @@ -87,8 +83,6 @@ describe('e2e_fees/private_refunds', () => { // the fee limit minus the final transaction fee. The other 2 fields in the note are Alice's npk_m_hash and // the randomness. const refundNoteValue = t.gasSettings.getFeeLimit().sub(new Fr(tx.transactionFee!)); - // TODO(#7324): The values in complete address are currently not updated after the keys are rotated so this does - // not work with key rotation as the key might be the old one and then we would fetch a new one in the contract. const aliceNpkMHash = t.aliceWallet.getCompleteAddress().publicKeys.masterNullifierPublicKey.hash(); const aliceRefundNote = new Note([refundNoteValue, aliceNpkMHash, aliceRandomness]); @@ -101,16 +95,17 @@ describe('e2e_fees/private_refunds', () => { aliceRefundNote, t.aliceAddress, tokenWithRefunds.address, - TokenWithRefundsContract.storage.balances.slot, + deriveStorageSlotInMap(TokenWithRefundsContract.storage.balances.slot, t.aliceAddress), TokenWithRefundsContract.notes.TokenNote.id, tx.txHash, ), ); // 6. Now we reconstruct the note for the final fee payment. It should contain the transaction fee, Bob's - // npk_m_hash (set in the paymentMethod above) and the randomness. + // npk_m_hash and the randomness. // Note that FPC emits randomness as unencrypted log and the tx fee is publicly know so Bob is able to reconstruct // his note just from on-chain data. + const bobNpkMHash = t.bobWallet.getCompleteAddress().publicKeys.masterNullifierPublicKey.hash(); const bobFeeNote = new Note([new Fr(tx.transactionFee!), bobNpkMHash, bobRandomness]); // 7. Once again we add the note to PXE which computes the note hash and checks that it is in the note hash tree. @@ -119,7 +114,7 @@ describe('e2e_fees/private_refunds', () => { bobFeeNote, t.bobAddress, tokenWithRefunds.address, - TokenWithRefundsContract.storage.balances.slot, + deriveStorageSlotInMap(TokenWithRefundsContract.storage.balances.slot, t.bobAddress), TokenWithRefundsContract.notes.TokenNote.id, tx.txHash, ), @@ -165,9 +160,9 @@ class PrivateRefundPaymentMethod implements FeePaymentMethod { private feePayerRandomness: Fr, /** - * The hash of the master nullifier public key that the FPC sends notes it receives to. + * Address that the FPC sends notes it receives to. */ - private feeRecipientNpkMHash: Fr, + private feeRecipient: AztecAddress, ) {} /** @@ -196,13 +191,13 @@ class PrivateRefundPaymentMethod implements FeePaymentMethod { action: { name: 'setup_refund', args: [ - this.feeRecipientNpkMHash, + this.feeRecipient, this.wallet.getCompleteAddress().address, maxFee, this.userRandomness, this.feePayerRandomness, ], - selector: FunctionSelector.fromSignature('setup_refund(Field,(Field),Field,Field,Field)'), + selector: FunctionSelector.fromSignature('setup_refund((Field),(Field),Field,Field,Field)'), type: FunctionType.PRIVATE, isStatic: false, to: this.asset, From 24e01fed89fa52456e4ee81a8f8897f09cf4bd2c Mon Sep 17 00:00:00 2001 From: AztecBot Date: Thu, 1 Aug 2024 02:19:54 +0000 Subject: [PATCH 28/35] git subrepo push --branch=master barretenberg subrepo: subdir: "barretenberg" merged: "f0a50e61d1" upstream: origin: "https://github.com/AztecProtocol/barretenberg" branch: "master" commit: "f0a50e61d1" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- barretenberg/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index 110cc633364..f9b45620dc4 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = c90da1e3b7eae0c5328081443fdfa8bfe1296445 - parent = dff2ffb81c8dab33567c1263cf412aacce89af66 + commit = f0a50e61d1713eb8b188d720fbe40a966919e85e + parent = 790ea5aadb212408ff609763898b54db4e45a784 method = merge cmdver = 0.4.6 From 3d9696d89ae9e1822cf685fd94570c6ba11916ce Mon Sep 17 00:00:00 2001 From: AztecBot Date: Thu, 1 Aug 2024 02:20:27 +0000 Subject: [PATCH 29/35] chore: replace relative paths to noir-protocol-circuits --- noir-projects/aztec-nr/aztec/Nargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/aztec/Nargo.toml b/noir-projects/aztec-nr/aztec/Nargo.toml index 7a1f1af5863..fb16331b042 100644 --- a/noir-projects/aztec-nr/aztec/Nargo.toml +++ b/noir-projects/aztec-nr/aztec/Nargo.toml @@ -5,4 +5,4 @@ compiler_version = ">=0.18.0" type = "lib" [dependencies] -protocol_types = { path = "../../noir-protocol-circuits/crates/types" } +protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.47.1", directory="noir-projects/noir-protocol-circuits/crates/types" } From 9e67798317d074b868d6de9d2649bd4d9139fc1b Mon Sep 17 00:00:00 2001 From: AztecBot Date: Thu, 1 Aug 2024 02:20:27 +0000 Subject: [PATCH 30/35] git_subrepo.sh: Fix parent in .gitrepo file. [skip ci] --- noir-projects/aztec-nr/.gitrepo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index 491a394e259..0a13c577a6d 100644 --- a/noir-projects/aztec-nr/.gitrepo +++ b/noir-projects/aztec-nr/.gitrepo @@ -9,4 +9,4 @@ remote = https://github.com/AztecProtocol/aztec-nr commit = 9a14f77b330bb363b6d6661f229b858246eccebb method = merge cmdver = 0.4.6 - parent = b5380c7e174c4724366cf0553b36674e0c904404 + parent = 197a474590bde744b4cd66713bf2a8e8055a78dd From c2076badca73a7a6d98350986dc069519543e4b6 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Thu, 1 Aug 2024 02:20:30 +0000 Subject: [PATCH 31/35] git subrepo push --branch=master noir-projects/aztec-nr subrepo: subdir: "noir-projects/aztec-nr" merged: "714772e145" upstream: origin: "https://github.com/AztecProtocol/aztec-nr" branch: "master" commit: "714772e145" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- noir-projects/aztec-nr/.gitrepo | 4 ++-- noir-projects/aztec-nr/aztec/Nargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index 0a13c577a6d..6eb62280d61 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 = 9a14f77b330bb363b6d6661f229b858246eccebb + commit = 714772e1455aee7811fbfeee0dbfc061ace0d4c9 method = merge cmdver = 0.4.6 - parent = 197a474590bde744b4cd66713bf2a8e8055a78dd + parent = dde929d6052cfa7970532250716bf78ad245ad0c diff --git a/noir-projects/aztec-nr/aztec/Nargo.toml b/noir-projects/aztec-nr/aztec/Nargo.toml index fb16331b042..7a1f1af5863 100644 --- a/noir-projects/aztec-nr/aztec/Nargo.toml +++ b/noir-projects/aztec-nr/aztec/Nargo.toml @@ -5,4 +5,4 @@ compiler_version = ">=0.18.0" type = "lib" [dependencies] -protocol_types = { git="https://github.com/AztecProtocol/aztec-packages", tag="aztec-packages-v0.47.1", directory="noir-projects/noir-protocol-circuits/crates/types" } +protocol_types = { path = "../../noir-protocol-circuits/crates/types" } From 55a39ac84367df240d4bb848fb3b15a5add11691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Thu, 1 Aug 2024 05:15:11 +0200 Subject: [PATCH 32/35] fix: checking funded amount is enough (#7648) --- .../token_with_refunds_contract/src/main.nr | 20 +++--- .../src/test/basic.nr | 37 ++++++++++- .../src/types/token_note.nr | 62 +++++++++---------- .../src/e2e_fees/private_refunds.test.ts | 36 ++++++++++- yarn-project/txe/package.json | 2 +- yarn-project/txe/src/oracle/txe_oracle.ts | 10 ++- 6 files changed, 122 insertions(+), 45 deletions(-) diff --git a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr index 5cde52d8ef1..06911c88348 100644 --- a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr @@ -457,7 +457,6 @@ contract TokenWithRefunds { let (fee_payer_point, user_point) = TokenNote::generate_refund_points( fee_payer_npk_m_hash, user_npk_m_hash, - funded_amount, user_randomness, fee_payer_randomness ); @@ -473,20 +472,25 @@ contract TokenWithRefunds { // 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(), - FunctionSelector::from_signature("complete_refund((Field,Field,bool),(Field,Field,bool))"), + FunctionSelector::from_signature("complete_refund((Field,Field,bool),(Field,Field,bool),Field)"), [ - slotted_fee_payer_point.x, slotted_fee_payer_point.y, slotted_fee_payer_point.is_infinite as Field, slotted_user_point.x, slotted_user_point.y, slotted_user_point.is_infinite as Field + slotted_fee_payer_point.x, slotted_fee_payer_point.y, slotted_fee_payer_point.is_infinite as Field, slotted_user_point.x, slotted_user_point.y, slotted_user_point.is_infinite as Field, funded_amount ] ); } #[aztec(public)] #[aztec(internal)] - fn complete_refund(fee_payer_point: Point, user_point: Point) { - // 1. We get the final note hiding points by calling a `complete_refund` function on the note. - // We use 1:1 exchange rate between fee juice and token. So using `tx_fee` is enough - let tx_fee = context.transaction_fee(); - let (fee_payer_note_hash, user_note_hash) = TokenNote::complete_refund(fee_payer_point, user_point, tx_fee); + fn complete_refund(fee_payer_point: Point, user_point: Point, funded_amount: Field) { + // 1. We get the final note hashes by calling a `complete_refund` function on the note. + // We use 1:1 exchange rate between fee juice and token so just passing transaction fee and funded amount + // to `complete_refund(...)` function is enough. + let (fee_payer_note_hash, user_note_hash) = TokenNote::complete_refund( + fee_payer_point, + user_point, + funded_amount, + context.transaction_fee() + ); // 2. At last we emit the note hashes. context.push_note_hash(fee_payer_note_hash); diff --git a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/basic.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/basic.nr index af5837f0711..a1ca536afe0 100644 --- a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/basic.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/test/basic.nr @@ -41,8 +41,8 @@ unconstrained fn setup_refund_success() { // When the refund was set up, we would've spent the note worth mint_amount, and inserted a note worth //`mint_amount - funded_amount`. When completing the refund, we would've constructed a hash corresponding to a note - // worth `funded_amount - transaction_fee`. We "know" the transaction fee was 1 (it is hardcoded in TXE oracle) - // but we need to notify TXE of the note (preimage). + // worth `funded_amount - transaction_fee`. We "know" the transaction fee was 1 (it is hardcoded in + // `executePublicFunction` TXE oracle) but we need to notify TXE of the note (preimage). env.store_note_in_cache( &mut TokenNote { amount: U128::from_integer(funded_amount - 1), @@ -68,3 +68,36 @@ unconstrained fn setup_refund_success() { utils::check_private_balance(token_contract_address, fee_payer, 1) } +// TODO(#7694): Ideally we would check the error message here but it's currently not possible because TXE does not +// support checking messages of errors thrown in a public teardown function. Once this is supported, check the message +// here and delete the e2e test checking it. +// #[test(should_fail_with = "tx fee is higher than funded amount")] +#[test(should_fail)] +unconstrained fn setup_refund_insufficient_funded_amount() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(true); + + // Renaming owner and recipient to match naming in TokenWithRefunds + let user = owner; + let fee_payer = recipient; + + // We set funded amount to 0 to make the transaction fee higher than the funded amount + let funded_amount = 0; + let user_randomness = 42; + let fee_payer_randomness = 123; + let mut context = env.private(); + + let setup_refund_from_call_interface = TokenWithRefunds::at(token_contract_address).setup_refund( + fee_payer, + user, + funded_amount, + user_randomness, + fee_payer_randomness + ); + + authwit_cheatcodes::add_private_authwit_from_call_interface(user, fee_payer, setup_refund_from_call_interface); + + env.impersonate(fee_payer); + + // The following should fail with "tx fee is higher than funded amount" because funded amount is 0 + env.call_private_void(setup_refund_from_call_interface); +} diff --git a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr index 5ba2b46b4ed..f5b0bc47eea 100644 --- a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/types/token_note.nr @@ -18,7 +18,6 @@ trait PrivatelyRefundable { fn generate_refund_points( fee_payer_npk_m_hash: Field, user_npk_m_hash: Field, - funded_amount: Field, user_randomness: Field, fee_payer_randomness: Field ) -> (Point, Point); @@ -26,6 +25,7 @@ trait PrivatelyRefundable { fn complete_refund( incomplete_fee_payer_point: Point, incomplete_user_point: Point, + funded_amount: Field, transaction_fee: Field ) -> (Field, Field); } @@ -157,25 +157,26 @@ impl OwnedNote for TokenNote { * * However we can still perform addition/subtraction on points! That is why we generate those two points, which are: * incomplete_fee_payer_point := G_npk * fee_payer_npk + G_rnd * fee_payer_randomness - * incomplete_user_point := G_npk * user_npk + G_amt * funded_amount + G_rnd * user_randomness - * - * where `funded_amount` is the total amount in tokens that the sponsored user initially supplied, from which - * the transaction fee will be subtracted. + * incomplete_user_point := G_npk * user_npk + G_rnd * user_randomness * * So we pass those points into the teardown function (here) and compute a third point corresponding to the transaction * fee as just: * * fee_point := G_amt * transaction_fee + * refund_point := G_amt * (funded_amount - transaction_fee) * - * Then we arrive at the final points via addition/subtraction of that transaction fee point: + * where `funded_amount` is the total amount in tokens that the sponsored user initially supplied and the transaction + * fee is the final transaction fee whose value is made available in the public teardown function. + * + * Then we arrive at the final points via addition of the fee and refund points: * * fee_payer_point := incomplete_fee_payer_point + fee_point = * = (G_npk * fee_payer_npk + G_rnd * fee_payer_randomness) + G_amt * transaction_fee = * = G_amt * transaction_fee + G_npk * fee_payer_npk + G_rnd * fee_payer_randomness * - * user_point := incomplete_user_point - fee_point = - * = (G_amt * funded_amount + G_npk * user_npk + G_rnd + user_randomness) - G_amt * transaction_fee = - * = G_amt * (funded_amount - transaction_fee) + G_npk * user_npk + G_rnd + user_randomness + * user_point := incomplete_user_point + refund_point = + * = (G_npk * user_npk + G_rnd + user_randomness) + G_amt * (funded_amount - transaction_fee) = + * = G_amt * (funded_amount - transaction_fee) + G_npk * user_npk + G_rnd * user_randomness * * The point above matches the note_hiding_point of (and therefore *is*) notes like: * { @@ -189,9 +190,8 @@ impl OwnedNote for TokenNote { * 1) randomness_influence = incomplete_fee_payer_point - G_npk * fee_payer_npk = * = (G_npk * fee_payer_npk + G_rnd * randomness) - G_npk * fee_payer_npk = * = G_rnd * randomness - * 2) user_fingerprint = incomplete_user_point - G_amt * funded_amount - randomness_influence = - * = (G_npk * user_npk + G_amt * funded_amount + G_rnd * randomness) - G_amt * funded_amount - * - G_rnd * randomness = + * 2) user_fingerprint = incomplete_user_point - randomness_influence = + * = (G_npk * user_npk + G_rnd * randomness) - G_rnd * randomness = * = G_npk * user_npk * 3) Then the second time the user would use this fee paying contract we would recover the same fingerprint and * link that the 2 transactions were made by the same user. Given that it's expected that only a limited set @@ -199,7 +199,7 @@ impl OwnedNote for TokenNote { * fee payer npk values of these known contracts is a feasible attack. */ impl PrivatelyRefundable for TokenNote { - fn generate_refund_points(fee_payer_npk_m_hash: Field, user_npk_m_hash: Field, funded_amount: Field, user_randomness: Field, fee_payer_randomness: Field) -> (Point, Point) { + fn generate_refund_points(fee_payer_npk_m_hash: Field, user_npk_m_hash: Field, user_randomness: Field, fee_payer_randomness: Field) -> (Point, Point) { // 1. To be able to multiply generators with randomness and npk_m_hash using barretneberg's (BB) blackbox // function we first need to convert the fields to high and low limbs. // We use the unsafe version because the multi_scalar_mul will constrain the scalars. @@ -215,44 +215,44 @@ impl PrivatelyRefundable for TokenNote { // 3. We do the necessary conversion for values relevant for the sponsored user point. // We use the unsafe version because the multi_scalar_mul will constrain the scalars. - let funded_amount_scalar = from_field_unsafe(funded_amount); let user_npk_m_hash_scalar = from_field_unsafe(user_npk_m_hash); let user_randomness_scalar = from_field_unsafe(user_randomness); - // 4. We compute `G_amt * funded_amount + G_npk * user_npk_m_hash + G_rnd * randomness`. + // 4. We compute `G_npk * user_npk_m_hash + G_rnd * randomness`. let incomplete_user_point = multi_scalar_mul( - [G_amt, G_npk, G_rnd], - [funded_amount_scalar, user_npk_m_hash_scalar, user_randomness_scalar] + [G_npk, G_rnd], + [user_npk_m_hash_scalar, user_randomness_scalar] ); // 5. At last we return the points. (incomplete_fee_payer_point, incomplete_user_point) } - fn complete_refund(incomplete_fee_payer_point: Point, incomplete_user_point: Point, transaction_fee: Field) -> (Field, Field) { - // 1. We convert the transaction fee to high and low limbs to be able to use BB API. + fn complete_refund(incomplete_fee_payer_point: Point, incomplete_user_point: Point, funded_amount: Field, transaction_fee: Field) -> (Field, Field) { + // 1. We check that user funded the fee payer contract with at least the transaction fee. + assert(!funded_amount.lt(transaction_fee), "tx fee is higher than funded amount"); // funded_amout >= transaction_fee + + // 2. We convert the transaction fee and refund amount to high and low limbs to be able to use BB API. // We use the unsafe version because the multi_scalar_mul will constrain the scalars. let transaction_fee_scalar = from_field_unsafe(transaction_fee); + let refund_scalar = from_field_unsafe(funded_amount - transaction_fee); - // 2. We compute the fee point as `G_amt * transaction_fee` - let fee_point = multi_scalar_mul( - [G_amt], - [transaction_fee_scalar] - ); + // 3. We compute the fee point as `G_amt * transaction_fee` + let fee_point = multi_scalar_mul([G_amt], [transaction_fee_scalar]); - // 3. Now we leverage homomorphism to privately add the fee to fee payer point and subtract it from - // the sponsored user point in public. - let fee_payer_point = incomplete_fee_payer_point + fee_point; - let user_point = incomplete_user_point - fee_point; + // 4. We compute the refund point as `G_amt * refund` + let refund_point = multi_scalar_mul([G_amt], [refund_scalar]); - assert_eq(user_point.is_infinite, false); + // 5. Now we leverage homomorphism to privately add the fee to fee payer point and we add refund to the user point. + let fee_payer_point = incomplete_fee_payer_point + fee_point; + let user_point = incomplete_user_point + refund_point; - // 4. We no longer need to do any elliptic curve operations with the points so we collapse them to the final + // 6. We no longer need to do any elliptic curve operations with the points so we collapse them to the final // note hashes. let fee_payer_note_hash = fee_payer_point.x; let user_note_hash = user_point.x; - // 5. Finally we return the hashes. + // 7. Finally we return the hashes. (fee_payer_note_hash, user_note_hash) } } diff --git a/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts b/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts index 8549dcee1c2..bc667647710 100644 --- a/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts @@ -129,6 +129,31 @@ describe('e2e_fees/private_refunds', () => { [initialAliceBalance - tx.transactionFee!, initialBobBalance + tx.transactionFee!], ); }); + + // TODO(#7694): Remove this test once the lacking feature in TXE is implemented. + it('insufficient funded amount is correctly handled', async () => { + // 1. We generate randomness for Alice and derive randomness for Bob. + const aliceRandomness = Fr.random(); // Called user_randomness in contracts + const bobRandomness = poseidon2Hash([aliceRandomness]); // Called fee_payer_randomness in contracts + + // 2. We call arbitrary `private_get_name(...)` function to check that the fee refund flow works. + await expect( + tokenWithRefunds.methods.private_get_name().prove({ + fee: { + gasSettings: t.gasSettings, + paymentMethod: new PrivateRefundPaymentMethod( + tokenWithRefunds.address, + privateFPC.address, + aliceWallet, + aliceRandomness, + bobRandomness, + t.bobWallet.getAddress(), // Bob is the recipient of the fee notes. + true, // We set max fee/funded amount to zero to trigger the error. + ), + }, + }), + ).rejects.toThrow('tx fee is higher than funded amount'); + }); }); class PrivateRefundPaymentMethod implements FeePaymentMethod { @@ -163,6 +188,12 @@ class PrivateRefundPaymentMethod implements FeePaymentMethod { * Address that the FPC sends notes it receives to. */ private feeRecipient: AztecAddress, + + /** + * If true, the max fee will be set to 0. + * TODO(#7694): Remove this param once the lacking feature in TXE is implemented. + */ + private setMaxFeeToZero = false, ) {} /** @@ -183,8 +214,9 @@ class PrivateRefundPaymentMethod implements FeePaymentMethod { * @returns The function call to pay the fee. */ async getFunctionCalls(gasSettings: GasSettings): Promise { - // we assume 1:1 exchange rate between fee juice and token. But in reality you would need to convert feeLimit (maxFee) to be in token denomination - const maxFee = gasSettings.getFeeLimit(); + // We assume 1:1 exchange rate between fee juice and token. But in reality you would need to convert feeLimit + // (maxFee) to be in token denomination. + const maxFee = this.setMaxFeeToZero ? Fr.ZERO : gasSettings.getFeeLimit(); await this.wallet.createAuthWit({ caller: this.paymentContract, diff --git a/yarn-project/txe/package.json b/yarn-project/txe/package.json index fc21460d926..d01e249591e 100644 --- a/yarn-project/txe/package.json +++ b/yarn-project/txe/package.json @@ -18,7 +18,7 @@ "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests", - "dev": "DEBUG='aztec:*' LOG_LEVEL=debug && node ./dest/bin/index.js", + "dev": "DEBUG='aztec:*' LOG_LEVEL=debug node ./dest/bin/index.js", "start": "node ./dest/bin/index.js" }, "inherits": [ diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 949e181179a..f70dc666f93 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -772,8 +772,12 @@ export class TXE implements TypedOracle { const executionResult = await this.executePublicFunction(targetContractAddress, args, callContext); + if (executionResult.reverted) { + throw new Error(`Execution reverted with reason: ${executionResult.revertReason}`); + } + // Apply side effects - this.sideEffectsCounter = executionResult.endSideEffectCounter.toNumber(); + this.sideEffectsCounter += executionResult.endSideEffectCounter.toNumber(); this.setContractAddress(currentContractAddress); this.setMsgSender(currentMessageSender); this.setFunctionSelector(currentFunctionSelector); @@ -808,6 +812,10 @@ export class TXE implements TypedOracle { const executionResult = await this.executePublicFunction(targetContractAddress, args, callContext); + if (executionResult.reverted) { + throw new Error(`Execution reverted with reason: ${executionResult.revertReason}`); + } + // Apply side effects this.sideEffectsCounter += executionResult.endSideEffectCounter.toNumber(); this.setContractAddress(currentContractAddress); From f8a76c1a65c7c25f49bf2d7b4ef5302a0d0fbd58 Mon Sep 17 00:00:00 2001 From: ledwards2225 <98505400+ledwards2225@users.noreply.github.com> Date: Thu, 1 Aug 2024 11:07:18 +0400 Subject: [PATCH 33/35] feat: New IVC class that better reflects the aztec architecture (#7695) Implement new class `AztecIvc` that resembles `ClientIvc` but better reflects what is needed for the actual aztec architecture. Rather than appending a recursive folding verifier to each circuit being accumulated, none are appended to apps and two are appended to kernels. This PR does not remove/disable/replace ClientIvc anywhere. (Admittedly this is a bit quick-n-dirty because I need it in order to make progress on the databus but the tests are thorough). --- barretenberg/cpp/src/CMakeLists.txt | 1 + .../src/barretenberg/aztec_ivc/CMakeLists.txt | 1 + .../src/barretenberg/aztec_ivc/aztec_ivc.cpp | 165 +++++++++++ .../src/barretenberg/aztec_ivc/aztec_ivc.hpp | 105 +++++++ .../barretenberg/aztec_ivc/aztec_ivc.test.cpp | 274 ++++++++++++++++++ .../barretenberg/client_ivc/client_ivc.cpp | 4 +- .../barretenberg/client_ivc/client_ivc.hpp | 48 +-- .../max_block_size_tracker.hpp | 45 +++ .../arithmetization/mega_arithmetization.hpp | 6 +- 9 files changed, 601 insertions(+), 48 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/aztec_ivc/CMakeLists.txt create mode 100644 barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp create mode 100644 barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp create mode 100644 barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/max_block_size_tracker.hpp diff --git a/barretenberg/cpp/src/CMakeLists.txt b/barretenberg/cpp/src/CMakeLists.txt index 3c1dee8a29a..5356710d721 100644 --- a/barretenberg/cpp/src/CMakeLists.txt +++ b/barretenberg/cpp/src/CMakeLists.txt @@ -52,6 +52,7 @@ else() message(STATUS "Using optimized assembly for field arithmetic.") endif() +add_subdirectory(barretenberg/aztec_ivc) add_subdirectory(barretenberg/bb) add_subdirectory(barretenberg/circuit_checker) add_subdirectory(barretenberg/client_ivc) diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/aztec_ivc/CMakeLists.txt new file mode 100644 index 00000000000..a4cbce17a68 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/CMakeLists.txt @@ -0,0 +1 @@ +barretenberg_module(aztec_ivc goblin) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp new file mode 100644 index 00000000000..e08a1e757ef --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.cpp @@ -0,0 +1,165 @@ +#include "barretenberg/aztec_ivc/aztec_ivc.hpp" + +namespace bb { + +/** + * @brief Accumulate a circuit into the IVC scheme + * @details If this is the first circuit being accumulated, initialize the prover and verifier accumulators. Otherwise, + * fold the instance for the provided circuit into the accumulator. When two fold proofs have been enqueued, two + * recursive folding verifications are appended to the next circuit that is accumulated, which must be a kernel. + * Similarly, if a merge proof exists, a recursive merge verifier is appended. + * + * @param circuit Circuit to be accumulated/folded + * @param precomputed_vk Optional precomputed VK (otherwise will be computed herein) + */ +void AztecIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr& precomputed_vk) +{ + circuit_count++; // increment the count of circuits processed into the IVC + + // When there are two fold proofs present, append two recursive verifiers to the kernel + if (verification_queue.size() == 2) { + BB_OP_COUNT_TIME_NAME("construct_circuits"); + ASSERT(circuit_count % 2 == 0); // ensure this is a kernel + + for (auto& [proof, vkey] : verification_queue) { + FoldingRecursiveVerifier verifier{ &circuit, { verifier_accumulator, { vkey } } }; + auto verifier_accum = verifier.verify_folding_proof(proof); + verifier_accumulator = std::make_shared(verifier_accum->get_value()); + info("Num gates = ", circuit.get_num_gates()); + } + verification_queue.clear(); + } + + // Construct a merge proof (and add a recursive merge verifier to the circuit if a previous merge proof exists) + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1063): update recursive merge verification to only + // occur in kernels, similar to folding recursive verification. + goblin.merge(circuit); + + // Construct the prover instance for circuit + auto prover_instance = std::make_shared(circuit, trace_structure); + + // Set the instance verification key from precomputed if available, else compute it + if (precomputed_vk) { + instance_vk = precomputed_vk; + } else { + instance_vk = std::make_shared(prover_instance->proving_key); + } + + // If this is the first circuit simply initialize the prover and verifier accumulator instances + if (circuit_count == 1) { + fold_output.accumulator = prover_instance; + verifier_accumulator = std::make_shared(instance_vk); + } else { // Otherwise, fold the new instance into the accumulator + FoldingProver folding_prover({ fold_output.accumulator, prover_instance }); + fold_output = folding_prover.fold_instances(); + + // Add fold proof and corresponding verification key to the verification queue + verification_queue.emplace_back(fold_output.proof, instance_vk); + } + + // Track the maximum size of each block for all circuits porcessed (for debugging purposes only) + max_block_size_tracker.update(circuit); +} + +/** + * @brief Construct a proof for the IVC, which, if verified, fully establishes its correctness + * + * @return Proof + */ +AztecIVC::Proof AztecIVC::prove() +{ + max_block_size_tracker.print(); // print minimum structured sizes for each block + ASSERT(verification_queue.size() == 1); // ensure only a single fold proof remains in the queue + auto& fold_proof = verification_queue[0].proof; + return { fold_proof, decider_prove(), goblin.prove() }; +}; + +bool AztecIVC::verify(const Proof& proof, + const std::shared_ptr& accumulator, + const std::shared_ptr& final_verifier_instance, + const std::shared_ptr& eccvm_vk, + const std::shared_ptr& translator_vk) +{ + // Goblin verification (merge, eccvm, translator) + GoblinVerifier goblin_verifier{ eccvm_vk, translator_vk }; + bool goblin_verified = goblin_verifier.verify(proof.goblin_proof); + + // Decider verification + AztecIVC::FoldingVerifier folding_verifier({ accumulator, final_verifier_instance }); + auto verifier_accumulator = folding_verifier.verify_folding_proof(proof.folding_proof); + + AztecIVC::DeciderVerifier decider_verifier(verifier_accumulator); + bool decision = decider_verifier.verify_proof(proof.decider_proof); + return goblin_verified && decision; +} + +/** + * @brief Verify a full proof of the IVC + * + * @param proof + * @return bool + */ +bool AztecIVC::verify(Proof& proof, const std::vector>& verifier_instances) +{ + auto eccvm_vk = std::make_shared(goblin.get_eccvm_proving_key()); + auto translator_vk = std::make_shared(goblin.get_translator_proving_key()); + return verify(proof, verifier_instances[0], verifier_instances[1], eccvm_vk, translator_vk); +} + +/** + * @brief Internal method for constructing a decider proof + * + * @return HonkProof + */ +HonkProof AztecIVC::decider_prove() const +{ + MegaDeciderProver decider_prover(fold_output.accumulator); + return decider_prover.construct_proof(); +} + +/** + * @brief Given a set of circuits, compute the verification keys that will be required by the IVC scheme + * @details The verification keys computed here are in general not the same as the verification keys for the + * raw input circuits because recursive verifier circuits (merge and/or folding) may be appended to the incoming + * circuits as part accumulation. + * @note This method exists for convenience and is not not meant to be used in practice for IVC. Given a set of + * circuits, it could be run once and for all to compute then save the required VKs. It also provides a convenient + * (albeit innefficient) way of separating out the cost of computing VKs from a benchmark. + * + * @param circuits A copy of the circuits to be accumulated (passing by reference would alter the original circuits) + * @return std::vector> + */ +std::vector> AztecIVC::precompute_folding_verification_keys( + std::vector circuits) +{ + std::vector> vkeys; + + for (auto& circuit : circuits) { + accumulate(circuit); + vkeys.emplace_back(instance_vk); + } + + // Reset the scheme so it can be reused for actual accumulation, maintaining the trace structure setting as is + TraceStructure structure = trace_structure; + *this = AztecIVC(); + this->trace_structure = structure; + + return vkeys; +} + +/** + * @brief Construct and verify a proof for the IVC + * @note Use of this method only makes sense when the prover and verifier are the same entity, e.g. in + * development/testing. + * + */ +bool AztecIVC::prove_and_verify() +{ + auto proof = prove(); + + ASSERT(verification_queue.size() == 1); // ensure only a single fold proof remains in the queue + auto verifier_inst = std::make_shared(this->verification_queue[0].instance_vk); + return verify(proof, { this->verifier_accumulator, verifier_inst }); +} + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp new file mode 100644 index 00000000000..c0d1a92c28d --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.hpp @@ -0,0 +1,105 @@ +#pragma once + +#include "barretenberg/goblin/goblin.hpp" +#include "barretenberg/goblin/mock_circuits.hpp" +#include "barretenberg/plonk_honk_shared/arithmetization/max_block_size_tracker.hpp" +#include "barretenberg/protogalaxy/decider_verifier.hpp" +#include "barretenberg/protogalaxy/protogalaxy_prover.hpp" +#include "barretenberg/protogalaxy/protogalaxy_verifier.hpp" +#include "barretenberg/sumcheck/instance/instances.hpp" +#include "barretenberg/ultra_honk/decider_prover.hpp" +#include + +namespace bb { + +/** + * @brief The IVC scheme used by the aztec client for private function execution + * @details Combines Protogalaxy with Goblin to accumulate one circuit instance at a time with efficient EC group + * operations. It is assumed that the circuits being accumulated correspond alternatingly to an app and a kernel, as is + * the case in Aztec. Two recursive folding verifiers are appended to each kernel (except the first one) to verify the + * folding of a previous kernel and an app/function circuit. Due to this structure it is enforced that the total number + * of circuits being accumulated is even. + * + */ +class AztecIVC { + + public: + using Flavor = MegaFlavor; + using VerificationKey = Flavor::VerificationKey; + using FF = Flavor::FF; + using FoldProof = std::vector; + using ProverInstance = ProverInstance_; + using VerifierInstance = VerifierInstance_; + using ClientCircuit = MegaCircuitBuilder; // can only be Mega + using DeciderProver = DeciderProver_; + using DeciderVerifier = DeciderVerifier_; + using ProverInstances = ProverInstances_; + using FoldingProver = ProtoGalaxyProver_; + using VerifierInstances = VerifierInstances_; + using FoldingVerifier = ProtoGalaxyVerifier_; + using ECCVMVerificationKey = bb::ECCVMFlavor::VerificationKey; + using TranslatorVerificationKey = bb::TranslatorFlavor::VerificationKey; + + using GURecursiveFlavor = MegaRecursiveFlavor_; + using RecursiveVerifierInstances = bb::stdlib::recursion::honk::RecursiveVerifierInstances_; + using FoldingRecursiveVerifier = + bb::stdlib::recursion::honk::ProtoGalaxyRecursiveVerifier_; + + // A full proof for the IVC scheme + struct Proof { + FoldProof folding_proof; // final fold proof + HonkProof decider_proof; + GoblinProof goblin_proof; + + size_t size() const { return folding_proof.size() + decider_proof.size() + goblin_proof.size(); } + + MSGPACK_FIELDS(folding_proof, decider_proof, goblin_proof); + }; + + struct FoldingVerifierInputs { + FoldProof proof; + std::shared_ptr instance_vk; + }; + + // Utility for tracking the max size of each block across the full IVC + MaxBlockSizeTracker max_block_size_tracker; + + private: + using ProverFoldOutput = FoldingResult; + + public: + GoblinProver goblin; + + ProverFoldOutput fold_output; // prover accumulator instance and fold proof + + std::shared_ptr verifier_accumulator; // verifier accumulator instance + std::shared_ptr instance_vk; // verification key for instance to be folded + + // Set of pairs of {fold_proof, verification_key} to be recursively verified + std::vector verification_queue; + + // A flag indicating whether or not to construct a structured trace in the ProverInstance + TraceStructure trace_structure = TraceStructure::NONE; + + // The number of circuits processed into the IVC + size_t circuit_count = 0; + + void accumulate(ClientCircuit& circuit, const std::shared_ptr& precomputed_vk = nullptr); + + Proof prove(); + + static bool verify(const Proof& proof, + const std::shared_ptr& accumulator, + const std::shared_ptr& final_verifier_instance, + const std::shared_ptr& eccvm_vk, + const std::shared_ptr& translator_vk); + + bool verify(Proof& proof, const std::vector>& verifier_instances); + + bool prove_and_verify(); + + HonkProof decider_prove() const; + + std::vector> precompute_folding_verification_keys(std::vector); +}; +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.test.cpp new file mode 100644 index 00000000000..71291981d94 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/aztec_ivc/aztec_ivc.test.cpp @@ -0,0 +1,274 @@ +#include "barretenberg/aztec_ivc/aztec_ivc.hpp" +#include "barretenberg/goblin/goblin.hpp" +#include "barretenberg/goblin/mock_circuits.hpp" +#include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" + +#include + +using namespace bb; + +class AztecIVCTests : public ::testing::Test { + protected: + static void SetUpTestSuite() + { + srs::init_crs_factory("../srs_db/ignition"); + srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); + } + + using Flavor = AztecIVC::Flavor; + using FF = typename Flavor::FF; + using VerificationKey = Flavor::VerificationKey; + using Builder = AztecIVC::ClientCircuit; + using ProverInstance = AztecIVC::ProverInstance; + using VerifierInstance = AztecIVC::VerifierInstance; + using FoldProof = AztecIVC::FoldProof; + using DeciderProver = AztecIVC::DeciderProver; + using DeciderVerifier = AztecIVC::DeciderVerifier; + using ProverInstances = ProverInstances_; + using FoldingProver = ProtoGalaxyProver_; + using VerifierInstances = VerifierInstances_; + using FoldingVerifier = ProtoGalaxyVerifier_; + + /** + * @brief Construct mock circuit with arithmetic gates and goblin ops + * @details Currently default sized to 2^16 to match kernel. (Note: dummy op gates added to avoid non-zero + * polynomials will bump size to next power of 2) + * + */ + static Builder create_mock_circuit(AztecIVC& ivc, size_t log2_num_gates = 16) + { + Builder circuit{ ivc.goblin.op_queue }; + MockCircuits::construct_arithmetic_circuit(circuit, log2_num_gates); + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/911): We require goblin ops to be added to the + // function circuit because we cannot support zero commtiments. While the builder handles this at + // finalisation stage via the add_gates_to_ensure_all_polys_are_non_zero function for other MegaHonk + // circuits (where we don't explicitly need to add goblin ops), in AztecIVC merge proving happens prior to + // folding where the absense of goblin ecc ops will result in zero commitments. + MockCircuits::construct_goblin_ecc_op_circuit(circuit); + return circuit; + } + + /** + * @brief Tamper with a proof by finding the first non-zero value and incrementing it by 1 + * + */ + static void tamper_with_proof(FoldProof& proof) + { + for (auto& val : proof) { + if (val > 0) { + val += 1; + break; + } + } + } +}; + +/** + * @brief A simple-as-possible test demonstrating IVC for two mock circuits + * @details When accumulating only two circuits, only a single round of folding is performed thus no recursive + * verfication occurs. + * + */ +TEST_F(AztecIVCTests, Basic) +{ + AztecIVC ivc; + + // Initialize the IVC with an arbitrary circuit + Builder circuit_0 = create_mock_circuit(ivc); + ivc.accumulate(circuit_0); + + // Create another circuit and accumulate + Builder circuit_1 = create_mock_circuit(ivc); + ivc.accumulate(circuit_1); + + EXPECT_TRUE(ivc.prove_and_verify()); +}; + +/** + * @brief Check that the IVC fails to verify if an intermediate fold proof is invalid + * @details When accumulating 4 circuits, there are 3 fold proofs to verify (the first two are recursively verfied and + * the 3rd is verified as part of the IVC proof). Check that if any of one of these proofs is invalid, the IVC will fail + * to verify. + * + */ +TEST_F(AztecIVCTests, BadProofFailure) +{ + // Confirm that the IVC verifies if nothing is tampered with + { + AztecIVC ivc; + ivc.trace_structure = TraceStructure::SMALL_TEST; + + // Construct a set of arbitrary circuits + size_t NUM_CIRCUITS = 4; + for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { + auto circuit = create_mock_circuit(ivc, /*log2_num_gates=*/5); + ivc.accumulate(circuit); + } + EXPECT_TRUE(ivc.prove_and_verify()); + } + + // The IVC fails to verify if the FIRST fold proof is tampered with + { + AztecIVC ivc; + ivc.trace_structure = TraceStructure::SMALL_TEST; + + // Construct a set of arbitrary circuits + size_t NUM_CIRCUITS = 4; + for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { + auto circuit = create_mock_circuit(ivc, /*log2_num_gates=*/5); + ivc.accumulate(circuit); + + if (idx == 2) { + EXPECT_EQ(ivc.verification_queue.size(), 2); // two proofs after 3 calls to accumulation + tamper_with_proof(ivc.verification_queue[0].proof); // tamper with first proof + } + } + + EXPECT_FALSE(ivc.prove_and_verify()); + } + + // The IVC fails to verify if the SECOND fold proof is tampered with + { + AztecIVC ivc; + ivc.trace_structure = TraceStructure::SMALL_TEST; + + // Construct a set of arbitrary circuits + size_t NUM_CIRCUITS = 4; + for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { + auto circuit = create_mock_circuit(ivc, /*log2_num_gates=*/5); + ivc.accumulate(circuit); + + if (idx == 2) { + EXPECT_EQ(ivc.verification_queue.size(), 2); // two proofs after 3 calls to accumulation + tamper_with_proof(ivc.verification_queue[1].proof); // tamper with second proof + } + } + + EXPECT_FALSE(ivc.prove_and_verify()); + } + + // The IVC fails to verify if the 3rd/FINAL fold proof is tampered with + { + AztecIVC ivc; + ivc.trace_structure = TraceStructure::SMALL_TEST; + + // Construct a set of arbitrary circuits + size_t NUM_CIRCUITS = 4; + for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { + auto circuit = create_mock_circuit(ivc, /*log2_num_gates=*/5); + ivc.accumulate(circuit); + } + + // Only a single proof should be present in the queue when verification of the IVC is performed + EXPECT_EQ(ivc.verification_queue.size(), 1); + tamper_with_proof(ivc.verification_queue[0].proof); // tamper with the final fold proof + + EXPECT_FALSE(ivc.prove_and_verify()); + } + + EXPECT_TRUE(true); +}; + +/** + * @brief Prove and verify accumulation of an arbitrary set of circuits + * + */ +TEST_F(AztecIVCTests, BasicLarge) +{ + AztecIVC ivc; + + // Construct a set of arbitrary circuits + size_t NUM_CIRCUITS = 6; + std::vector circuits; + for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { + circuits.emplace_back(create_mock_circuit(ivc)); + } + + // Accumulate each circuit + for (auto& circuit : circuits) { + ivc.accumulate(circuit); + } + + info(ivc.goblin.op_queue->get_current_size()); + + EXPECT_TRUE(ivc.prove_and_verify()); +}; + +/** + * @brief Using a structured trace allows for the accumulation of circuits of varying size + * + */ +TEST_F(AztecIVCTests, BasicStructured) +{ + AztecIVC ivc; + ivc.trace_structure = TraceStructure::SMALL_TEST; + + // Construct some circuits of varying size + Builder circuit_0 = create_mock_circuit(ivc, /*log2_num_gates=*/5); + Builder circuit_1 = create_mock_circuit(ivc, /*log2_num_gates=*/6); + Builder circuit_2 = create_mock_circuit(ivc, /*log2_num_gates=*/7); + Builder circuit_3 = create_mock_circuit(ivc, /*log2_num_gates=*/8); + + // The circuits can be accumulated as normal due to the structured trace + ivc.accumulate(circuit_0); + ivc.accumulate(circuit_1); + ivc.accumulate(circuit_2); + ivc.accumulate(circuit_3); + + EXPECT_TRUE(ivc.prove_and_verify()); +}; + +/** + * @brief Prove and verify accumulation of an arbitrary set of circuits using precomputed verification keys + * + */ +TEST_F(AztecIVCTests, PrecomputedVerificationKeys) +{ + AztecIVC ivc; + + // Construct a set of arbitrary circuits + size_t NUM_CIRCUITS = 4; + std::vector circuits; + for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { + circuits.emplace_back(create_mock_circuit(ivc)); + } + + // Precompute the verification keys that will be needed for the IVC + auto precomputed_vkeys = ivc.precompute_folding_verification_keys(circuits); + + // Accumulate each circuit using the precomputed VKs + for (auto [circuit, precomputed_vk] : zip_view(circuits, precomputed_vkeys)) { + ivc.accumulate(circuit, precomputed_vk); + } + + EXPECT_TRUE(ivc.prove_and_verify()); +}; + +/** + * @brief Perform accumulation with a structured trace and precomputed verification keys + * + */ +TEST_F(AztecIVCTests, StructuredPrecomputedVKs) +{ + AztecIVC ivc; + ivc.trace_structure = TraceStructure::SMALL_TEST; + + // Construct a set of arbitrary circuits + size_t NUM_CIRCUITS = 4; + std::vector circuits; + for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { + circuits.emplace_back(create_mock_circuit(ivc, /*log2_num_gates=*/5)); + } + + // Precompute the (structured) verification keys that will be needed for the IVC + auto precomputed_vkeys = ivc.precompute_folding_verification_keys(circuits); + + // Accumulate each circuit + for (auto [circuit, precomputed_vk] : zip_view(circuits, precomputed_vkeys)) { + ivc.accumulate(circuit, precomputed_vk); + } + + EXPECT_TRUE(ivc.prove_and_verify()); +}; diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 3dedf183a31..ae8ca804cd4 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -29,7 +29,7 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr(circuit, trace_structure); // Track the maximum size of each block for all circuits porcessed (for debugging purposes only) - max_block_sizes.update(circuit); + max_block_size_tracker.update(circuit); // Set the instance verification key from precomputed if available, else compute it if (precomputed_vk) { @@ -56,7 +56,7 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr; @@ -134,7 +94,5 @@ class ClientIVC { HonkProof decider_prove() const; std::vector> precompute_folding_verification_keys(std::vector); - - MaxBlockSizes max_block_sizes; // for tracking minimum block size requirements across an IVC }; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/max_block_size_tracker.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/max_block_size_tracker.hpp new file mode 100644 index 00000000000..b9d1f64f721 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/max_block_size_tracker.hpp @@ -0,0 +1,45 @@ +#include "barretenberg/plonk_honk_shared/arithmetization/mega_arithmetization.hpp" +#include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" + +namespace bb { + +/** + * @brief A debugging utility for tracking the max size of each block over all circuits in the IVC + * + */ +struct MaxBlockSizeTracker { + using Builder = MegaCircuitBuilder; + using MegaTraceBlocks = MegaArithmetization::MegaTraceBlocks; + MegaTraceBlocks max_sizes; + + MaxBlockSizeTracker() + { + for (auto& size : max_sizes.get()) { + size = 0; // init max sizes to zero + } + } + + // Update the max block sizes based on the block sizes of a provided circuit + void update(Builder& circuit) + { + for (auto [block, max_size] : zip_view(circuit.blocks.get(), max_sizes.get())) { + max_size = std::max(block.size(), max_size); + } + } + + // For printing only. Must match the order of the members in the arithmetization + std::vector block_labels{ "ecc_op", "pub_inputs", "arithmetic", + "delta_range", "elliptic", "aux", + "lookup", "busread", "poseidon_external", + "poseidon_internal" }; + + void print() + { + info("Minimum required block sizes for structured trace: "); + for (auto [label, max_size] : zip_view(block_labels, max_sizes.get())) { + std::cout << std::left << std::setw(20) << (label + ":") << max_size << std::endl; + } + info(""); + } +}; +} // namespace bb \ No newline at end of file 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 6ee5f10f25c..ef5eaad163a 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 @@ -11,6 +11,7 @@ namespace bb { */ template class MegaArith { + public: /** * @brief Defines the circuit block types for the Mega arithmetization * @note Its useful to define this as a template since it is used to actually store gate data (T = MegaTraceBlock) @@ -40,6 +41,7 @@ template class MegaArith { bool operator==(const MegaTraceBlocks& other) const = default; }; + private: // An arbitrary but small-ish structuring that can be used for generic unit testing with non-trivial circuits struct SmallTestStructuredBlockSizes : public MegaTraceBlocks { SmallTestStructuredBlockSizes() @@ -47,7 +49,7 @@ template class MegaArith { const uint32_t FIXED_SIZE = 1 << 14; this->ecc_op = FIXED_SIZE; this->pub_inputs = FIXED_SIZE; - this->arithmetic = FIXED_SIZE; + this->arithmetic = 1 << 15; this->delta_range = FIXED_SIZE; this->elliptic = FIXED_SIZE; this->aux = FIXED_SIZE; @@ -235,6 +237,8 @@ template class MegaArith { inline static const std::vector selector_names = {}; }; +using MegaArithmetization = MegaArith; + template concept HasAdditionalSelectors = IsAnyOf>; } // namespace bb \ No newline at end of file From 2631fb5ce0d99dcba40a44b61d4feb61cd4d0922 Mon Sep 17 00:00:00 2001 From: ludamad Date: Thu, 1 Aug 2024 16:12:54 +0400 Subject: [PATCH 34/35] chore(ci): report memory usage in bb-native-tests (#7713) It was hard to see why Mara's PR took down memory, should make it more clear. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85b0786b0ed..6325dc1f33a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -294,7 +294,7 @@ jobs: working-directory: ./barretenberg/cpp/ timeout-minutes: 40 # limit our parallelism to half our cores - run: earthly-ci --no-output +test --hardware_concurrency=64 + run: earthly-ci --exec-stats --no-output +test --hardware_concurrency=64 bb-js-test: needs: [build-images, changes] From 76ef29825e9e3ef470b8801e5627c26d952644eb Mon Sep 17 00:00:00 2001 From: Leila Wang Date: Thu, 1 Aug 2024 13:20:12 +0100 Subject: [PATCH 35/35] fix: skip squashing of revertible nullifier and non-revertible note hash (#7624) #5212 When a revertible nullifier is nullifying a non-revertible note hash in a tx that contains public functions, they can't be squashed. Because if the tx reverts, we will have to keep the note hash, and discard the nullifier. ### Reset Circuit It takes a `split_counter` from the private inputs, and uses this counter to check that the revertible nullifiers being squashed do not link to non-revertible note hashes. It's provided from the private inputs instead of being fetched from the previous kernel's public inputs because a reset circuit can be run before processing the call that sets the `min_revertible_side_effect_counter` to the public inputs. The `split_counter` will be propagated to the `validation_requests` in the public inputs. This value must be the same as the one in the previous kernel, if it's already set in an earlier reset circuit. ### Private Tail(_to_Public) Circuit It checks that each nullifier either has zero note hash, or is linked to a note hash that has a smaller counter and the exact siloed note hash. Making sure that no transient data remains in the final public inputs. The `split_counter` in the `validation_requests` is verified: - In `tail_to_public`, it must match the `min_revertible_side_effect_counter`. - In `tail`, it must be zero to allow all the transient pairs to be squashed. ### PXE PXE will assign nonces to all the pending note hashes when the `end_setup` is called and `min_revertible_side_effect_counter` is set. At this point, we know that all the pending note hashes that haven't been squashed can't be squashed anymore, because the nullifiers emitted afterwards will be revertible and won't be able to squash non-revertible note hashes. So we can compute their nonces with the correct indexes. Those notes will be returned to the `getNotes` oracle call with non-zero nonces. Utils in aztec.nr will compute the siloed note hash as the `note_hash_for_consumption`, emitted it along with the nullifier. Currently only the non-revertible note hashes have non-zero nonces so they can't be squashed. But if needs to, an oracle can assign nonces to all the pending note hashes, keeping all of them from being squashed, to have a complete record of everything happening in a tx. --- .../src/core/libraries/ConstantsGen.sol | 7 +- noir-projects/aztec-nr/authwit/src/auth.nr | 2 +- .../aztec/src/context/private_context.nr | 16 +- .../aztec/src/context/public_context.nr | 6 +- .../aztec-nr/aztec/src/initializer.nr | 4 +- .../aztec-nr/aztec/src/note/lifecycle.nr | 12 +- .../aztec-nr/aztec/src/note/utils.nr | 33 +++- .../oracle/enqueue_public_function_call.nr | 6 + .../aztec-nr/aztec/src/oracle/mod.nr | 1 - .../aztec-nr/aztec/src/oracle/public_call.nr | 28 --- .../aztec/src/state_vars/private_immutable.nr | 2 +- .../aztec/src/state_vars/private_mutable.nr | 2 +- .../contracts/avm_test_contract/src/main.nr | 12 +- .../contracts/claim_contract/src/main.nr | 2 +- .../src/main.nr | 2 +- .../src/main.nr | 2 +- .../easy_private_voting_contract/src/main.nr | 2 +- .../inclusion_proofs_contract/src/main.nr | 2 +- .../private_fpc_contract/src/main.nr | 2 +- .../contracts/test_contract/src/main.nr | 4 +- .../contracts/token_contract/src/main.nr | 2 +- .../token_with_refunds_contract/src/main.nr | 2 +- .../components/previous_kernel_validator.nr | 58 ++++-- .../previous_kernel_validator_hints.nr | 32 ++++ ...private_kernel_circuit_output_validator.nr | 4 + ...e_kernel_circuit_public_inputs_composer.nr | 1 + .../src/components/tail_output_validator.nr | 79 ++++---- ...t_output_hints.nr => tail_output_hints.nr} | 17 +- .../tail_to_public_output_composer.nr | 11 +- .../split_to_public.nr | 2 - .../tail_to_public_output_validator.nr | 46 +++-- .../tail_to_public_output_hints.nr | 9 - .../src/private_kernel_reset.nr | 20 +- .../src/private_kernel_tail.nr | 16 +- .../src/private_kernel_tail_to_public.nr | 19 +- .../mod.nr} | 2 + .../validate_no_transient_data.nr | 71 ++++++++ ...alidate_propagated_from_previous_kernel.nr | 34 ++++ .../tail_output_validator_builder/mod.nr | 42 ++++- ...alidate_propagated_sorted_siloed_values.nr | 19 +- .../split_to_public.nr | 12 -- ...tail_to_public_output_validator_builder.nr | 8 +- .../private_validation_request_processor.nr | 23 ++- .../public_validation_request_processor.nr | 4 +- .../src/reset/transient_data.nr | 55 +++++- .../private_kernel_circuit_public_inputs.nr | 8 +- ...te_kernel_circuit_public_inputs_builder.nr | 7 +- .../public_kernel_circuit_public_inputs.nr | 8 +- ...ic_kernel_circuit_public_inputs_builder.nr | 6 +- .../mod.nr} | 16 +- ...ests.nr => private_validation_requests.nr} | 53 ++---- ...=> private_validation_requests_builder.nr} | 33 ++-- .../public_validation_requests.nr | 86 +++++++++ .../public_validation_requests_builder.nr | 47 +++++ .../crates/types/src/constants.nr | 7 +- .../crates/types/src/tests/fixture_builder.nr | 49 +++-- yarn-project/circuits.js/src/constants.gen.ts | 7 +- .../hints/build_transient_data_hints.test.ts | 54 ++++-- .../src/hints/build_transient_data_hints.ts | 13 +- yarn-project/circuits.js/src/structs/index.ts | 4 +- .../private_kernel_circuit_public_inputs.ts | 8 +- ...ate_kernel_reset_circuit_private_inputs.ts | 8 + ...ivate_kernel_tail_circuit_public_inputs.ts | 8 +- .../public_kernel_circuit_public_inputs.ts | 10 +- .../src/structs/optional_number.ts | 50 +++++ ...ests.ts => private_validation_requests.ts} | 55 ++---- .../src/structs/public_validation_requests.ts | 126 +++++++++++++ .../circuits.js/src/tests/factories.ts | 26 +-- .../src/type_conversion.ts | 76 ++++++-- .../build_private_kernel_reset_hints.ts | 2 + .../pxe/src/kernel_prover/hints/index.ts | 2 + .../src/kernel_prover/hints/needs_reset.ts | 51 ++++++ .../src/kernel_prover/kernel_prover.test.ts | 2 +- .../pxe/src/kernel_prover/kernel_prover.ts | 68 ++----- .../private_inputs_builders/index.ts | 1 - .../simulator/src/acvm/oracle/oracle.ts | 23 +-- .../simulator/src/acvm/oracle/typed_oracle.ts | 15 +- .../src/client/client_execution_context.ts | 12 +- .../src/client/execution_note_cache.ts | 87 +++++++-- .../src/client/execution_result.test.ts | 172 ++++++++++-------- .../simulator/src/client/execution_result.ts | 38 +++- .../simulator/src/client/private_execution.ts | 4 +- .../simulator/src/client/simulator.ts | 5 +- yarn-project/txe/src/oracle/txe_oracle.ts | 90 ++++----- .../txe/src/txe_service/txe_service.ts | 7 +- 85 files changed, 1411 insertions(+), 668 deletions(-) delete mode 100644 noir-projects/aztec-nr/aztec/src/oracle/public_call.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator/previous_kernel_validator_hints.nr rename noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/{kernel_circuit_output_hints.nr => tail_output_hints.nr} (87%) rename noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/{previous_kernel_validator_builder.nr => previous_kernel_validator_builder/mod.nr} (95%) create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/previous_kernel_validator_builder/validate_no_transient_data.nr rename noir-projects/noir-protocol-circuits/crates/types/src/abis/{validation_requests.nr => validation_requests/mod.nr} (50%) rename noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/{validation_requests.nr => private_validation_requests.nr} (56%) rename noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/{validation_requests_builder.nr => private_validation_requests_builder.nr} (53%) create mode 100644 noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/public_validation_requests.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/public_validation_requests_builder.nr create mode 100644 yarn-project/circuits.js/src/structs/optional_number.ts rename yarn-project/circuits.js/src/structs/{validation_requests.ts => private_validation_requests.ts} (71%) create mode 100644 yarn-project/circuits.js/src/structs/public_validation_requests.ts rename yarn-project/pxe/src/kernel_prover/{private_inputs_builders => hints}/build_private_kernel_reset_hints.ts (98%) create mode 100644 yarn-project/pxe/src/kernel_prover/hints/index.ts create mode 100644 yarn-project/pxe/src/kernel_prover/hints/needs_reset.ts delete mode 100644 yarn-project/pxe/src/kernel_prover/private_inputs_builders/index.ts diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index c4ee79505fa..6011e290933 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -181,14 +181,15 @@ library Constants { uint256 internal constant AGGREGATION_OBJECT_LENGTH = 16; uint256 internal constant SCOPED_READ_REQUEST_LEN = 3; uint256 internal constant PUBLIC_DATA_READ_LENGTH = 2; - uint256 internal constant VALIDATION_REQUESTS_LENGTH = 1090; + uint256 internal constant PRIVATE_VALIDATION_REQUESTS_LENGTH = 772; + uint256 internal constant PUBLIC_VALIDATION_REQUESTS_LENGTH = 514; uint256 internal constant PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = 364; uint256 internal constant COMBINED_CONSTANT_DATA_LENGTH = 41; uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = 1336; - uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2483; + uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2165; uint256 internal constant PUBLIC_ACCUMULATED_DATA_LENGTH = 1215; - uint256 internal constant PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 4011; + uint256 internal constant PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 3435; uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 415; uint256 internal constant CONSTANT_ROLLUP_DATA_LENGTH = 11; uint256 internal constant BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 28; diff --git a/noir-projects/aztec-nr/authwit/src/auth.nr b/noir-projects/aztec-nr/authwit/src/auth.nr index c7220bb10bd..b6343f2c94e 100644 --- a/noir-projects/aztec-nr/authwit/src/auth.nr +++ b/noir-projects/aztec-nr/authwit/src/auth.nr @@ -226,7 +226,7 @@ pub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_o // Compute the nullifier, similar computation to the outer hash, but without the chain_id and version. // Those should already be handled in the verification, so we just need something to nullify, that allow same inner_hash for multiple actors. let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash); - context.push_nullifier(nullifier, 0); + context.push_nullifier(nullifier); } /** 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 4ea1d70fcec..30ff19883d2 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -6,7 +6,10 @@ use crate::{ key_validation_request::get_key_validation_request, arguments, returns::pack_returns, call_private_function::call_private_function_internal, header::get_header_at, logs::{emit_encrypted_note_log, emit_encrypted_event_log}, - enqueue_public_function_call::{enqueue_public_function_call_internal, set_public_teardown_function_call_internal} + enqueue_public_function_call::{ + enqueue_public_function_call_internal, notify_set_min_revertible_side_effect_counter, + set_public_teardown_function_call_internal +} } }; use dep::protocol_types::{ @@ -125,9 +128,11 @@ impl PrivateContext { self.note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() }); } - // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo - // - consider creating a separate function with 1 arg for the zero note hash case. - fn push_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) { + fn push_nullifier(&mut self, nullifier: Field) { + self.nullifiers.push(Nullifier { value: nullifier, note_hash: 0, counter: self.next_counter() }); + } + + fn push_nullifier_for_note_hash(&mut self, nullifier: Field, nullified_note_hash: Field) { self.nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() }); } @@ -186,6 +191,7 @@ impl PrivateContext { // [self.side_effect_counter as Field] // ); self.min_revertible_side_effect_counter = self.side_effect_counter; + notify_set_min_revertible_side_effect_counter(self.min_revertible_side_effect_counter); } // docs:start:max-block-number @@ -254,7 +260,7 @@ impl PrivateContext { ); // Push nullifier (and the "commitment" corresponding to this can be "empty") - self.push_nullifier(nullifier, 0) + self.push_nullifier(nullifier) } // docs:end:consume_l1_to_l2_message 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 32afffb88ae..e53749bb3a8 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -56,8 +56,7 @@ impl PublicContext { self.l1_to_l2_msg_exists(message_hash, leaf_index), "Tried to consume nonexistent L1-to-L2 message" ); - // Push nullifier (and the "commitment" corresponding to this can be "empty") - self.push_nullifier(nullifier, 0); + self.push_nullifier(nullifier); } fn message_portal(_self: &mut Self, recipient: EthAddress, content: Field) { @@ -115,8 +114,7 @@ impl PublicContext { fn push_note_hash(_self: &mut Self, note_hash: Field) { emit_note_hash(note_hash); } - fn push_nullifier(_self: &mut Self, nullifier: Field, _nullified_commitment: Field) { - // Cannot nullify pending commitments in AVM, so `nullified_commitment` is not used + fn push_nullifier(_self: &mut Self, nullifier: Field) { emit_nullifier(nullifier); } diff --git a/noir-projects/aztec-nr/aztec/src/initializer.nr b/noir-projects/aztec-nr/aztec/src/initializer.nr index 3dff18d094b..b5f88d9399b 100644 --- a/noir-projects/aztec-nr/aztec/src/initializer.nr +++ b/noir-projects/aztec-nr/aztec/src/initializer.nr @@ -10,12 +10,12 @@ use crate::{ pub fn mark_as_initialized_public(context: &mut PublicContext) { let init_nullifier = compute_unsiloed_contract_initialization_nullifier((*context).this_address()); - context.push_nullifier(init_nullifier, 0); + context.push_nullifier(init_nullifier); } pub fn mark_as_initialized_private(context: &mut PrivateContext) { let init_nullifier = compute_unsiloed_contract_initialization_nullifier((*context).this_address()); - context.push_nullifier(init_nullifier, 0); + context.push_nullifier(init_nullifier); } pub fn assert_is_initialized_public(context: &mut PublicContext) { diff --git a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr index 649d9fe1c54..52880c1e67e 100644 --- a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr +++ b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr @@ -56,19 +56,19 @@ pub fn destroy_note( let note_hash_counter = note.get_header().note_hash_counter; let note_hash_for_consumption = if (note_hash_counter == 0) { - // Counter is zero, so we're nullifying a non-transient note and we don't populate the note_hash with real - // value (if we did so the `notifyNullifiedNote` oracle would throw). + // Counter is zero, so we're nullifying a settled note and we don't populate the note_hash with real value. 0 } else { - // A non-zero note hash counter implies that we're nullifying a transient note (i.e. one that has not yet been + // A non-zero note hash counter implies that we're nullifying a pending note (i.e. one that has not yet been // persisted in the trees and is instead in the pending new note hashes array). In such a case we populate its - // hash with real value to inform the kernel which note we're nullifyng so that it can find it and squash both - // the note and the nullifier. + // hash with real value to inform the kernel which note we're nullifyng so that it can either squash both + // the note and the nullifier if it's an inner note hash, or check that the it matches a pending note if it's + // a siloed note hash. note_hash }; let nullifier_counter = context.side_effect_counter; assert(notify_nullified_note(nullifier, note_hash_for_consumption, nullifier_counter) == 0); - context.push_nullifier(nullifier, note_hash_for_consumption) + context.push_nullifier_for_note_hash(nullifier, note_hash_for_consumption) } diff --git a/noir-projects/aztec-nr/aztec/src/note/utils.nr b/noir-projects/aztec-nr/aztec/src/note/utils.nr index 094fdc81476..33381da9305 100644 --- a/noir-projects/aztec-nr/aztec/src/note/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/note/utils.nr @@ -52,25 +52,42 @@ fn compute_note_hash_for_read_request_from_slotted_and_nonce(slotted_note_hash: pub fn compute_note_hash_for_read_request(note: Note) -> Field where Note: NoteInterface { let slotted_note_hash = compute_slotted_note_hash(note); let nonce = note.get_header().nonce; + let counter = note.get_header().note_hash_counter; - compute_note_hash_for_read_request_from_slotted_and_nonce(slotted_note_hash, nonce) + if counter != 0 { + slotted_note_hash + } else { + compute_note_hash_for_read_request_from_slotted_and_nonce(slotted_note_hash, nonce) + } } pub fn compute_note_hash_for_consumption(note: Note) -> Field where Note: NoteInterface { let header = note.get_header(); - // There are 3 cases for reading a note intended for consumption: - // 1. The note was inserted in this transaction, and is transient. - // 2. The note was inserted in a previous transaction, and was inserted in public - // 3. The note was inserted in a previous transaction, and was inserted in private + // There are 4 cases for reading a note intended for consumption: + // 1. The note was inserted in this transaction, is revertible, or is not nullified by a revertible nullifier in + // the same transaction: (note_hash_counter != 0) & (nonce == 0) + // 2. The note was inserted in this transaction, is non-revertible, and is nullified by a revertible nullifier in + // the same transaction: (note_hash_counter != 0) & (nonce != 0) + // 3. The note was inserted in a previous transaction, and was inserted in public: (note_hash_counter == 0) & (nonce == 0) + // 4. The note was inserted in a previous transaction, and was inserted in private: (note_hash_counter == 0) & (nonce != 0) let slotted_note_hash = compute_slotted_note_hash(note); - if (header.note_hash_counter != 0) { + if ((header.note_hash_counter != 0) & (header.nonce == 0)) { + // Case 1. // If a note is transient, we just read the slotted_note_hash (kernel will silo by contract address). slotted_note_hash } else { - // If a note is not transient, that means we are reading a settled note (from tree) created in a - // previous TX. So we need the siloed_note_hash which has already been hashed with + // Case 2: If a note is non-revertible, and is nullified by a revertible nullifier, we cannot squash them in the + // private reset circuit. Because if the tx reverts, we will have to keep the note hash and throw away the + // nullifier. + // And if the tx does not revert, both will be emitted. In which case, the nullifier must be created in the app + // from the siloed note hash. + // The kernel circuit will check that a nullifier with non-zero note_nonce is linked to a note hash, whose + // siloed note hash matches the note hash specified in the nullifier. + + // Case 3 & 4: If a note is not from the current transaction, that means we are reading a settled note (from + // tree) created in a previous TX. So we need the siloed_note_hash which has already been hashed with // nonce and then contract address. This hash will match the existing leaf in the note hash // tree, so the kernel can just perform a membership check directly on this hash/leaf. let unique_note_hash = compute_note_hash_for_read_request_from_slotted_and_nonce(slotted_note_hash, header.nonce); diff --git a/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr b/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr index 97c2553299f..484c4e59030 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr @@ -56,3 +56,9 @@ unconstrained pub fn set_public_teardown_function_call_internal( ); } +#[oracle(notifySetMinRevertibleSideEffectCounter)] +unconstrained fn notify_set_min_revertible_side_effect_counter_oracle(_counter: u32) {} + +unconstrained pub fn notify_set_min_revertible_side_effect_counter(counter: u32) { + notify_set_min_revertible_side_effect_counter_oracle(counter); +} diff --git a/noir-projects/aztec-nr/aztec/src/oracle/mod.nr b/noir-projects/aztec-nr/aztec/src/oracle/mod.nr index ca5d02105c0..5c9b0550865 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/mod.nr @@ -17,7 +17,6 @@ mod get_sibling_path; mod unsafe_rand; mod enqueue_public_function_call; mod header; -mod public_call; mod notes; mod storage; mod logs; diff --git a/noir-projects/aztec-nr/aztec/src/oracle/public_call.nr b/noir-projects/aztec-nr/aztec/src/oracle/public_call.nr deleted file mode 100644 index 3a632426b19..00000000000 --- a/noir-projects/aztec-nr/aztec/src/oracle/public_call.nr +++ /dev/null @@ -1,28 +0,0 @@ -use dep::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}; -#[oracle(callPublicFunction)] -unconstrained fn call_public_function_oracle( - _contract_address: AztecAddress, - _function_selector: FunctionSelector, - _args_hash: Field, - _side_effect_counter: u32, - _is_static_call: bool, - _is_delegate_call: bool -) -> [Field; RETURNS_COUNT] {} - -unconstrained pub fn call_public_function_internal( - contract_address: AztecAddress, - function_selector: FunctionSelector, - args_hash: Field, - side_effect_counter: u32, - is_static_call: bool, - is_delegate_call: bool -) -> [Field; RETURNS_COUNT] { - call_public_function_oracle( - contract_address, - function_selector, - args_hash, - side_effect_counter, - is_static_call, - is_delegate_call - ) -} diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr index 95ee56edefb..bc95a67be66 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr @@ -47,7 +47,7 @@ impl PrivateImmutable { ) -> NoteEmission where Note: NoteInterface { // Nullify the storage slot. let nullifier = self.compute_initialization_nullifier(); - self.context.push_nullifier(nullifier, 0); + self.context.push_nullifier(nullifier); create_note(self.context, self.storage_slot, note) } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr index 497f9dc987b..85bc5319678 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr @@ -48,7 +48,7 @@ impl PrivateMutable where Note: NoteInter pub fn initialize(self, note: &mut Note) -> NoteEmission { // Nullify the storage slot. let nullifier = self.compute_initialization_nullifier(); - self.context.push_nullifier(nullifier, 0); + self.context.push_nullifier(nullifier); create_note(self.context, self.storage_slot, note) } 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 55542886694..bc048e52adc 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 @@ -373,7 +373,7 @@ contract AvmTest { // Use the standard context interface to emit a new nullifier #[aztec(public)] fn new_nullifier(nullifier: Field) { - context.push_nullifier(nullifier, 0); + context.push_nullifier(nullifier); } // Use the standard context interface to check for a nullifier @@ -390,7 +390,7 @@ contract AvmTest { // Use the standard context interface to emit a new nullifier #[aztec(public)] fn emit_nullifier_and_check(nullifier: Field) { - context.push_nullifier(nullifier, 0); + context.push_nullifier(nullifier); let exists = context.nullifier_exists(nullifier, context.storage_address()); assert(exists, "Nullifier was just created, but its existence wasn't detected!"); } @@ -398,9 +398,9 @@ contract AvmTest { // Create the same nullifier twice (shouldn't work!) #[aztec(public)] fn nullifier_collision(nullifier: Field) { - context.push_nullifier(nullifier, 0); + context.push_nullifier(nullifier); // Can't do this twice! - context.push_nullifier(nullifier, 0); + context.push_nullifier(nullifier); } #[aztec(public)] @@ -446,13 +446,13 @@ contract AvmTest { #[aztec(public)] fn create_same_nullifier_in_nested_call(nestedAddress: AztecAddress, nullifier: Field) { - context.push_nullifier(nullifier, 0); + context.push_nullifier(nullifier); AvmTest::at(nestedAddress).new_nullifier(nullifier).call(&mut context); } #[aztec(public)] fn create_different_nullifier_in_nested_call(nestedAddress: AztecAddress, nullifier: Field) { - context.push_nullifier(nullifier, 0); + context.push_nullifier(nullifier); AvmTest::at(nestedAddress).new_nullifier(nullifier + 1).call(&mut context); } 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 0d7fe868d50..8b15ee8f04e 100644 --- a/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr @@ -39,7 +39,7 @@ contract Claim { // The nullifier is unique to the note and THIS contract because the protocol siloes all nullifiers with // the address of a contract it was emitted from. let (_, nullifier) = proof_note.compute_note_hash_and_nullifier(&mut context); - context.push_nullifier(nullifier, 0); + context.push_nullifier(nullifier); // 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).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 b268d9ee1c9..8158fc27015 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 @@ -44,7 +44,7 @@ contract ContractClassRegisterer { // Emit the contract class id as a nullifier to be able to prove that this class has been (not) registered let event = ContractClassRegistered { contract_class_id, version: 1, artifact_hash, private_functions_root, packed_public_bytecode }; - context.push_nullifier(contract_class_id.to_field(), 0); + context.push_nullifier(contract_class_id.to_field()); // Broadcast class info including public bytecode dep::aztec::oracle::debug_log::debug_log_format( 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 bea326ca5f1..27e7c717bdc 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 @@ -42,7 +42,7 @@ contract ContractInstanceDeployer { let address = AztecAddress::compute(public_keys_hash, partial_address); // Emit the address as a nullifier to be able to prove that this instance has been (not) deployed - context.push_nullifier(address.to_field(), 0); + context.push_nullifier(address.to_field()); // Broadcast the event let event = ContractInstanceDeployed { diff --git a/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr b/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr index 774034e276a..e29a9754652 100644 --- a/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr @@ -35,7 +35,7 @@ contract EasyPrivateVoting { let secret = context.request_nsk_app(msg_sender_npk_m_hash); // get secret key of caller of function let nullifier = std::hash::pedersen_hash([context.msg_sender().to_field(), secret]); // derive nullifier from sender and secret - context.push_nullifier(nullifier, 0); // push nullifier + context.push_nullifier(nullifier); EasyPrivateVoting::at(context.this_address()).add_to_tally_public(candidate).enqueue(&mut context); } // docs:end:cast_vote diff --git a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr index 13d762ee531..4ace7740842 100644 --- a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr @@ -179,7 +179,7 @@ contract InclusionProofs { #[aztec(public)] fn push_nullifier_public(nullifier: Field) { - context.push_nullifier(nullifier, 0); + context.push_nullifier(nullifier); } // Proves nullifier existed at latest block diff --git a/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr index 60abc87e0ba..be0895bb493 100644 --- a/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr @@ -23,7 +23,7 @@ contract PrivateFPC { fn fund_transaction_privately(amount: Field, asset: AztecAddress, user_randomness: Field) { assert(asset == storage.other_asset.read_private()); // convince the FPC we are not cheating - context.push_nullifier(user_randomness, 0); + context.push_nullifier(user_randomness); // We use different randomness for fee payer to prevent a potential privay leak (see impl // of PrivatelyRefundable for TokenNote for details). 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 3cf7eb92a08..0a19e7583da 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -248,13 +248,13 @@ contract Test { // Purely exists for testing #[aztec(public)] fn emit_nullifier_public(nullifier: Field) { - context.push_nullifier(nullifier, 0); + context.push_nullifier(nullifier); } // Forcefully emits a nullifier (for testing purposes) #[aztec(private)] fn emit_nullifier(nullifier: Field) { - context.push_nullifier(nullifier, 0); + context.push_nullifier(nullifier); } // For testing non-note encrypted logs 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 e12673267f4..faa737f2efc 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -351,7 +351,7 @@ contract Token { fn cancel_authwit(inner_hash: Field) { let on_behalf_of = context.msg_sender(); let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash); - context.push_nullifier(nullifier, 0); + context.push_nullifier(nullifier); } // docs:end:cancel_authwit diff --git a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr index 06911c88348..36e495ca6cc 100644 --- a/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_with_refunds_contract/src/main.nr @@ -347,7 +347,7 @@ contract TokenWithRefunds { fn cancel_authwit(inner_hash: Field) { let on_behalf_of = context.msg_sender(); let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash); - context.push_nullifier(nullifier, 0); + context.push_nullifier(nullifier); } // docs:end:cancel_authwit diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr index b1f6836edd8..43c4065906c 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr @@ -1,31 +1,36 @@ +mod previous_kernel_validator_hints; + +use crate::components::previous_kernel_validator::previous_kernel_validator_hints::{generate_previous_kernel_validator_hints, PreviousKernelValidatorHints}; use dep::types::{ abis::kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, utils::arrays::array_length, traits::is_empty }; struct PreviousKernelValidator { - previous_kernel: PrivateKernelCircuitPublicInputs + previous_kernel: PrivateKernelCircuitPublicInputs, + hints: PreviousKernelValidatorHints, } impl PreviousKernelValidator { pub fn new(previous_kernel: PrivateKernelCircuitPublicInputs) -> Self { - PreviousKernelValidator { previous_kernel } + let hints = generate_previous_kernel_validator_hints(previous_kernel); + PreviousKernelValidator { previous_kernel, hints } } pub fn validate_for_private_tail(self) { self.validate_common(); - self.validate_empty_public_call_requests(); + self.validate_empty_data(); } pub fn validate_for_private_tail_to_public(self) { self.validate_common(); - self.validate_non_empty_public_call_requests(); + self.validate_non_empty_data(); } fn validate_common(self) { self.validate_empty_private_call_stack(); self.verify_empty_validation_requests(); - self.verify_no_transient_data(); + self.validate_no_transient_data(); } fn validate_empty_private_call_stack(self) { @@ -34,20 +39,38 @@ impl PreviousKernelValidator { ); } - fn validate_empty_public_call_requests(self) { + fn validate_empty_data(self) { assert_eq( array_length(self.previous_kernel.end.public_call_requests), 0, "Public call stack must be empty when executing the tail circuit" ); assert( is_empty(self.previous_kernel.public_teardown_call_request), "Public teardown call request must be empty when executing the tail circuit" ); + + if self.previous_kernel.validation_requests.split_counter.is_some() { + // Even when min_revertible_side_effect_counter could be non-zero in a pure private tx. + // The split counter must be 0 to ensure that all the transient data are squashed. + assert_eq( + self.previous_kernel.validation_requests.split_counter.unwrap_unchecked(), 0, "split_counter must be 0 for pure private tx" + ); + } } - fn validate_non_empty_public_call_requests(self) { + fn validate_non_empty_data(self) { let len = array_length(self.previous_kernel.end.public_call_requests); assert( (len != 0) | !is_empty(self.previous_kernel.public_teardown_call_request), "Must have public calls when exporting public kernel data from the tail circuit" ); + + assert( + self.previous_kernel.min_revertible_side_effect_counter != 0, "min_revertible_side_effect_counter must not be 0" + ); + + if self.previous_kernel.validation_requests.split_counter.is_some() { + assert_eq( + self.previous_kernel.validation_requests.split_counter.unwrap_unchecked(), self.previous_kernel.min_revertible_side_effect_counter, "split_counter does not match min_revertible_side_effect_counter" + ); + } } fn verify_empty_validation_requests(self) { @@ -62,11 +85,22 @@ impl PreviousKernelValidator { ); } - fn verify_no_transient_data(self) { - // Currently all the transient nullifiers must be cleared in the reset circuits. - // When a transient nullifier is removed, the linked note hash and all the associated note logs will also be removed. - for nullifier in self.previous_kernel.end.nullifiers { - assert_eq(nullifier.nullified_note_hash(), 0, "Unresolved transient nullifier"); + fn validate_no_transient_data(self) { + let nullifiers = self.previous_kernel.end.nullifiers; + let inner_note_hashes = self.previous_kernel.end.note_hashes; + let siloed_note_hashes = self.hints.siloed_note_hashes; + let note_hash_indexes_for_nullifiers = self.hints.note_hash_indexes_for_nullifiers; + for i in 0..nullifiers.len() { + let nullified_note_hash = nullifiers[i].nullifier.note_hash; + if nullified_note_hash != 0 { + let note_hash_index = note_hash_indexes_for_nullifiers[i]; + assert_eq( + nullified_note_hash, siloed_note_hashes[note_hash_index], "Hinted siloed note hash does not match nullified note hash" + ); + assert( + inner_note_hashes[note_hash_index].counter() < nullifiers[i].counter(), "Cannot link a note hash emitted after a nullifier" + ); + } } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator/previous_kernel_validator_hints.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator/previous_kernel_validator_hints.nr new file mode 100644 index 00000000000..1d0c9cf8199 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator/previous_kernel_validator_hints.nr @@ -0,0 +1,32 @@ +use dep::types::{ + abis::kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, + constants::{MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX}, hash::silo_note_hash, + utils::arrays::{find_index, sort_get_order_hints_asc} +}; + +struct PreviousKernelValidatorHints { + siloed_note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], + note_hash_indexes_for_nullifiers: [u32; MAX_NULLIFIERS_PER_TX], +} + +unconstrained pub fn generate_previous_kernel_validator_hints(previous_kernel: PrivateKernelCircuitPublicInputs) -> PreviousKernelValidatorHints { + let mut siloed_note_hashes = [0; MAX_NOTE_HASHES_PER_TX]; + let unsilod_note_hashes = previous_kernel.end.note_hashes; + let sorted_note_hash_hints = sort_get_order_hints_asc(unsilod_note_hashes); + let tx_hash = previous_kernel.end.nullifiers[0].value(); // First nullifier is tx hash. + for i in 0..unsilod_note_hashes.len() { + siloed_note_hashes[i] = silo_note_hash(unsilod_note_hashes[i], tx_hash, sorted_note_hash_hints[i].sorted_index); + } + + let mut note_hash_indexes_for_nullifiers = [0; MAX_NULLIFIERS_PER_TX]; + let nullifiers = previous_kernel.end.nullifiers; + for i in 0..nullifiers.len() { + let nullified_note_hash = nullifiers[i].nullifier.note_hash; + let note_hash_index = find_index(siloed_note_hashes, |n: Field| n == nullified_note_hash); + if (nullified_note_hash != 0) & (note_hash_index != MAX_NOTE_HASHES_PER_TX) { + note_hash_indexes_for_nullifiers[i] = note_hash_index; + } + } + + PreviousKernelValidatorHints { siloed_note_hashes, note_hash_indexes_for_nullifiers } +} 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 37a858d04e5..562b2c66699 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 @@ -239,6 +239,10 @@ impl PrivateKernelCircuitOutputValidator { ) { assert_eq(self.output.constants, previous_kernel.constants, "mismatch constants"); + assert_eq( + self.output.validation_requests.split_counter, previous_kernel.validation_requests.split_counter, "mismatch validation requests split counter" + ); + validate_array_prepended( self.output.validation_requests.note_hash_read_requests, previous_kernel.validation_requests.note_hash_read_requests, 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 1993ea11092..e27795d3bde 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 @@ -66,6 +66,7 @@ impl PrivateKernelCircuitPublicInputsComposer { public_inputs.validation_requests.note_hash_read_requests = array_to_bounded_vec(start.note_hash_read_requests); public_inputs.validation_requests.nullifier_read_requests = array_to_bounded_vec(start.nullifier_read_requests); public_inputs.validation_requests.scoped_key_validation_requests_and_generators = array_to_bounded_vec(start.scoped_key_validation_requests_and_generators); + public_inputs.validation_requests.split_counter = start.split_counter; let start = previous_kernel_public_inputs.end; public_inputs.end.note_hashes = array_to_bounded_vec(start.note_hashes); 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 7ef9a42e076..69057ab52b2 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 @@ -1,10 +1,11 @@ -mod kernel_circuit_output_hints; +mod tail_output_hints; mod validate_value_transformation; use crate::components::{ + previous_kernel_validator::previous_kernel_validator_hints::PreviousKernelValidatorHints, tail_output_composer::meter_gas_used::meter_gas_used, tail_output_validator::{ - kernel_circuit_output_hints::{generate_kernel_circuit_output_hints, Hints}, + tail_output_hints::{generate_tail_output_hints, TailOutputHints}, validate_value_transformation::{validate_transformed_values, validate_value_transformation} } }; @@ -24,22 +25,25 @@ use dep::types::{ struct TailOutputValidator { output: KernelCircuitPublicInputs, previous_kernel: PrivateKernelCircuitPublicInputs, + previous_kernel_hints: PreviousKernelValidatorHints, + hints: TailOutputHints, } impl TailOutputValidator { pub fn new( output: KernelCircuitPublicInputs, - previous_kernel: PrivateKernelCircuitPublicInputs + previous_kernel: PrivateKernelCircuitPublicInputs, + previous_kernel_hints: PreviousKernelValidatorHints ) -> Self { - TailOutputValidator { output, previous_kernel } + let hints = generate_tail_output_hints(previous_kernel); + TailOutputValidator { output, previous_kernel, previous_kernel_hints, hints } } pub fn validate(self) { - let hints = generate_kernel_circuit_output_hints(self.previous_kernel); self.validate_empty_values(); self.validate_propagated_values(); - self.validate_propagated_sorted_siloed_values(hints); - self.validate_accumulated_values(hints); + self.validate_propagated_sorted_siloed_values(); + self.validate_accumulated_values(); self.validate_gas_used(); } @@ -58,97 +62,102 @@ impl TailOutputValidator { assert_eq(self.output.fee_payer, self.previous_kernel.fee_payer, "mismatch fee_payer"); } - fn validate_propagated_sorted_siloed_values(self, hints: Hints) { - // First nullifier is tx hash. - let tx_hash = self.output.end.nullifiers[0]; + fn validate_propagated_sorted_siloed_values(self) { + // note_hashes + let siloed_note_hashes = self.previous_kernel_hints.siloed_note_hashes; + let sorted_note_hash_hints = self.hints.sorted_note_hash_hints; let unsiloed_note_hashes = self.previous_kernel.end.note_hashes; + let tx_hash = self.output.end.nullifiers[0]; // First nullifier is tx hash. for i in 0..unsiloed_note_hashes.len() { - let siloed_note_hash = silo_note_hash(unsiloed_note_hashes[i], tx_hash, i); - assert_eq(hints.siloed_note_hashes[i], siloed_note_hash, "mismatch siloed note hashes"); + let siloed_note_hash = silo_note_hash( + unsiloed_note_hashes[i], + tx_hash, + sorted_note_hash_hints[i].sorted_index + ); + assert_eq(siloed_note_hashes[i], siloed_note_hash, "mismatch siloed note hashes"); } assert_sorted_transformed_value_array( self.previous_kernel.end.note_hashes, - hints.siloed_note_hashes, + siloed_note_hashes, self.output.end.note_hashes, - hints.sorted_note_hash_hints + sorted_note_hash_hints ); // nullifiers validate_transformed_values( self.previous_kernel.end.nullifiers, - hints.siloed_nullifiers, + self.hints.siloed_nullifiers, silo_nullifier ); assert_sorted_transformed_value_array( self.previous_kernel.end.nullifiers, - hints.siloed_nullifiers, + self.hints.siloed_nullifiers, self.output.end.nullifiers, - hints.sorted_nullifier_hints + self.hints.sorted_nullifier_hints ); // l2_to_l1_msgs let tx_context = self.previous_kernel.constants.tx_context; validate_transformed_values( self.previous_kernel.end.l2_to_l1_msgs, - hints.siloed_l2_to_l1_msgs, + self.hints.siloed_l2_to_l1_msgs, |msg| silo_l2_to_l1_message(msg, tx_context.version, tx_context.chain_id) ); assert_sorted_transformed_value_array( self.previous_kernel.end.l2_to_l1_msgs, - hints.siloed_l2_to_l1_msgs, + self.hints.siloed_l2_to_l1_msgs, self.output.end.l2_to_l1_msgs, - hints.sorted_l2_to_l1_msg_hints + self.hints.sorted_l2_to_l1_msg_hints ); } - fn validate_accumulated_values(self, hints: Hints) { + fn validate_accumulated_values(self) { // note_encrypted_log_hashes validate_value_transformation( self.previous_kernel.end.note_encrypted_logs_hashes, - hints.note_encrypted_log_hashes, + self.hints.note_encrypted_log_hashes, |nlh: NoteLogHash, lh: LogHash| (nlh.value == lh.value) & (nlh.length == lh.length) ); assert_sorted_transformed_value_array( self.previous_kernel.end.note_encrypted_logs_hashes, - hints.note_encrypted_log_hashes, - hints.sorted_note_encrypted_log_hashes, - hints.sorted_note_encrypted_log_hash_hints + self.hints.note_encrypted_log_hashes, + self.hints.sorted_note_encrypted_log_hashes, + self.hints.sorted_note_encrypted_log_hash_hints ); - let hash = compute_tx_note_logs_hash(hints.sorted_note_encrypted_log_hashes); + let hash = compute_tx_note_logs_hash(self.hints.sorted_note_encrypted_log_hashes); assert_eq(hash, self.output.end.note_encrypted_logs_hash, "mismatch note_encrypted_logs_hash"); // encrypted_log_hashes validate_value_transformation( self.previous_kernel.end.encrypted_logs_hashes, - hints.siloed_encrypted_log_hashes, + self.hints.siloed_encrypted_log_hashes, |slh: ScopedEncryptedLogHash, lh: LogHash| (lh.value == silo_encrypted_log_hash(slh)) & (lh.length == slh.log_hash.length) ); assert_sorted_transformed_value_array( self.previous_kernel.end.encrypted_logs_hashes, - hints.siloed_encrypted_log_hashes, - hints.sorted_siloed_encrypted_log_hashes, - hints.sorted_encrypted_log_hash_hints + self.hints.siloed_encrypted_log_hashes, + self.hints.sorted_siloed_encrypted_log_hashes, + self.hints.sorted_encrypted_log_hash_hints ); - let hash = compute_tx_logs_hash(hints.sorted_siloed_encrypted_log_hashes); + let hash = compute_tx_logs_hash(self.hints.sorted_siloed_encrypted_log_hashes); assert_eq(hash, self.output.end.encrypted_logs_hash, "mismatch encrypted_logs_hash"); // unencrypted_log_hashes - assert_sorted_array_with_order_hints( self.previous_kernel.end.unencrypted_logs_hashes, - hints.sorted_unencrypted_log_hashes, - hints.sorted_unencrypted_log_hash_hints + self.hints.sorted_unencrypted_log_hashes, + self.hints.sorted_unencrypted_log_hash_hints ); assert_eq( - hints.sorted_unencrypted_log_hashes.map(|log: ScopedLogHash| log.expose_to_public()), self.output.end.unencrypted_logs_hashes, "mismatch unencrypted_logs_hashes" + self.hints.sorted_unencrypted_log_hashes.map(|log: ScopedLogHash| log.expose_to_public()), self.output.end.unencrypted_logs_hashes, "mismatch unencrypted_logs_hashes" ); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/kernel_circuit_output_hints.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/tail_output_hints.nr similarity index 87% rename from noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/kernel_circuit_output_hints.nr rename to noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/tail_output_hints.nr index 7dd95e99431..0be773d1849 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/kernel_circuit_output_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/tail_output_hints.nr @@ -12,10 +12,9 @@ use dep::types::{ utils::arrays::{OrderHint, sort_by_counters_asc, sort_get_order_hints_asc} }; -struct Hints { +struct TailOutputHints { // Note hashes. sorted_note_hash_hints: [OrderHint; MAX_NOTE_HASHES_PER_TX], - siloed_note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], // Nullifiers. sorted_nullifier_hints: [OrderHint; MAX_NULLIFIERS_PER_TX], siloed_nullifiers: [Field; MAX_NULLIFIERS_PER_TX], @@ -35,19 +34,10 @@ struct Hints { sorted_unencrypted_log_hash_hints: [OrderHint; MAX_UNENCRYPTED_LOGS_PER_TX], } -unconstrained pub fn generate_kernel_circuit_output_hints(previous_kernel: PrivateKernelCircuitPublicInputs) -> Hints { +unconstrained pub fn generate_tail_output_hints(previous_kernel: PrivateKernelCircuitPublicInputs) -> TailOutputHints { // note_hashes let sorted_note_hash_hints = sort_get_order_hints_asc(previous_kernel.end.note_hashes); - let mut siloed_note_hashes = [0; MAX_NOTE_HASHES_PER_TX]; - - // First nullifier is tx hash. - let tx_hash = previous_kernel.end.nullifiers[0].value(); - let unsiloed_note_hashes = previous_kernel.end.note_hashes; - for i in 0..unsiloed_note_hashes.len() { - siloed_note_hashes[i] = silo_note_hash(unsiloed_note_hashes[i], tx_hash, i); - } - // nullifiers let sorted_nullifier_hints = sort_get_order_hints_asc(previous_kernel.end.nullifiers); let siloed_nullifiers = previous_kernel.end.nullifiers.map(silo_nullifier); @@ -82,9 +72,8 @@ unconstrained pub fn generate_kernel_circuit_output_hints(previous_kernel: Priva let sorted_unencrypted_log_hashes = sort_by_counters_asc(previous_kernel.end.unencrypted_logs_hashes); let sorted_unencrypted_log_hash_hints = sort_get_order_hints_asc(previous_kernel.end.unencrypted_logs_hashes); - Hints { + TailOutputHints { sorted_note_hash_hints, - siloed_note_hashes, sorted_nullifier_hints, siloed_nullifiers, sorted_l2_to_l1_msg_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 d947609bd6c..4a22e8d18d5 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 @@ -8,7 +8,10 @@ use crate::components::{ split_to_public::split_to_public } }; -use dep::types::abis::{kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}}; +use dep::types::abis::{ + kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}, + validation_requests::PublicValidationRequests +}; struct TailToPublicOutputComposer { output_composer: PrivateKernelCircuitPublicInputsComposer, @@ -24,8 +27,12 @@ impl TailToPublicOutputComposer { pub fn finish(self) -> PublicKernelCircuitPublicInputs { let source = self.output_composer.public_inputs; + + let mut validation_requests = PublicValidationRequests::empty(); + validation_requests.for_rollup = source.validation_requests.for_rollup(); + let mut output = PublicKernelCircuitPublicInputs::empty(); - output.validation_requests = source.validation_requests.finish(); + output.validation_requests = validation_requests; output.constants = source.constants; output.public_teardown_call_stack[0] = source.public_teardown_call_request.expose_to_public(); output.fee_payer = source.fee_payer; 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 43108d70a20..865d409c2e9 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 @@ -10,8 +10,6 @@ pub fn split_to_public( data: PrivateAccumulatedDataBuilder, min_revertible_side_effect_counter: u32 ) -> (PublicAccumulatedData, PublicAccumulatedData) { - assert(min_revertible_side_effect_counter != 0, "min_revertible_side_effect_counter must not be 0"); - let mut non_revertible_builder = PublicAccumulatedDataBuilder::empty(); let mut revertible_builder = PublicAccumulatedDataBuilder::empty(); 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 bc375dc4c19..4d569989d9a 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,42 +1,46 @@ mod tail_to_public_output_hints; use crate::components::{ - tail_output_validator::validate_value_transformation::{validate_transformed_values, validate_value_transformation}, + previous_kernel_validator::previous_kernel_validator_hints::PreviousKernelValidatorHints, + tail_output_validator::{validate_value_transformation::{validate_transformed_values, validate_value_transformation}}, tail_to_public_output_composer::meter_gas_used::{meter_gas_used_non_revertible, meter_gas_used_revertible}, tail_to_public_output_validator::tail_to_public_output_hints::{generate_tail_to_public_output_hints, TailToPublicOutputHints} }; use dep::types::{ abis::{ kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}, - log_hash::{LogHash, ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash}, nullifier::Nullifier, - public_call_request::PublicCallRequest + log_hash::{LogHash, ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash}, note_hash::NoteHash, + nullifier::Nullifier, public_call_request::PublicCallRequest }, hash::{silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier}, traits::{Empty, is_empty, is_empty_array}, utils::arrays::{ - assert_split_sorted_transformed_value_arrays_asc, assert_split_sorted_transformed_value_arrays_desc, - validate_array + array_length, assert_split_sorted_transformed_value_arrays_asc, + assert_split_sorted_transformed_value_arrays_desc, validate_array } }; struct TailToPublicOutputValidator { output: PublicKernelCircuitPublicInputs, previous_kernel: PrivateKernelCircuitPublicInputs, + previous_kernel_hints: PreviousKernelValidatorHints, + hints: TailToPublicOutputHints, } impl TailToPublicOutputValidator { pub fn new( output: PublicKernelCircuitPublicInputs, - previous_kernel: PrivateKernelCircuitPublicInputs + previous_kernel: PrivateKernelCircuitPublicInputs, + previous_kernel_hints: PreviousKernelValidatorHints ) -> Self { - TailToPublicOutputValidator { output, previous_kernel } + let hints = generate_tail_to_public_output_hints(previous_kernel); + TailToPublicOutputValidator { output, previous_kernel, previous_kernel_hints, hints } } pub fn validate(self) { - let hints = generate_tail_to_public_output_hints(self.previous_kernel); self.validate_empty_values(); self.validate_propagated_values(); - self.validate_propagated_sorted_siloed_values(hints); + self.validate_propagated_sorted_siloed_values(); self.validate_gas_used(); } @@ -73,26 +77,34 @@ impl TailToPublicOutputValidator { ); } - fn validate_propagated_sorted_siloed_values(self, hints: TailToPublicOutputHints) { + fn validate_propagated_sorted_siloed_values(self) { let split_counter = self.previous_kernel.min_revertible_side_effect_counter; - assert(split_counter != 0, "min_revertible_side_effect_counter must not be 0"); - let prev_data = self.previous_kernel.end; let output_non_revertible = self.output.end_non_revertible; let output_revertible = self.output.end; + let hints = self.hints; + let previous_kernel_hints = self.previous_kernel_hints; // note_hashes - let first_nullifier = output_non_revertible.nullifiers[0].value; + let siloed_note_hashes = previous_kernel_hints.siloed_note_hashes; let unsiloed_note_hashes = prev_data.note_hashes; + let tx_hash = output_non_revertible.nullifiers[0].value; + let sorted_split_indexes = hints.sorted_note_hash_hints.sorted_indexes; + let sorted_counters_gte = hints.sorted_note_hash_hints.sorted_counters_gte; + let num_non_revertible = array_length(output_non_revertible.note_hashes); for i in 0..unsiloed_note_hashes.len() { - let siloed_note_hash = silo_note_hash(unsiloed_note_hashes[i], first_nullifier, i); - assert_eq(hints.siloed_note_hashes[i].value, siloed_note_hash, "mismatch siloed note hashes"); - assert_eq(hints.siloed_note_hashes[i].counter, 0, "cannot expose note hash counter"); + let note_hash = unsiloed_note_hashes[i]; + let mut index = sorted_split_indexes[i]; + if sorted_counters_gte[index] == note_hash.counter() { + index += num_non_revertible; + } + let siloed_note_hash = silo_note_hash(note_hash, tx_hash, index); + assert_eq(siloed_note_hashes[i], siloed_note_hash, "mismatch siloed note hashes"); } assert_split_sorted_transformed_value_arrays_asc( prev_data.note_hashes, - hints.siloed_note_hashes, + siloed_note_hashes.map(|value: Field| NoteHash { value, counter: 0 }), split_counter, output_non_revertible.note_hashes, output_revertible.note_hashes, 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 5a017223916..1084710fc85 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 @@ -15,7 +15,6 @@ use dep::types::{ struct TailToPublicOutputHints { // Note hashes. - siloed_note_hashes: [NoteHash; MAX_NOTE_HASHES_PER_TX], sorted_note_hash_hints: SplitOrderHints, // Nullifiers. siloed_nullifiers: [Nullifier; MAX_NULLIFIERS_PER_TX], @@ -41,13 +40,6 @@ unconstrained pub fn generate_tail_to_public_output_hints(previous_kernel: Priva // note_hashes let unsiloed_note_hashes = previous_kernel.end.note_hashes; - - let first_nullifier = previous_kernel.end.nullifiers[0].value(); - let mut siloed_note_hashes = [NoteHash::empty(); MAX_NOTE_HASHES_PER_TX]; - for i in 0..unsiloed_note_hashes.len() { - siloed_note_hashes[i].value = silo_note_hash(unsiloed_note_hashes[i], first_nullifier, i); - } - let sorted_note_hash_hints = sort_get_split_order_hints_asc(unsiloed_note_hashes, split_counter); // nullifiers @@ -94,7 +86,6 @@ unconstrained pub fn generate_tail_to_public_output_hints(previous_kernel: Priva let sorted_public_call_request_hints = sort_get_split_order_hints_desc(previous_kernel.end.public_call_requests, split_counter); TailToPublicOutputHints { - siloed_note_hashes, sorted_note_hash_hints, sorted_nullifier_hints, siloed_nullifiers, 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 a57531c8d7b..fa5a9f2f9fd 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 @@ -20,6 +20,7 @@ struct PrivateKernelResetHints, nullifier_read_request_hints: NullifierReadRequestHints, key_validation_hints: [KeyValidationHint; KEY_VALIDATION_REQUESTS], + validation_requests_split_counter: u32, } struct PrivateKernelResetCircuitPrivateInputs { @@ -55,7 +56,8 @@ impl [Field; 4] { + let mut siloed_note_hashes = [0; 4]; + let inner_note_hash = 123123; + let tx_hash = self.previous_kernel.nullifiers.storage[0].value(); + for i in 0..siloed_note_hashes.len() { + self.previous_kernel.add_new_note_hash(inner_note_hash); + let note = self.previous_kernel.note_hashes.storage[i]; + siloed_note_hashes[i] = silo_note_hash(note, tx_hash, i); + } + siloed_note_hashes + } +} + +#[test] +fn validate_no_transient_data_no_extra_nullifiers_succeeds() { + let builder = PreviousKernelValidatorBuilder::new(); + builder.validate_for_private_tail(); +} + +#[test] +fn validate_no_transient_data_no_transient_nullifiers_succeeds() { + let mut builder = PreviousKernelValidatorBuilder::new(); + + builder.previous_kernel.append_nullifiers(3); + + builder.validate_for_private_tail(); +} + +#[test] +fn validate_no_transient_data_nullifiers_for_note_hashes_succeeds() { + let mut builder = PreviousKernelValidatorBuilder::new(); + + let siloed_note_hashes = builder.append_same_inner_note_hashes(); + builder.previous_kernel.add_nullifier(1); + builder.previous_kernel.add_nullifier_for_note_hash(2, siloed_note_hashes[2]); + builder.previous_kernel.add_nullifier_for_note_hash(3, siloed_note_hashes[0]); + builder.previous_kernel.add_nullifier(4); + + builder.validate_for_private_tail(); +} + +#[test(should_fail_with="Cannot link a note hash emitted after a nullifier")] +fn validate_no_transient_data_nullifiers_for_note_hashes_emitted_after_fails() { + let mut builder = PreviousKernelValidatorBuilder::new(); + + builder.previous_kernel.append_nullifiers(2); + // Emit the note hashes after the nullifiers + let siloed_note_hashes = builder.append_same_inner_note_hashes(); + // Link a note hash to the nullifier at index 2. + builder.previous_kernel.nullifiers.storage[2].nullifier.note_hash = siloed_note_hashes[0]; + + builder.validate_for_private_tail(); +} + +#[test(should_fail_with="Hinted siloed note hash does not match nullified note hash")] +fn validate_no_transient_data_nullifiers_for_note_hashes_not_found_fails() { + let mut builder = PreviousKernelValidatorBuilder::new(); + + let siloed_note_hashes = builder.append_same_inner_note_hashes(); + builder.previous_kernel.add_nullifier(1); + builder.previous_kernel.add_nullifier_for_note_hash(2, siloed_note_hashes[2]); + // Assign a random note hash for nullifier 3. + builder.previous_kernel.add_nullifier_for_note_hash(3, 123); + builder.previous_kernel.add_nullifier(4); + + builder.validate_for_private_tail(); +} 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 7a1ea86602a..14422620ccf 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 @@ -37,6 +37,40 @@ fn validate_propagated_from_previous_kernel_constants_non_empty_global_variables builder.validate_as_inner_call(); } +/** + * validation_requests + */ + +#[test] +fn validate_propagated_from_previous_kernel_validation_requests_split_counter_succeeds() { + let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); + + builder.previous_kernel.validation_requests_split_counter = Option::some(123); + builder.output.validation_requests_split_counter = Option::some(123); + + builder.validate_as_inner_call(); +} + +#[test(should_fail_with="mismatch validation requests split counter")] +fn validate_propagated_from_previous_kernel_validation_requests_split_counter_mismatch_fails() { + let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); + + builder.previous_kernel.validation_requests_split_counter = Option::some(123); + builder.output.validation_requests_split_counter = Option::some(4567); + + builder.validate_as_inner_call(); +} + +#[test(should_fail_with="mismatch validation requests split counter")] +fn validate_propagated_from_previous_kernel_validation_requests_split_counter_unexpected_fails() { + let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); + + builder.previous_kernel.validation_requests_split_counter = Option::none(); + builder.output.validation_requests_split_counter = Option::some(123); + + builder.validate_as_inner_call(); +} + /** * note_hash_read_requests */ 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 524e283b332..cbb0fc236f5 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 @@ -4,15 +4,22 @@ mod validate_gas_used; mod validate_propagated_sorted_siloed_values; mod validate_propagated_values; -use crate::components::{tail_output_composer::meter_gas_used::meter_gas_used, tail_output_validator::TailOutputValidator}; +use crate::components::{ + previous_kernel_validator::previous_kernel_validator_hints::{generate_previous_kernel_validator_hints, PreviousKernelValidatorHints}, + tail_output_composer::meter_gas_used::meter_gas_used, + tail_output_validator::{tail_output_hints::{generate_tail_output_hints, TailOutputHints}, TailOutputValidator} +}; use dep::types::{ - abis::{gas_settings::GasSettings, kernel_circuit_public_inputs::KernelCircuitPublicInputs}, + abis::{ + gas_settings::GasSettings, + kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs} +}, tests::fixture_builder::FixtureBuilder }; struct TailOutputValidatorBuilder { output: FixtureBuilder, - previous_kernel: FixtureBuilder + previous_kernel: FixtureBuilder, } impl TailOutputValidatorBuilder { @@ -26,6 +33,16 @@ impl TailOutputValidatorBuilder { TailOutputValidatorBuilder { output, previous_kernel } } + pub fn get_hints(self) -> TailOutputHints { + let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); + generate_tail_output_hints(previous_kernel) + } + + pub fn get_previous_kernel_hints(self) -> PreviousKernelValidatorHints { + let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); + generate_previous_kernel_validator_hints(previous_kernel) + } + 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.constants.tx_context.gas_settings); @@ -34,12 +51,25 @@ impl TailOutputValidatorBuilder { pub fn validate(self) { let output = self.export_output(); - let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); - TailOutputValidator::new(output, previous_kernel).validate(); + self.validate_with_output(output); } pub fn validate_with_output(self, output: KernelCircuitPublicInputs) { let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); - TailOutputValidator::new(output, previous_kernel).validate(); + let previous_kernel_hints = generate_previous_kernel_validator_hints(previous_kernel); + TailOutputValidator::new(output, previous_kernel, previous_kernel_hints).validate(); + } + + pub fn validate_with_hints(self, hints: TailOutputHints) { + let output = self.export_output(); + let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); + let previous_kernel_hints = generate_previous_kernel_validator_hints(previous_kernel); + TailOutputValidator { output, previous_kernel, previous_kernel_hints, hints }.validate(); + } + + pub fn validate_with_previous_kernel_hints(self, previous_kernel_hints: PreviousKernelValidatorHints) { + let output = self.export_output(); + let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); + TailOutputValidator::new(output, previous_kernel, previous_kernel_hints).validate(); } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_sorted_siloed_values.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_sorted_siloed_values.nr index a1d68769169..606762baaa5 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_sorted_siloed_values.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_sorted_siloed_values.nr @@ -20,18 +20,17 @@ fn validate_propagated_sorted_siloed_values_note_hashes_unordered_succeeds() { let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.append_note_hashes(3); - swap_items(&mut builder.previous_kernel.note_hashes, 0, 2); for i in 0..3 { // Need to silo the note hashes in the right order to hash with the correct index. builder.output.add_siloed_note_hash(builder.previous_kernel.note_hashes.storage[i].value()); } - swap_items(&mut builder.output.note_hashes, 0, 2); + swap_items(&mut builder.previous_kernel.note_hashes, 0, 2); builder.validate(); } #[test(should_fail_with="mismatch sorted values")] -fn validate_propagated_sorted_siloed_values_note_hashes_mismatch_hash_fails() { +fn validate_propagated_sorted_siloed_values_note_hashes_mismatch_sorted_hash_fails() { let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.append_note_hashes(2); @@ -42,6 +41,20 @@ fn validate_propagated_sorted_siloed_values_note_hashes_mismatch_hash_fails() { builder.validate(); } +#[test(should_fail_with="mismatch siloed note hashes")] +fn validate_propagated_sorted_siloed_values_note_hashes_mismatch_siloed_hash_fails() { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.previous_kernel.append_note_hashes(2); + builder.output.append_siloed_note_hashes(2); + + let mut hints = builder.get_previous_kernel_hints(); + // Tweak the hash in the hints. + hints.siloed_note_hashes[0] += 1; + + builder.validate_with_previous_kernel_hints(hints); +} + /** * nullifiers */ 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 8998a01e387..31d397eda2f 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 @@ -73,15 +73,3 @@ fn split_to_public_succeeds() { assert_array_eq(non_revertible.public_call_stack, [expected[0]]); assert_array_eq(revertible.public_call_stack, [expected[1], expected[2]]); } - -#[test(should_fail_with="min_revertible_side_effect_counter must not be 0")] -fn split_to_public_zero_counter_fails() { - let mut builder = FixtureBuilder::new(); - - builder.append_note_hashes(1); - - let _ = split_to_public( - builder.to_private_accumulated_data_builder(), - builder.min_revertible_side_effect_counter - ); -} 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 1a1f05e1893..d156f1175c7 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,4 +1,7 @@ -use crate::components::tail_to_public_output_validator::TailToPublicOutputValidator; +use crate::components::{ + previous_kernel_validator::previous_kernel_validator_hints::generate_previous_kernel_validator_hints, + tail_to_public_output_validator::TailToPublicOutputValidator +}; use dep::types::tests::fixture_builder::FixtureBuilder; struct TailToPublicOutputValidatorBuilder { @@ -20,7 +23,8 @@ impl TailToPublicOutputValidatorBuilder { let revertible = true; let output = self.output.to_public_kernel_circuit_public_inputs(revertible); let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); - TailToPublicOutputValidator::new(output, previous_kernel).validate(); + let previous_kernel_hints = generate_previous_kernel_validator_hints(previous_kernel); + TailToPublicOutputValidator::new(output, previous_kernel, previous_kernel_hints).validate(); } } 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 e8ed87e4582..6614b575118 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 @@ -6,7 +6,7 @@ use crate::{ use dep::types::{ abis::{ note_hash::ScopedNoteHash, nullifier::ScopedNullifier, - validation_requests::{ValidationRequests, ScopedKeyValidationRequestAndGenerator}, + validation_requests::{PrivateValidationRequests, ScopedKeyValidationRequestAndGenerator}, read_request::ScopedReadRequest }, constants::{ @@ -17,7 +17,7 @@ use dep::types::{ }; struct PrivateValidationRequestProcessor { - validation_requests: ValidationRequests, + validation_requests: PrivateValidationRequests, note_hash_read_request_hints: NoteHashReadRequestHints, pending_note_hashes: [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX], note_hash_tree_root: Field, @@ -25,24 +25,33 @@ struct PrivateValidationRequestProcessor PrivateValidationRequestProcessor { - pub fn validate(self) -> ValidationRequests { + pub fn validate(self) -> PrivateValidationRequests { let remaining_note_hash_read_requests = self.validate_note_hash_read_requests(); let remaining_nullifier_read_requests = self.validate_nullifier_read_requests(); let remaining_key_validation_requests = self.validate_keys(); - ValidationRequests { + PrivateValidationRequests { for_rollup: self.validation_requests.for_rollup, - nullifier_non_existent_read_requests: self.validation_requests.nullifier_non_existent_read_requests, - public_data_reads: self.validation_requests.public_data_reads, note_hash_read_requests: remaining_note_hash_read_requests.storage, nullifier_read_requests: remaining_nullifier_read_requests.storage, - scoped_key_validation_requests_and_generators: remaining_key_validation_requests.storage + scoped_key_validation_requests_and_generators: remaining_key_validation_requests.storage, + split_counter: Option::some(self.validate_split_counter()) } } + fn validate_split_counter(self) -> u32 { + if self.validation_requests.split_counter.is_some() { + assert_eq( + self.validation_requests.split_counter.unwrap_unchecked(), self.validation_requests_split_counter, "mismatch hinted split counter" + ); + } + self.validation_requests_split_counter + } + fn validate_note_hash_read_requests(self) -> BoundedVec { reset_read_requests( self.validation_requests.note_hash_read_requests, diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr index c0d9adf3313..75f0178153a 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr @@ -10,7 +10,7 @@ use crate::{ use dep::types::{ abis::{ kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, nullifier::Nullifier, - public_data_update_request::PublicDataUpdateRequest, validation_requests::ValidationRequests + public_data_update_request::PublicDataUpdateRequest, validation_requests::PublicValidationRequests }, data::public_data_hint::PublicDataHint, constants::{MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX}, @@ -19,7 +19,7 @@ use dep::types::{ }; struct PublicValidationRequestProcessor { - validation_requests: ValidationRequests, + validation_requests: PublicValidationRequests, pending_nullifiers: [Nullifier; MAX_NULLIFIERS_PER_TX], pending_public_data_writes: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], nullifier_read_request_hints: NullifierReadRequestHints, 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 84f175da5b6..7e8f1eb084f 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 @@ -5,7 +5,7 @@ use dep::types::{ traits::is_empty }; -pub fn verify_squashed_transient_data( +pub fn verify_squashed_transient_data( note_hashes: [ScopedNoteHash; NUM_NOTE_HASHES], nullifiers: [ScopedNullifier; NUM_NULLIFIERS], note_logs: [NoteLogHash; NUM_LOGS], @@ -14,7 +14,8 @@ pub fn verify_squashed_transient_data expected_note_logs: [NoteLogHash; NUM_LOGS], transient_nullifier_indexes_for_note_hashes: [u32; NUM_NOTE_HASHES], transient_note_hash_indexes_for_nullifiers: [u32; NUM_NULLIFIERS], - transient_or_propagated_note_hash_indexes_for_logs: [u32; NUM_LOGS] + transient_or_propagated_note_hash_indexes_for_logs: [u32; NUM_LOGS], + split_counter: u32 ) { let mut note_hashes_kept = 0; let mut note_hashes_removed = 0; @@ -26,6 +27,15 @@ pub fn verify_squashed_transient_data note_hashes_kept += 1; } else { let nullifier = nullifiers[nullifier_index]; + assert( + nullifier.counter() > note_hash.counter(), "Cannot nullify a note hash created afterwards" + ); + if nullifier.counter() >= split_counter { + assert( + note_hash.counter() >= split_counter, "Cannot squash a non-revertible note hash with a revertible nullifier" + ); + // Since the nullifier counter must be larger than the note hash counter, it's not possible to squash a revertible note hash with a non-revertible nullifier. + } assert_eq( note_hash.value(), nullifier.nullified_note_hash(), "Value of the hinted transient note hash does not match" ); @@ -107,7 +117,7 @@ mod tests { global contract_address = AztecAddress::from_field(987654); - struct TestDataBuilder { + struct TestDataBuilder { note_hashes: [ScopedNoteHash; NUM_NOTE_HASHES], nullifiers: [ScopedNullifier; NUM_NULLIFIERS], note_logs: [NoteLogHash; NUM_LOGS], @@ -116,10 +126,11 @@ mod tests { expected_note_logs: [NoteLogHash; NUM_LOGS], transient_nullifier_indexes_for_note_hashes: [u32; NUM_NOTE_HASHES], transient_note_hash_indexes_for_nullifiers: [u32; NUM_NULLIFIERS], - transient_or_propagated_note_hash_indexes_for_logs: [u32; NUM_LOGS] + transient_or_propagated_note_hash_indexes_for_logs: [u32; NUM_LOGS], + split_counter: u32, } - impl TestDataBuilder { + impl TestDataBuilder { pub fn new() -> TestDataBuilder<5, 4, 3> { let note_hashes = [ NoteHash { value: 11, counter: 100 }.scope(contract_address), @@ -162,7 +173,8 @@ mod tests { expected_note_logs, transient_nullifier_indexes_for_note_hashes, transient_note_hash_indexes_for_nullifiers, - transient_or_propagated_note_hash_indexes_for_logs + transient_or_propagated_note_hash_indexes_for_logs, + split_counter: 0 } } @@ -204,7 +216,8 @@ mod tests { expected_note_logs, transient_nullifier_indexes_for_note_hashes, transient_note_hash_indexes_for_nullifiers, - transient_or_propagated_note_hash_indexes_for_logs + transient_or_propagated_note_hash_indexes_for_logs, + split_counter: 0 } } @@ -245,7 +258,8 @@ mod tests { expected_note_logs, transient_nullifier_indexes_for_note_hashes, transient_note_hash_indexes_for_nullifiers, - transient_or_propagated_note_hash_indexes_for_logs + transient_or_propagated_note_hash_indexes_for_logs, + split_counter: 0 } } @@ -259,7 +273,8 @@ mod tests { self.expected_note_logs, self.transient_nullifier_indexes_for_note_hashes, self.transient_note_hash_indexes_for_nullifiers, - self.transient_or_propagated_note_hash_indexes_for_logs + self.transient_or_propagated_note_hash_indexes_for_logs, + self.split_counter ); } } @@ -379,6 +394,28 @@ mod tests { builder.verify(); } + #[test(should_fail_with="Cannot nullify a note hash created afterwards")] + fn fails_nullify_note_hash_emitted_afterwards() { + let mut builder = TestDataBuilder::new(); + + // Make the nullifier at index 1 to have a smaller counter than its note hash. + let note_hash_counter = builder.note_hashes[builder.transient_note_hash_indexes_for_nullifiers[1]].counter(); + builder.nullifiers[1].nullifier.counter = note_hash_counter - 1; + + builder.verify(); + } + + #[test(should_fail_with="Cannot squash a non-revertible note hash with a revertible nullifier")] + fn fails_nullify_non_revertible_note_hash_with_revertible_nullifier() { + let mut builder = TestDataBuilder::new(); + + let note_hash_counter = builder.note_hashes[builder.transient_note_hash_indexes_for_nullifiers[1]].counter(); + // Make the note hash non-revertible. + builder.split_counter = note_hash_counter + 1; + + builder.verify(); + } + #[test(should_fail_with="Empty log must be padded to the right")] fn fails_unexpected_log_value() { let mut builder = TestDataBuilder::new_clear_all(); 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 734902e1666..525aaba4dc2 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 @@ -1,6 +1,6 @@ use crate::abis::{ accumulated_data::PrivateAccumulatedData, combined_constant_data::CombinedConstantData, - public_call_request::PublicCallRequest, validation_requests::ValidationRequests + public_call_request::PublicCallRequest, validation_requests::PrivateValidationRequests }; use crate::constants::PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH; use crate::traits::{Serialize, Deserialize, Eq, Empty}; @@ -73,7 +73,7 @@ impl Eq for PrivateKernelCircuitPublicInputsArrayLengths { struct PrivateKernelCircuitPublicInputs { min_revertible_side_effect_counter: u32, - validation_requests: ValidationRequests, + validation_requests: PrivateValidationRequests, end: PrivateAccumulatedData, constants: CombinedConstantData, public_teardown_call_request: PublicCallRequest, @@ -102,7 +102,7 @@ impl Deserialize for PrivateKernelC let mut reader = Reader::new(fields); let item = Self { min_revertible_side_effect_counter: reader.read() as u32, - validation_requests: reader.read_struct(ValidationRequests::deserialize), + validation_requests: reader.read_struct(PrivateValidationRequests::deserialize), end: reader.read_struct(PrivateAccumulatedData::deserialize), constants: reader.read_struct(CombinedConstantData::deserialize), public_teardown_call_request: reader.read_struct(PublicCallRequest::deserialize), @@ -128,7 +128,7 @@ impl Empty for PrivateKernelCircuitPublicInputs { fn empty() -> Self { Self { min_revertible_side_effect_counter: 0, - validation_requests: ValidationRequests::empty(), + validation_requests: PrivateValidationRequests::empty(), end: PrivateAccumulatedData::empty(), constants: CombinedConstantData::empty(), public_teardown_call_request: PublicCallRequest::empty(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs_builder.nr index fc1d57fd1c9..add7c553b6e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs_builder.nr @@ -2,15 +2,14 @@ use crate::{ abis::{ accumulated_data::PrivateAccumulatedDataBuilder, combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::private_kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, - public_call_request::PublicCallRequest, - validation_requests::validation_requests_builder::ValidationRequestsBuilder + public_call_request::PublicCallRequest, validation_requests::PrivateValidationRequestsBuilder }, address::AztecAddress, traits::Empty }; struct PrivateKernelCircuitPublicInputsBuilder { min_revertible_side_effect_counter: u32, - validation_requests: ValidationRequestsBuilder, + validation_requests: PrivateValidationRequestsBuilder, end: PrivateAccumulatedDataBuilder, constants: CombinedConstantData, public_teardown_call_request: PublicCallRequest, @@ -34,7 +33,7 @@ impl Empty for PrivateKernelCircuitPublicInputsBuilder { fn empty() -> Self { PrivateKernelCircuitPublicInputsBuilder { min_revertible_side_effect_counter: 0, - validation_requests: ValidationRequestsBuilder::empty(), + validation_requests: PrivateValidationRequestsBuilder::empty(), end: PrivateAccumulatedDataBuilder::empty(), constants: CombinedConstantData::empty(), public_teardown_call_request: PublicCallRequest::empty(), 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 398013a1988..1755db26a0f 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 @@ -1,7 +1,7 @@ use crate::abis::{ accumulated_data::PublicAccumulatedData, combined_constant_data::CombinedConstantData, public_call_request::PublicCallRequest, - validation_requests::{RollupValidationRequests, ValidationRequests} + validation_requests::{RollupValidationRequests, PublicValidationRequests} }; use crate::constants::{MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH}; use crate::traits::{Empty, Serialize, Deserialize, Eq}; @@ -9,7 +9,7 @@ use crate::utils::reader::Reader; use crate::address::AztecAddress; struct PublicKernelCircuitPublicInputs { - validation_requests: ValidationRequests, + validation_requests: PublicValidationRequests, end_non_revertible: PublicAccumulatedData, end: PublicAccumulatedData, constants: CombinedConstantData, @@ -40,7 +40,7 @@ impl PublicKernelCircuitPublicInputs { impl Empty for PublicKernelCircuitPublicInputs { fn empty() -> Self { PublicKernelCircuitPublicInputs { - validation_requests: ValidationRequests::empty(), + validation_requests: PublicValidationRequests::empty(), end_non_revertible: PublicAccumulatedData::empty(), end: PublicAccumulatedData::empty(), constants: CombinedConstantData::empty(), @@ -79,7 +79,7 @@ impl Deserialize for PublicKernelCir let mut reader = Reader::new(fields); let item = PublicKernelCircuitPublicInputs { - validation_requests: reader.read_struct(ValidationRequests::deserialize), + validation_requests: reader.read_struct(PublicValidationRequests::deserialize), end_non_revertible: reader.read_struct(PublicAccumulatedData::deserialize), end: reader.read_struct(PublicAccumulatedData::deserialize), constants: reader.read_struct(CombinedConstantData::deserialize), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr index 697d278015a..3f1d8e029f6 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr @@ -3,13 +3,13 @@ use crate::{ accumulated_data::{CombinedAccumulatedData, PublicAccumulatedDataBuilder}, combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::{public_kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs}, - public_call_request::PublicCallRequest, validation_requests::ValidationRequestsBuilder + public_call_request::PublicCallRequest, validation_requests::PublicValidationRequestsBuilder }, address::AztecAddress, constants::MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, traits::Empty }; struct PublicKernelCircuitPublicInputsBuilder { - validation_requests: ValidationRequestsBuilder, + validation_requests: PublicValidationRequestsBuilder, end_non_revertible: PublicAccumulatedDataBuilder, end: PublicAccumulatedDataBuilder, constants: CombinedConstantData, @@ -38,7 +38,7 @@ impl PublicKernelCircuitPublicInputsBuilder { impl Empty for PublicKernelCircuitPublicInputsBuilder { fn empty() -> Self { PublicKernelCircuitPublicInputsBuilder { - validation_requests: ValidationRequestsBuilder::empty(), + validation_requests: PublicValidationRequestsBuilder::empty(), end_non_revertible: PublicAccumulatedDataBuilder::empty(), end: PublicAccumulatedDataBuilder::empty(), constants: CombinedConstantData::empty(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/mod.nr similarity index 50% rename from noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/mod.nr index 88760779181..74eaf16f8bb 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/mod.nr @@ -1,13 +1,17 @@ -mod validation_requests; -mod validation_requests_builder; -mod rollup_validation_requests; 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; -use validation_requests::ValidationRequests; -use validation_requests_builder::ValidationRequestsBuilder; -use rollup_validation_requests::RollupValidationRequests; use key_validation_request::KeyValidationRequest; use key_validation_request_and_generator::KeyValidationRequestAndGenerator; +use private_validation_requests::PrivateValidationRequests; +use private_validation_requests_builder::PrivateValidationRequestsBuilder; +use public_validation_requests::PublicValidationRequests; +use public_validation_requests_builder::PublicValidationRequestsBuilder; +use rollup_validation_requests::RollupValidationRequests; use scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/private_validation_requests.nr similarity index 56% rename from noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/private_validation_requests.nr index d6fc581fe26..45213a9a857 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/private_validation_requests.nr @@ -1,6 +1,6 @@ use crate::{ abis::{ - max_block_number::MaxBlockNumber, public_data_read::PublicDataRead, read_request::ScopedReadRequest, + read_request::ScopedReadRequest, validation_requests::{ rollup_validation_requests::RollupValidationRequests, scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator @@ -8,25 +8,22 @@ use crate::{ }, constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, - MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_READS_PER_TX, VALIDATION_REQUESTS_LENGTH + MAX_KEY_VALIDATION_REQUESTS_PER_TX, PRIVATE_VALIDATION_REQUESTS_LENGTH }, traits::{Serialize, Deserialize, Empty}, utils::reader::Reader }; -// TODO - Use specific structs for private and public: PrivateValidationRequests vs PublicValidationRequests -struct ValidationRequests { +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], - nullifier_non_existent_read_requests: [ScopedReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX], scoped_key_validation_requests_and_generators: [ScopedKeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_TX], - public_data_reads: [PublicDataRead; MAX_PUBLIC_DATA_READS_PER_TX], + split_counter: Option, } -impl Serialize for ValidationRequests { - fn serialize(self) -> [Field; VALIDATION_REQUESTS_LENGTH] { - let mut fields: BoundedVec = BoundedVec::new(); +impl Serialize for PrivateValidationRequests { + fn serialize(self) -> [Field; PRIVATE_VALIDATION_REQUESTS_LENGTH] { + let mut fields: BoundedVec = BoundedVec::new(); fields.extend_from_array(self.for_rollup.serialize()); @@ -38,35 +35,28 @@ impl Serialize for ValidationRequests { fields.extend_from_array(self.nullifier_read_requests[i].serialize()); } - for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX { - fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize()); - } - for i in 0..MAX_KEY_VALIDATION_REQUESTS_PER_TX { fields.extend_from_array(self.scoped_key_validation_requests_and_generators[i].serialize()); } - for i in 0..MAX_PUBLIC_DATA_READS_PER_TX { - fields.extend_from_array(self.public_data_reads[i].serialize()); - } + fields.push(self.split_counter.is_some() as Field); + fields.push(self.split_counter.unwrap_unchecked() as Field); - assert_eq(fields.len(), VALIDATION_REQUESTS_LENGTH); + assert_eq(fields.len(), PRIVATE_VALIDATION_REQUESTS_LENGTH); fields.storage } } -impl Deserialize for ValidationRequests { - fn deserialize(serialized: [Field; VALIDATION_REQUESTS_LENGTH]) -> Self { - // TODO(#4390): This should accept a reader ^ to avoid copying data. +impl Deserialize for PrivateValidationRequests { + fn deserialize(serialized: [Field; PRIVATE_VALIDATION_REQUESTS_LENGTH]) -> Self { let mut reader = Reader::new(serialized); let item = Self { for_rollup: reader.read_struct(RollupValidationRequests::deserialize), note_hash_read_requests: reader.read_struct_array(ScopedReadRequest::deserialize, [ScopedReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_TX]), nullifier_read_requests: reader.read_struct_array(ScopedReadRequest::deserialize, [ScopedReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_TX]), - nullifier_non_existent_read_requests: reader.read_struct_array(ScopedReadRequest::deserialize, [ScopedReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX]), scoped_key_validation_requests_and_generators: reader.read_struct_array(ScopedKeyValidationRequestAndGenerator::deserialize, [ScopedKeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_TX]), - public_data_reads: reader.read_struct_array(PublicDataRead::deserialize, [PublicDataRead::empty(); MAX_PUBLIC_DATA_READS_PER_TX]), + split_counter: Option { _is_some: reader.read_bool(), _value: reader.read_u32() } }; reader.finish(); @@ -74,35 +64,32 @@ impl Deserialize for ValidationRequests { } } -impl Empty for ValidationRequests { +impl Empty for PrivateValidationRequests { fn empty() -> Self { - - ValidationRequests { + PrivateValidationRequests { for_rollup: RollupValidationRequests::empty(), note_hash_read_requests: [ScopedReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_TX], nullifier_read_requests: [ScopedReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_TX], - nullifier_non_existent_read_requests: [ScopedReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX], scoped_key_validation_requests_and_generators: [ScopedKeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_TX], - public_data_reads: [PublicDataRead::empty(); MAX_PUBLIC_DATA_READS_PER_TX], + split_counter: Option::none(), } } } -impl Eq for ValidationRequests { +impl Eq for PrivateValidationRequests { fn eq(self, other: Self) -> bool { (self.for_rollup.eq(other.for_rollup)) & (self.note_hash_read_requests == other.note_hash_read_requests) & (self.nullifier_read_requests == other.nullifier_read_requests) & - (self.nullifier_non_existent_read_requests == other.nullifier_non_existent_read_requests) & (self.scoped_key_validation_requests_and_generators == other.scoped_key_validation_requests_and_generators) & - (self.public_data_reads == other.public_data_reads) + (self.split_counter == other.split_counter) } } #[test] fn serialization_of_empty() { - let item = ValidationRequests::empty(); + let item = PrivateValidationRequests::empty(); let serialized = item.serialize(); - let deserialized = ValidationRequests::deserialize(serialized); + let deserialized = PrivateValidationRequests::deserialize(serialized); assert(item.eq(deserialized)); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/private_validation_requests_builder.nr similarity index 53% rename from noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests_builder.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/private_validation_requests_builder.nr index bc297cc8516..227cd34a594 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/validation_requests_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/private_validation_requests_builder.nr @@ -1,54 +1,51 @@ use crate::{ abis::{ - max_block_number::MaxBlockNumber, public_data_read::PublicDataRead, read_request::ScopedReadRequest, + max_block_number::MaxBlockNumber, read_request::ScopedReadRequest, validation_requests::{ - validation_requests::ValidationRequests, rollup_validation_requests::RollupValidationRequests, + private_validation_requests::PrivateValidationRequests, + rollup_validation_requests::RollupValidationRequests, scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator } }, constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, - MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_READS_PER_TX + MAX_KEY_VALIDATION_REQUESTS_PER_TX }, traits::Empty }; -struct ValidationRequestsBuilder { +struct PrivateValidationRequestsBuilder { max_block_number: MaxBlockNumber, note_hash_read_requests: BoundedVec, nullifier_read_requests: BoundedVec, - nullifier_non_existent_read_requests: BoundedVec, scoped_key_validation_requests_and_generators: BoundedVec, - public_data_reads: BoundedVec, + split_counter: Option, } -impl ValidationRequestsBuilder { - pub fn finish(self) -> ValidationRequests { - ValidationRequests { - for_rollup: self.to_rollup(), +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, - nullifier_non_existent_read_requests: self.nullifier_non_existent_read_requests.storage, scoped_key_validation_requests_and_generators: self.scoped_key_validation_requests_and_generators.storage, - public_data_reads: self.public_data_reads.storage + split_counter: self.split_counter } } - pub fn to_rollup(self) -> RollupValidationRequests { + pub fn for_rollup(self) -> RollupValidationRequests { RollupValidationRequests { max_block_number: self.max_block_number } } } -impl Empty for ValidationRequestsBuilder { +impl Empty for PrivateValidationRequestsBuilder { fn empty() -> Self { - ValidationRequestsBuilder { + PrivateValidationRequestsBuilder { max_block_number: MaxBlockNumber::empty(), note_hash_read_requests: BoundedVec::new(), nullifier_read_requests: BoundedVec::new(), - nullifier_non_existent_read_requests: BoundedVec::new(), scoped_key_validation_requests_and_generators: BoundedVec::new(), - public_data_reads: BoundedVec::new(), + split_counter: Option::none(), } } } 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 new file mode 100644 index 00000000000..4def172e8ec --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/public_validation_requests.nr @@ -0,0 +1,86 @@ +use crate::{ + abis::{ + public_data_read::PublicDataRead, read_request::ScopedReadRequest, + validation_requests::{rollup_validation_requests::RollupValidationRequests} +}, + constants::{ + MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, + MAX_PUBLIC_DATA_READS_PER_TX, PUBLIC_VALIDATION_REQUESTS_LENGTH +}, + traits::{Serialize, Deserialize, Empty}, utils::reader::Reader +}; + +struct PublicValidationRequests { + for_rollup: RollupValidationRequests, + nullifier_read_requests: [ScopedReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_TX], + nullifier_non_existent_read_requests: [ScopedReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX], + public_data_reads: [PublicDataRead; MAX_PUBLIC_DATA_READS_PER_TX], +} + +impl Serialize for PublicValidationRequests { + fn serialize(self) -> [Field; PUBLIC_VALIDATION_REQUESTS_LENGTH] { + let mut fields: BoundedVec = BoundedVec::new(); + + fields.extend_from_array(self.for_rollup.serialize()); + + for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_TX { + fields.extend_from_array(self.nullifier_read_requests[i].serialize()); + } + + for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX { + fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize()); + } + + for i in 0..MAX_PUBLIC_DATA_READS_PER_TX { + fields.extend_from_array(self.public_data_reads[i].serialize()); + } + + assert_eq(fields.len(), PUBLIC_VALIDATION_REQUESTS_LENGTH); + + fields.storage + } +} + +impl Deserialize for PublicValidationRequests { + fn deserialize(serialized: [Field; PUBLIC_VALIDATION_REQUESTS_LENGTH]) -> Self { + // TODO(#4390): This should accept a reader ^ to avoid copying data. + let mut reader = Reader::new(serialized); + let item = Self { + for_rollup: reader.read_struct(RollupValidationRequests::deserialize), + nullifier_read_requests: reader.read_struct_array(ScopedReadRequest::deserialize, [ScopedReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_TX]), + nullifier_non_existent_read_requests: reader.read_struct_array(ScopedReadRequest::deserialize, [ScopedReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX]), + public_data_reads: reader.read_struct_array(PublicDataRead::deserialize, [PublicDataRead::empty(); MAX_PUBLIC_DATA_READS_PER_TX]), + }; + + reader.finish(); + item + } +} + +impl Empty for PublicValidationRequests { + fn empty() -> Self { + PublicValidationRequests { + for_rollup: RollupValidationRequests::empty(), + nullifier_read_requests: [ScopedReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_TX], + nullifier_non_existent_read_requests: [ScopedReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX], + public_data_reads: [PublicDataRead::empty(); MAX_PUBLIC_DATA_READS_PER_TX], + } + } +} + +impl Eq for PublicValidationRequests { + fn eq(self, other: Self) -> bool { + (self.for_rollup.eq(other.for_rollup)) & + (self.nullifier_read_requests == other.nullifier_read_requests) & + (self.nullifier_non_existent_read_requests == other.nullifier_non_existent_read_requests) & + (self.public_data_reads == other.public_data_reads) + } +} + +#[test] +fn serialization_of_empty() { + let item = PublicValidationRequests::empty(); + let serialized = item.serialize(); + let deserialized = PublicValidationRequests::deserialize(serialized); + assert(item.eq(deserialized)); +} 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 new file mode 100644 index 00000000000..c05b4339886 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/public_validation_requests_builder.nr @@ -0,0 +1,47 @@ +use crate::{ + abis::{ + max_block_number::MaxBlockNumber, public_data_read::PublicDataRead, read_request::ScopedReadRequest, + validation_requests::{ + public_validation_requests::PublicValidationRequests, + rollup_validation_requests::RollupValidationRequests +} +}, + constants::{ + MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, + MAX_PUBLIC_DATA_READS_PER_TX +}, + traits::Empty +}; + +struct PublicValidationRequestsBuilder { + max_block_number: MaxBlockNumber, + nullifier_read_requests: BoundedVec, + nullifier_non_existent_read_requests: BoundedVec, + public_data_reads: BoundedVec, +} + +impl PublicValidationRequestsBuilder { + pub fn finish(self) -> PublicValidationRequests { + PublicValidationRequests { + for_rollup: self.for_rollup(), + 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 + } + } + + pub fn for_rollup(self) -> RollupValidationRequests { + RollupValidationRequests { max_block_number: self.max_block_number } + } +} + +impl Empty for PublicValidationRequestsBuilder { + fn empty() -> Self { + PublicValidationRequestsBuilder { + max_block_number: MaxBlockNumber::empty(), + nullifier_read_requests: BoundedVec::new(), + nullifier_non_existent_read_requests: BoundedVec::new(), + public_data_reads: BoundedVec::new(), + } + } +} 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 b788d2e8cb6..4d82d22f457 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -236,17 +236,18 @@ global AGGREGATION_OBJECT_LENGTH: u32 = 16; global SCOPED_READ_REQUEST_LEN = READ_REQUEST_LENGTH + 1; global PUBLIC_DATA_READ_LENGTH = 2; -global VALIDATION_REQUESTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + (SCOPED_READ_REQUEST_LEN * MAX_NOTE_HASH_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX) + (SCOPED_KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH * MAX_KEY_VALIDATION_REQUESTS_PER_TX) + (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX); +global PRIVATE_VALIDATION_REQUESTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + (SCOPED_READ_REQUEST_LEN * MAX_NOTE_HASH_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_READ_REQUESTS_PER_TX) + (SCOPED_KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH * MAX_KEY_VALIDATION_REQUESTS_PER_TX) + 2; +global PUBLIC_VALIDATION_REQUESTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX) + (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX); global PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; global COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NOTE_HASHES_PER_TX + MAX_NULLIFIERS_PER_TX + MAX_L2_TO_L1_MSGS_PER_TX + 5 + (MAX_UNENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; global COMBINED_CONSTANT_DATA_LENGTH = HEADER_LENGTH + TX_CONTEXT_LENGTH + GLOBAL_VARIABLES_LENGTH + 1; global PRIVATE_ACCUMULATED_DATA_LENGTH = (SCOPED_NOTE_HASH_LENGTH * MAX_NOTE_HASHES_PER_TX) + (SCOPED_NULLIFIER_LENGTH * MAX_NULLIFIERS_PER_TX) + (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) + (PRIVATE_CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + (PUBLIC_CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX); -global PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1 + VALIDATION_REQUESTS_LENGTH + PRIVATE_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + PUBLIC_CALL_REQUEST_LENGTH + AZTEC_ADDRESS_LENGTH; +global PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1 + PRIVATE_VALIDATION_REQUESTS_LENGTH + PRIVATE_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + PUBLIC_CALL_REQUEST_LENGTH + AZTEC_ADDRESS_LENGTH; global PUBLIC_ACCUMULATED_DATA_LENGTH = (MAX_NOTE_HASHES_PER_TX * NOTE_HASH_LENGTH) + (MAX_NULLIFIERS_PER_TX * NULLIFIER_LENGTH) + (MAX_L2_TO_L1_MSGS_PER_TX * 1) + (MAX_NOTE_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_UNENCRYPTED_LOGS_PER_TX * SCOPED_LOG_HASH_LENGTH) + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * PUBLIC_CALL_REQUEST_LENGTH) + GAS_LENGTH; -global PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = VALIDATION_REQUESTS_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + 1 + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * PUBLIC_CALL_REQUEST_LENGTH) + AZTEC_ADDRESS_LENGTH; +global PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = PUBLIC_VALIDATION_REQUESTS_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + 1 + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * PUBLIC_CALL_REQUEST_LENGTH) + AZTEC_ADDRESS_LENGTH; global KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + COMBINED_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + 1 + AZTEC_ADDRESS_LENGTH; 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 3bf793b4def..fe91c1faa33 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 @@ -18,8 +18,8 @@ use crate::{ public_data_update_request::PublicDataUpdateRequest, read_request::{ReadRequest, ScopedReadRequest}, log_hash::{LogHash, NoteLogHash, ScopedLogHash, EncryptedLogHash, ScopedEncryptedLogHash}, validation_requests::{ - ValidationRequests, ValidationRequestsBuilder, KeyValidationRequest, - KeyValidationRequestAndGenerator, ScopedKeyValidationRequestAndGenerator + KeyValidationRequest, KeyValidationRequestAndGenerator, PrivateValidationRequests, + PublicValidationRequests, RollupValidationRequests, ScopedKeyValidationRequestAndGenerator } }, address::{AztecAddress, EthAddress, SaltedInitializationHash, PublicKeysHash}, @@ -108,6 +108,7 @@ struct FixtureBuilder { nullifier_non_existent_read_requests: BoundedVec, scoped_key_validation_requests_and_generators: BoundedVec, public_data_reads: BoundedVec, + validation_requests_split_counter: Option, // Function. function_data: FunctionData, @@ -377,21 +378,19 @@ impl FixtureBuilder { } } - pub fn to_validation_requests(self) -> ValidationRequests { - let validation_requests = ValidationRequestsBuilder { - max_block_number: self.max_block_number, - note_hash_read_requests: self.note_hash_read_requests, - nullifier_read_requests: self.nullifier_read_requests, - nullifier_non_existent_read_requests: self.nullifier_non_existent_read_requests, - scoped_key_validation_requests_and_generators: self.scoped_key_validation_requests_and_generators, - public_data_reads: self.public_data_reads - }; - validation_requests.finish() + 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, + scoped_key_validation_requests_and_generators: self.scoped_key_validation_requests_and_generators.storage, + split_counter: self.validation_requests_split_counter + } } pub fn to_private_kernel_circuit_public_inputs(self) -> PrivateKernelCircuitPublicInputs { let end = self.to_private_accumulated_data(); - let validation_requests = self.to_validation_requests(); + let validation_requests = self.to_private_validation_requests(); let constants = self.to_constant_data(); let public_teardown_call_request = self.public_teardown_call_stack.get_unchecked(0); @@ -410,6 +409,15 @@ impl FixtureBuilder { PrivateKernelData { public_inputs, vk: self.vk, vk_index: self.vk_index, vk_path: self.vk_path } } + pub fn to_public_validation_requests(self) -> PublicValidationRequests { + PublicValidationRequests { + for_rollup: self.to_rollup_validation_requests(), + 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 + } + } + pub fn to_public_kernel_circuit_public_inputs(self, revertible: bool) -> PublicKernelCircuitPublicInputs { // TODO: Split the data using self.min_revertible_side_effect_counter. let accumulated_data = self.to_public_accumulated_data(); @@ -423,7 +431,7 @@ impl FixtureBuilder { } else { PublicAccumulatedData::empty() }; - let validation_requests = self.to_validation_requests(); + let validation_requests = self.to_public_validation_requests(); let constants = self.to_constant_data(); PublicKernelCircuitPublicInputs { @@ -442,8 +450,12 @@ impl FixtureBuilder { PublicKernelData { public_inputs, proof: self.proof, vk: self.vk, vk_index: self.vk_index, vk_path: self.vk_path } } + pub fn to_rollup_validation_requests(self) -> RollupValidationRequests { + RollupValidationRequests { max_block_number: self.max_block_number } + } + pub fn to_kernel_circuit_public_inputs(self) -> KernelCircuitPublicInputs { - let rollup_validation_requests = self.to_validation_requests().for_rollup; + let rollup_validation_requests = self.to_rollup_validation_requests(); let end = self.to_combined_accumulated_data(); let constants = self.to_constant_data(); @@ -526,6 +538,12 @@ impl FixtureBuilder { ); } + pub fn add_nullifier_for_note_hash(&mut self, value: Field, note_hash: Field) { + self.nullifiers.push( + Nullifier { value, counter: self.next_counter(), note_hash }.scope(self.storage_contract_address) + ); + } + pub fn add_siloed_nullifier(&mut self, value: Field) { let siloed_value = compute_siloed_nullifier(self.storage_contract_address, value); self.add_nullifier(siloed_value); @@ -1029,6 +1047,7 @@ impl Empty for FixtureBuilder { nullifier_non_existent_read_requests: BoundedVec::new(), scoped_key_validation_requests_and_generators: BoundedVec::new(), public_data_reads: BoundedVec::new(), + validation_requests_split_counter: Option::none(), function_data: FunctionData::empty(), args_hash: 0, returns_hash: 0, diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 62caab71d9e..70b29599f24 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -165,14 +165,15 @@ export const PUBLIC_CONTEXT_INPUTS_LENGTH = 40; export const AGGREGATION_OBJECT_LENGTH = 16; export const SCOPED_READ_REQUEST_LEN = 3; export const PUBLIC_DATA_READ_LENGTH = 2; -export const VALIDATION_REQUESTS_LENGTH = 1090; +export const PRIVATE_VALIDATION_REQUESTS_LENGTH = 772; +export const PUBLIC_VALIDATION_REQUESTS_LENGTH = 514; export const PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; export const COMBINED_ACCUMULATED_DATA_LENGTH = 364; export const COMBINED_CONSTANT_DATA_LENGTH = 41; export const PRIVATE_ACCUMULATED_DATA_LENGTH = 1336; -export const PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2483; +export const PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2165; export const PUBLIC_ACCUMULATED_DATA_LENGTH = 1215; -export const PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 4011; +export const PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 3435; export const KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 415; export const CONSTANT_ROLLUP_DATA_LENGTH = 11; export const BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 28; diff --git a/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts b/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts index 933c377636e..44cfd0ba60b 100644 --- a/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_transient_data_hints.test.ts @@ -20,6 +20,15 @@ describe('buildTransientDataHints', () => { let futureNullifierReads: ScopedReadRequest[]; let noteHashNullifierCounterMap: Map; + const buildHints = () => + buildTransientDataHints( + noteHashes, + nullifiers, + futureNoteHashReads, + futureNullifierReads, + noteHashNullifierCounterMap, + ); + beforeEach(() => { noteHashes = [ new NoteHash(new Fr(11), 100).scope(contractAddress), @@ -37,20 +46,21 @@ describe('buildTransientDataHints', () => { futureNoteHashReads = [new ScopedReadRequest(new ReadRequest(new Fr(44), 351), contractAddress)]; futureNullifierReads = [new ScopedReadRequest(new ReadRequest(new Fr(66), 502), contractAddress)]; noteHashNullifierCounterMap = new Map(); - noteHashNullifierCounterMap.set(100, 700); // Linked to a nullifier. - noteHashNullifierCounterMap.set(300, 500); // Linked to a nullifier that will be read. - noteHashNullifierCounterMap.set(350, 600); // Linked to a nullifier, but the note hash will be read. - noteHashNullifierCounterMap.set(375, 800); // Linked to a nullifier not yet known. + noteHashNullifierCounterMap.set(100, 700); + noteHashNullifierCounterMap.set(300, 500); + noteHashNullifierCounterMap.set(350, 600); + noteHashNullifierCounterMap.set(375, 800); + /** + * nullifiers[0] not nullifying any note hashes. + * nullifiers[1] <> noteHashes[2], nullifier is read. + * nullifiers[2] <> noteHashes[3], note hash is read. + * nullifiers[3] <> noteHashes[0]. + * noteHashes[1] and noteHashes[4] not being nullified. + */ }); it('builds index hints that link transient note hashes and nullifiers', () => { - const [nullifierIndexes, noteHashIndexesForNullifiers] = buildTransientDataHints( - noteHashes, - nullifiers, - futureNoteHashReads, - futureNullifierReads, - noteHashNullifierCounterMap, - ); + const [nullifierIndexes, noteHashIndexesForNullifiers] = buildHints(); // Only first one is squashed, since: // second one is not linked to a nullifier // third one's nullifier will be read @@ -59,17 +69,21 @@ describe('buildTransientDataHints', () => { expect(noteHashIndexesForNullifiers).toEqual([5, 5, 5, 0]); }); - it('throws if note hash does not match', () => { - nullifiers[1].nullifier.noteHash = new Fr(11); - expect(() => buildTransientDataHints(noteHashes, nullifiers, [], [], noteHashNullifierCounterMap)).toThrow( - 'Hinted note hash does not match.', - ); + it('keeps the pair if note hash does not match', () => { + nullifiers[3].nullifier.noteHash = new Fr(9999); + const [nullifierIndexes, noteHashIndexesForNullifiers] = buildHints(); + expect(nullifierIndexes).toEqual([4, 4, 4, 4, 4]); + expect(noteHashIndexesForNullifiers).toEqual([5, 5, 5, 5]); }); it('throws if contract address does not match', () => { - nullifiers[1].contractAddress = AztecAddress.fromBigInt(123456n); - expect(() => buildTransientDataHints(noteHashes, nullifiers, [], [], noteHashNullifierCounterMap)).toThrow( - 'Contract address of hinted note hash does not match.', - ); + nullifiers[3].contractAddress = AztecAddress.fromBigInt(123456n); + expect(buildHints).toThrow('Contract address of hinted note hash does not match.'); + }); + + it('throws if note hash counter is larger than nullifier counter', () => { + nullifiers[3].nullifier.counter = noteHashes[0].counter - 1; + noteHashNullifierCounterMap.set(noteHashes[0].counter, noteHashes[0].counter - 1); + expect(buildHints).toThrow('Hinted nullifier has smaller counter than note hash.'); }); }); diff --git a/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts b/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts index 99daa29e7d1..97bb8cd9735 100644 --- a/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts +++ b/yarn-project/circuits.js/src/hints/build_transient_data_hints.ts @@ -55,14 +55,21 @@ export function buildTransientDataHints isValidNullifierReadRequest(read, nullifier))) { continue; diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index be0313852e2..5b03befe974 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -45,6 +45,7 @@ export * from './membership_witness.js'; export * from './non_existent_read_request_hints.js'; export * from './note_hash.js'; export * from './nullifier.js'; +export * from './optional_number.js'; export * from './parity/base_parity_inputs.js'; export * from './parity/parity_public_inputs.js'; export * from './parity/root_parity_input.js'; @@ -53,6 +54,7 @@ export * from './partial_state_reference.js'; export * from './private_call_request.js'; export * from './private_call_stack_item.js'; export * from './private_circuit_public_inputs.js'; +export * from './private_validation_requests.js'; export * from './proof.js'; export * from './public_call_request.js'; export * from './public_call_stack_item.js'; @@ -62,6 +64,7 @@ export * from './public_data_hint.js'; export * from './public_data_read_request.js'; export * from './public_data_read_request_hints.js'; export * from './public_data_update_request.js'; +export * from './public_validation_requests.js'; export * from './read_request.js'; export * from './read_request_hints/index.js'; export * from './recursive_proof.js'; @@ -81,7 +84,6 @@ export * from './state_reference.js'; export * from './trees/index.js'; export * from './tx_context.js'; export * from './tx_request.js'; -export * from './validation_requests.js'; export * from './verification_key.js'; export { EventSelector, FunctionSelector } from '@aztec/foundation/abi'; diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_circuit_public_inputs.ts index 25d85d9031b..d6c521f317a 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_circuit_public_inputs.ts @@ -2,8 +2,8 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { PrivateValidationRequests } from '../private_validation_requests.js'; import { PublicCallRequest } from '../public_call_request.js'; -import { ValidationRequests } from '../validation_requests.js'; import { CombinedConstantData } from './combined_constant_data.js'; import { PrivateAccumulatedData } from './private_accumulated_data.js'; @@ -19,7 +19,7 @@ export class PrivateKernelCircuitPublicInputs { /** * Validation requests accumulated from public functions. */ - public validationRequests: ValidationRequests, + public validationRequests: PrivateValidationRequests, /** * Data accumulated from both public and private circuits. */ @@ -58,7 +58,7 @@ export class PrivateKernelCircuitPublicInputs { const reader = BufferReader.asReader(buffer); return new PrivateKernelCircuitPublicInputs( reader.readObject(Fr), - reader.readObject(ValidationRequests), + reader.readObject(PrivateValidationRequests), reader.readObject(PrivateAccumulatedData), reader.readObject(CombinedConstantData), reader.readObject(PublicCallRequest), @@ -69,7 +69,7 @@ export class PrivateKernelCircuitPublicInputs { static empty() { return new PrivateKernelCircuitPublicInputs( Fr.zero(), - ValidationRequests.empty(), + PrivateValidationRequests.empty(), PrivateAccumulatedData.empty(), CombinedConstantData.empty(), PublicCallRequest.empty(), diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts index 1f43c69fff5..79e4e90bb6d 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts @@ -39,6 +39,11 @@ export class PrivateKernelResetHints< * Contains hints for key validation request. */ public keyValidationHints: Tuple, + /** + * The "final" minRevertibleSideEffectCounter of a tx, to split the data for squashing. + * Not the minRevertibleSideEffectCounter at the point the reset circuit is run. + */ + public validationRequestsSplitCounter: number, ) {} toBuffer() { @@ -48,6 +53,7 @@ export class PrivateKernelResetHints< this.noteHashReadRequestHints, this.nullifierReadRequestHints, this.keyValidationHints, + this.validationRequestsSplitCounter, ); } @@ -79,6 +85,7 @@ export class PrivateKernelResetHints< KeyValidationHint, NEW_KEY_VALIDATION_REQUESTS >, + this.validationRequestsSplitCounter, ); } /** @@ -113,6 +120,7 @@ export class PrivateKernelResetHints< nullifierReadRequestHintsFromBuffer(buf, numNullifierReadRequestPending, numNullifierReadRequestSettled), }), reader.readArray(numNullifierKeys, KeyValidationHint), + reader.readNumber(), ); } } diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts index be511028dec..b804341e44d 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts @@ -6,9 +6,9 @@ import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX } from '../../constants.gen.js'; import { countAccumulatedItems, mergeAccumulatedData } from '../../utils/index.js'; import { PartialStateReference } from '../partial_state_reference.js'; import { PublicCallRequest } from '../public_call_request.js'; +import { PublicValidationRequests } from '../public_validation_requests.js'; import { RevertCode } from '../revert_code.js'; import { RollupValidationRequests } from '../rollup_validation_requests.js'; -import { ValidationRequests } from '../validation_requests.js'; import { CombinedAccumulatedData } from './combined_accumulated_data.js'; import { CombinedConstantData } from './combined_constant_data.js'; import { KernelCircuitPublicInputs } from './kernel_circuit_public_inputs.js'; @@ -20,7 +20,7 @@ export class PartialPrivateTailPublicInputsForPublic { /** * Validation requests accumulated from public functions. */ - public validationRequests: ValidationRequests, + public validationRequests: PublicValidationRequests, /** * Accumulated side effects and enqueued calls that are not revertible. */ @@ -59,7 +59,7 @@ export class PartialPrivateTailPublicInputsForPublic { static fromBuffer(buffer: Buffer | BufferReader): PartialPrivateTailPublicInputsForPublic { const reader = BufferReader.asReader(buffer); return new PartialPrivateTailPublicInputsForPublic( - reader.readObject(ValidationRequests), + reader.readObject(PublicValidationRequests), reader.readObject(PublicAccumulatedData), reader.readObject(PublicAccumulatedData), reader.readObject(PublicCallRequest), @@ -77,7 +77,7 @@ export class PartialPrivateTailPublicInputsForPublic { static empty() { return new PartialPrivateTailPublicInputsForPublic( - ValidationRequests.empty(), + PublicValidationRequests.empty(), PublicAccumulatedData.empty(), PublicAccumulatedData.empty(), PublicCallRequest.empty(), diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts index 7997158441d..ca542885d3e 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_circuit_public_inputs.ts @@ -7,8 +7,8 @@ import { inspect } from 'util'; import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX } from '../../constants.gen.js'; import { PublicCallRequest } from '../public_call_request.js'; +import { PublicValidationRequests } from '../public_validation_requests.js'; import { RevertCode } from '../revert_code.js'; -import { ValidationRequests } from '../validation_requests.js'; import { CombinedConstantData } from './combined_constant_data.js'; import { PublicAccumulatedData } from './public_accumulated_data.js'; @@ -21,7 +21,7 @@ export class PublicKernelCircuitPublicInputs { /** * Validation requests accumulated from public functions. */ - public validationRequests: ValidationRequests, + public validationRequests: PublicValidationRequests, /** * Accumulated side effects and enqueued calls that are not revertible. */ @@ -92,7 +92,7 @@ export class PublicKernelCircuitPublicInputs { static fromBuffer(buffer: Buffer | BufferReader): PublicKernelCircuitPublicInputs { const reader = BufferReader.asReader(buffer); return new PublicKernelCircuitPublicInputs( - reader.readObject(ValidationRequests), + reader.readObject(PublicValidationRequests), reader.readObject(PublicAccumulatedData), reader.readObject(PublicAccumulatedData), reader.readObject(CombinedConstantData), @@ -104,7 +104,7 @@ export class PublicKernelCircuitPublicInputs { static empty() { return new PublicKernelCircuitPublicInputs( - ValidationRequests.empty(), + PublicValidationRequests.empty(), PublicAccumulatedData.empty(), PublicAccumulatedData.empty(), CombinedConstantData.empty(), @@ -117,7 +117,7 @@ export class PublicKernelCircuitPublicInputs { static fromFields(fields: Fr[] | FieldReader): PublicKernelCircuitPublicInputs { const reader = FieldReader.asReader(fields); return new PublicKernelCircuitPublicInputs( - ValidationRequests.fromFields(reader), + PublicValidationRequests.fromFields(reader), PublicAccumulatedData.fromFields(reader), PublicAccumulatedData.fromFields(reader), CombinedConstantData.fromFields(reader), diff --git a/yarn-project/circuits.js/src/structs/optional_number.ts b/yarn-project/circuits.js/src/structs/optional_number.ts new file mode 100644 index 00000000000..9281a317c27 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/optional_number.ts @@ -0,0 +1,50 @@ +import { type Fr } from '@aztec/foundation/fields'; +import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; +import { type FieldsOf } from '@aztec/foundation/types'; + +export class OptionalNumber { + constructor( + /** + * Whether a value was set. + */ + public isSome: boolean, + /** + * The actual number, if isSome is true. + */ + public value: number, + ) {} + + getSize() { + return this.toBuffer().length; + } + + static getFields(fields: FieldsOf) { + return [fields.isSome, fields.value] as const; + } + + toBuffer() { + return serializeToBuffer(...OptionalNumber.getFields(this)); + } + + static fromBuffer(buffer: Buffer | BufferReader): OptionalNumber { + const reader = BufferReader.asReader(buffer); + return new OptionalNumber(reader.readBoolean(), reader.readNumber()); + } + + toFields(): Fr[] { + return serializeToFields(...OptionalNumber.getFields(this)); + } + + static fromFields(fields: Fr[] | FieldReader): OptionalNumber { + const reader = FieldReader.asReader(fields); + return new OptionalNumber(reader.readBoolean(), reader.readU32()); + } + + isEmpty(): boolean { + return !this.isSome && !this.value; + } + + static empty() { + return new OptionalNumber(false, 0); + } +} diff --git a/yarn-project/circuits.js/src/structs/validation_requests.ts b/yarn-project/circuits.js/src/structs/private_validation_requests.ts similarity index 71% rename from yarn-project/circuits.js/src/structs/validation_requests.ts rename to yarn-project/circuits.js/src/structs/private_validation_requests.ts index cdfa2bbf2b4..f026fbfacaf 100644 --- a/yarn-project/circuits.js/src/structs/validation_requests.ts +++ b/yarn-project/circuits.js/src/structs/private_validation_requests.ts @@ -8,11 +8,9 @@ import { inspect } from 'util'; import { MAX_KEY_VALIDATION_REQUESTS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_READS_PER_TX, } from '../constants.gen.js'; -import { PublicDataRead } from './public_data_read_request.js'; +import { OptionalNumber } from './optional_number.js'; import { ScopedReadRequest } from './read_request.js'; import { RollupValidationRequests } from './rollup_validation_requests.js'; import { ScopedKeyValidationRequestAndGenerator } from './scoped_key_validation_request_and_generator.js'; @@ -20,7 +18,7 @@ import { ScopedKeyValidationRequestAndGenerator } from './scoped_key_validation_ /** * Validation requests accumulated during the execution of the transaction. */ -export class ValidationRequests { +export class PrivateValidationRequests { constructor( /** * Validation requests that cannot be fulfilled in the current context (private or public), and must be instead be @@ -35,13 +33,6 @@ export class ValidationRequests { * All the nullifier read requests made in this transaction. */ public nullifierReadRequests: Tuple, - /** - * The nullifier read requests made in this transaction. - */ - public nullifierNonExistentReadRequests: Tuple< - ScopedReadRequest, - typeof MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX - >, /** * All the key validation requests made in this transaction. */ @@ -50,9 +41,11 @@ export class ValidationRequests { typeof MAX_KEY_VALIDATION_REQUESTS_PER_TX >, /** - * All the public data reads made in this transaction. + * The counter to split the data for squashing. + * A revertible nullifier and a non-revertible note hash will not be squashed. + * It should be the "final" minRevertibleSideEffectCounter of a tx. */ - public publicDataReads: Tuple, + public splitCounter: OptionalNumber, ) {} getSize() { @@ -60,9 +53,8 @@ export class ValidationRequests { this.forRollup.getSize() + arraySerializedSizeOfNonEmpty(this.noteHashReadRequests) + arraySerializedSizeOfNonEmpty(this.nullifierReadRequests) + - arraySerializedSizeOfNonEmpty(this.nullifierNonExistentReadRequests) + arraySerializedSizeOfNonEmpty(this.scopedKeyValidationRequestsAndGenerators) + - arraySerializedSizeOfNonEmpty(this.publicDataReads) + this.splitCounter.getSize() ); } @@ -71,9 +63,8 @@ export class ValidationRequests { this.forRollup, this.noteHashReadRequests, this.nullifierReadRequests, - this.nullifierNonExistentReadRequests, this.scopedKeyValidationRequestsAndGenerators, - this.publicDataReads, + this.splitCounter, ); } @@ -83,13 +74,12 @@ export class ValidationRequests { static fromFields(fields: Fr[] | FieldReader) { const reader = FieldReader.asReader(fields); - return new ValidationRequests( + return new PrivateValidationRequests( reader.readObject(RollupValidationRequests), reader.readArray(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ScopedReadRequest), reader.readArray(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest), - reader.readArray(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ScopedReadRequest), reader.readArray(MAX_KEY_VALIDATION_REQUESTS_PER_TX, ScopedKeyValidationRequestAndGenerator), - reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead), + reader.readObject(OptionalNumber), ); } @@ -100,13 +90,12 @@ export class ValidationRequests { */ static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); - return new ValidationRequests( + return new PrivateValidationRequests( reader.readObject(RollupValidationRequests), reader.readArray(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ScopedReadRequest), reader.readArray(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest), - reader.readArray(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ScopedReadRequest), reader.readArray(MAX_KEY_VALIDATION_REQUESTS_PER_TX, ScopedKeyValidationRequestAndGenerator), - reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead), + reader.readObject(OptionalNumber), ); } @@ -116,22 +105,21 @@ export class ValidationRequests { * @returns Deserialized object. */ static fromString(str: string) { - return ValidationRequests.fromBuffer(Buffer.from(str, 'hex')); + return PrivateValidationRequests.fromBuffer(Buffer.from(str, 'hex')); } static empty() { - return new ValidationRequests( + return new PrivateValidationRequests( RollupValidationRequests.empty(), makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ScopedReadRequest.empty), makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest.empty), - makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ScopedReadRequest.empty), makeTuple(MAX_KEY_VALIDATION_REQUESTS_PER_TX, ScopedKeyValidationRequestAndGenerator.empty), - makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead.empty), + OptionalNumber.empty(), ); } [inspect.custom]() { - return `ValidationRequests { + return `PrivateValidationRequests { forRollup: ${inspect(this.forRollup)}, noteHashReadRequests: [${this.noteHashReadRequests .filter(x => !x.isEmpty()) @@ -141,18 +129,11 @@ export class ValidationRequests { .filter(x => !x.isEmpty()) .map(h => inspect(h)) .join(', ')}], - nullifierNonExistentReadRequests: [${this.nullifierNonExistentReadRequests - .filter(x => !x.isEmpty()) - .map(h => inspect(h)) - .join(', ')}], scopedKeyValidationRequestsAndGenerators: [${this.scopedKeyValidationRequestsAndGenerators .filter(x => !x.isEmpty()) .map(h => inspect(h)) .join(', ')}], - publicDataReads: [${this.publicDataReads - .filter(x => !x.isEmpty()) - .map(h => inspect(h)) - .join(', ')}] -}`; + splitCounter: ${this.splitCounter} + `; } } diff --git a/yarn-project/circuits.js/src/structs/public_validation_requests.ts b/yarn-project/circuits.js/src/structs/public_validation_requests.ts new file mode 100644 index 00000000000..af29d553736 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/public_validation_requests.ts @@ -0,0 +1,126 @@ +import { makeTuple } from '@aztec/foundation/array'; +import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection'; +import { type Fr } from '@aztec/foundation/fields'; +import { BufferReader, FieldReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { inspect } from 'util'; + +import { + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, + MAX_PUBLIC_DATA_READS_PER_TX, +} from '../constants.gen.js'; +import { PublicDataRead } from './public_data_read_request.js'; +import { ScopedReadRequest } from './read_request.js'; +import { RollupValidationRequests } from './rollup_validation_requests.js'; + +/** + * Validation requests accumulated during the execution of the transaction. + */ +export class PublicValidationRequests { + constructor( + /** + * Validation requests that cannot be fulfilled in the current context (private or public), and must be instead be + * forwarded to the rollup for it to take care of them. + */ + public forRollup: RollupValidationRequests, + /** + * All the nullifier read requests made in this transaction. + */ + public nullifierReadRequests: Tuple, + /** + * The nullifier read requests made in this transaction. + */ + public nullifierNonExistentReadRequests: Tuple< + ScopedReadRequest, + typeof MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX + >, + /** + * All the public data reads made in this transaction. + */ + public publicDataReads: Tuple, + ) {} + + getSize() { + return ( + this.forRollup.getSize() + + arraySerializedSizeOfNonEmpty(this.nullifierReadRequests) + + arraySerializedSizeOfNonEmpty(this.nullifierNonExistentReadRequests) + + arraySerializedSizeOfNonEmpty(this.publicDataReads) + ); + } + + toBuffer() { + return serializeToBuffer( + this.forRollup, + this.nullifierReadRequests, + this.nullifierNonExistentReadRequests, + this.publicDataReads, + ); + } + + toString() { + return this.toBuffer().toString('hex'); + } + + static fromFields(fields: Fr[] | FieldReader) { + const reader = FieldReader.asReader(fields); + return new PublicValidationRequests( + reader.readObject(RollupValidationRequests), + reader.readArray(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest), + reader.readArray(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ScopedReadRequest), + reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead), + ); + } + + /** + * Deserializes from a buffer or reader, corresponding to a write in cpp. + * @param buffer - Buffer or reader to read from. + * @returns Deserialized object. + */ + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PublicValidationRequests( + reader.readObject(RollupValidationRequests), + reader.readArray(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest), + reader.readArray(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ScopedReadRequest), + reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead), + ); + } + + /** + * Deserializes from a string, corresponding to a write in cpp. + * @param str - String to read from. + * @returns Deserialized object. + */ + static fromString(str: string) { + return PublicValidationRequests.fromBuffer(Buffer.from(str, 'hex')); + } + + static empty() { + return new PublicValidationRequests( + RollupValidationRequests.empty(), + makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest.empty), + makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ScopedReadRequest.empty), + makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead.empty), + ); + } + + [inspect.custom]() { + return `PublicValidationRequests { + forRollup: ${inspect(this.forRollup)}, + nullifierReadRequests: [${this.nullifierReadRequests + .filter(x => !x.isEmpty()) + .map(h => inspect(h)) + .join(', ')}], + nullifierNonExistentReadRequests: [${this.nullifierNonExistentReadRequests + .filter(x => !x.isEmpty()) + .map(h => inspect(h)) + .join(', ')}], + publicDataReads: [${this.publicDataReads + .filter(x => !x.isEmpty()) + .map(h => inspect(h)) + .join(', ')}] +}`; + } +} diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index c2e0b89388b..baffa66a56f 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -44,7 +44,6 @@ import { MAX_ENCRYPTED_LOGS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_CALL, - MAX_KEY_VALIDATION_REQUESTS_PER_TX, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_TX, @@ -124,7 +123,6 @@ import { RootParityInputs, RootRollupInputs, RootRollupPublicInputs, - ScopedKeyValidationRequestAndGenerator, ScopedLogHash, ScopedReadRequest, StateDiffHints, @@ -148,10 +146,10 @@ import { GasFees } from '../structs/gas_fees.js'; import { GasSettings } from '../structs/gas_settings.js'; import { GlobalVariables } from '../structs/global_variables.js'; import { Header } from '../structs/header.js'; +import { PublicValidationRequests } from '../structs/index.js'; import { KernelCircuitPublicInputs } from '../structs/kernel/kernel_circuit_public_inputs.js'; import { KernelData } from '../structs/kernel/kernel_data.js'; import { RollupValidationRequests } from '../structs/rollup_validation_requests.js'; -import { ValidationRequests } from '../structs/validation_requests.js'; /** * Creates an arbitrary side effect object with the given seed. @@ -248,18 +246,6 @@ function makeKeyValidationRequestAndGenerators(seed: number): KeyValidationReque return new KeyValidationRequestAndGenerator(makeKeyValidationRequests(seed), fr(seed + 4)); } -/** - * Creates arbitrary scoped ScopedKeyValidationRequestAndGenerator from the given seed. - * @param seed - The seed to use for generating the ScopedKeyValidationRequestAndGenerator. - * @returns A ScopedKeyValidationRequestAndGenerator. - */ -function makeScopedKeyValidationRequestAndGenerators(seed: number): ScopedKeyValidationRequestAndGenerator { - return new ScopedKeyValidationRequestAndGenerator( - makeKeyValidationRequestAndGenerators(seed), - makeAztecAddress(seed + 4), - ); -} - /** * Creates arbitrary public data update request. * @param seed - The seed to use for generating the public data update request. @@ -312,13 +298,11 @@ export function makeContractStorageRead(seed = 1): ContractStorageRead { return new ContractStorageRead(fr(seed), fr(seed + 1), seed + 2); } -export function makeValidationRequests(seed = 1) { - return new ValidationRequests( +function makePublicValidationRequests(seed = 1) { + return new PublicValidationRequests( makeRollupValidationRequests(seed), makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, makeScopedReadRequest, seed + 0x80), - makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, makeScopedReadRequest, seed + 0x90), makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, makeScopedReadRequest, seed + 0x95), - makeTuple(MAX_KEY_VALIDATION_REQUESTS_PER_TX, makeScopedKeyValidationRequestAndGenerators, seed + 0x100), makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, makePublicDataRead, seed + 0xe00), ); } @@ -467,7 +451,7 @@ export function makePublicKernelCircuitPublicInputs( ): PublicKernelCircuitPublicInputs { const tupleGenerator = fullAccumulatedData ? makeTuple : makeHalfFullTuple; return new PublicKernelCircuitPublicInputs( - makeValidationRequests(seed), + makePublicValidationRequests(seed), makePublicAccumulatedData(seed, fullAccumulatedData), makePublicAccumulatedData(seed, fullAccumulatedData), makeConstantData(seed + 0x100), @@ -488,7 +472,7 @@ export function makePrivateKernelTailCircuitPublicInputs( ): PrivateKernelTailCircuitPublicInputs { const forPublic = isForPublic ? new PartialPrivateTailPublicInputsForPublic( - ValidationRequests.empty(), + PublicValidationRequests.empty(), makePublicAccumulatedData(seed + 0x100, false), makePublicAccumulatedData(seed + 0x200, false), makePublicCallRequest(seed + 0x400), diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index 4cc162811da..254e69075ac 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -61,6 +61,7 @@ import { type NullifierLeafPreimage, type NullifierNonExistentReadRequestHints, type NullifierReadRequestHints, + OptionalNumber, type PUBLIC_DATA_TREE_HEIGHT, ParityPublicInputs, PartialPrivateTailPublicInputsForPublic, @@ -83,6 +84,7 @@ import { type PrivateKernelResetHints, type PrivateKernelTailCircuitPrivateInputs, PrivateKernelTailCircuitPublicInputs, + PrivateValidationRequests, PublicAccumulatedData, type PublicCallData, PublicCallRequest, @@ -99,6 +101,7 @@ import { PublicKernelCircuitPublicInputs, type PublicKernelData, type PublicKernelTailCircuitPrivateInputs, + PublicValidationRequests, type RECURSIVE_PROOF_LENGTH, ReadRequest, type ReadRequestStatus, @@ -121,7 +124,6 @@ import { StateReference, TxContext, type TxRequest, - ValidationRequests, type VerificationKeyAsFields, } from '@aztec/circuits.js'; import { toBufferBE } from '@aztec/foundation/bigint-buffer'; @@ -176,6 +178,7 @@ import type { NullifierNonMembershipHint as NullifierNonMembershipHintNoir, NullifierReadRequestHints as NullifierReadRequestHintsNoir, NullifierSettledReadHint as NullifierSettledReadHintNoir, + Option as OptionalNumberNoir, ParityPublicInputs as ParityPublicInputsNoir, RootParityInput as ParityRootParityInputNoir, PartialStateReference as PartialStateReferenceNoir, @@ -195,6 +198,7 @@ import type { PrivateKernelResetHints as PrivateKernelResetHintsNoir, PrivateKernelTailCircuitPrivateInputs as PrivateKernelTailCircuitPrivateInputsNoir, PrivateKernelTailToPublicCircuitPrivateInputs as PrivateKernelTailToPublicCircuitPrivateInputsNoir, + PrivateValidationRequests as PrivateValidationRequestsNoir, PublicAccumulatedData as PublicAccumulatedDataNoir, PublicCallData as PublicCallDataNoir, PublicCallRequest as PublicCallRequestNoir, @@ -211,6 +215,7 @@ import type { PublicKernelData as PublicKernelDataNoir, PublicKernelSetupCircuitPrivateInputs as PublicKernelSetupCircuitPrivateInputsNoir, PublicKernelTailCircuitPrivateInputs as PublicKernelTailCircuitPrivateInputsNoir, + PublicValidationRequests as PublicValidationRequestsNoir, ReadRequest as ReadRequestNoir, ReadRequestStatus as ReadRequestStatusNoir, RollupValidationRequests as RollupValidationRequestsNoir, @@ -231,7 +236,6 @@ import type { StorageUpdateRequest as StorageUpdateRequestNoir, TxContext as TxContextNoir, TxRequest as TxRequestNoir, - ValidationRequests as ValidationRequestsNoir, } from './types/index.js'; /* eslint-disable camelcase */ @@ -1165,25 +1169,32 @@ function mapPublicDataReadRequestHintsToNoir(hints: PublicDataReadRequestHints): }; } -function mapValidationRequestsToNoir(requests: ValidationRequests): ValidationRequestsNoir { +function mapOptionalNumberToNoir(option: OptionalNumber): OptionalNumberNoir { + return { + _is_some: option.isSome, + _value: mapNumberToNoir(option.value), + }; +} + +function mapOptionalNumberFromNoir(option: OptionalNumberNoir) { + return new OptionalNumber(option._is_some, mapNumberFromNoir(option._value)); +} + +function mapPrivateValidationRequestsToNoir(requests: PrivateValidationRequests): PrivateValidationRequestsNoir { return { for_rollup: mapRollupValidationRequestsToNoir(requests.forRollup), note_hash_read_requests: mapTuple(requests.noteHashReadRequests, mapScopedReadRequestToNoir), nullifier_read_requests: mapTuple(requests.nullifierReadRequests, mapScopedReadRequestToNoir), - nullifier_non_existent_read_requests: mapTuple( - requests.nullifierNonExistentReadRequests, - mapScopedReadRequestToNoir, - ), scoped_key_validation_requests_and_generators: mapTuple( requests.scopedKeyValidationRequestsAndGenerators, mapScopedKeyValidationRequestAndGeneratorToNoir, ), - public_data_reads: mapTuple(requests.publicDataReads, mapPublicDataReadToNoir), + split_counter: mapOptionalNumberToNoir(requests.splitCounter), }; } -function mapValidationRequestsFromNoir(requests: ValidationRequestsNoir): ValidationRequests { - return new ValidationRequests( +function mapPrivateValidationRequestsFromNoir(requests: PrivateValidationRequestsNoir) { + return new PrivateValidationRequests( mapRollupValidationRequestsFromNoir(requests.for_rollup), mapTupleFromNoir( requests.note_hash_read_requests, @@ -1195,16 +1206,40 @@ function mapValidationRequestsFromNoir(requests: ValidationRequestsNoir): Valida MAX_NULLIFIER_READ_REQUESTS_PER_TX, mapScopedReadRequestFromNoir, ), - mapTupleFromNoir( - requests.nullifier_non_existent_read_requests, - MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, - mapScopedReadRequestFromNoir, - ), mapTupleFromNoir( requests.scoped_key_validation_requests_and_generators, MAX_KEY_VALIDATION_REQUESTS_PER_TX, mapScopedKeyValidationRequestAndGeneratorFromNoir, ), + mapOptionalNumberFromNoir(requests.split_counter), + ); +} + +function mapPublicValidationRequestsToNoir(requests: PublicValidationRequests): PublicValidationRequestsNoir { + return { + for_rollup: mapRollupValidationRequestsToNoir(requests.forRollup), + nullifier_read_requests: mapTuple(requests.nullifierReadRequests, mapScopedReadRequestToNoir), + nullifier_non_existent_read_requests: mapTuple( + requests.nullifierNonExistentReadRequests, + mapScopedReadRequestToNoir, + ), + public_data_reads: mapTuple(requests.publicDataReads, mapPublicDataReadToNoir), + }; +} + +function mapPublicValidationRequestsFromNoir(requests: PublicValidationRequestsNoir): PublicValidationRequests { + return new PublicValidationRequests( + mapRollupValidationRequestsFromNoir(requests.for_rollup), + mapTupleFromNoir( + requests.nullifier_read_requests, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, + mapScopedReadRequestFromNoir, + ), + mapTupleFromNoir( + requests.nullifier_non_existent_read_requests, + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, + mapScopedReadRequestFromNoir, + ), mapTupleFromNoir(requests.public_data_reads, MAX_PUBLIC_DATA_READS_PER_TX, mapPublicDataReadFromNoir), ); } @@ -1434,7 +1469,7 @@ export function mapPublicKernelCircuitPublicInputsToNoir( ): PublicKernelCircuitPublicInputsNoir { return { constants: mapCombinedConstantDataToNoir(inputs.constants), - validation_requests: mapValidationRequestsToNoir(inputs.validationRequests), + validation_requests: mapPublicValidationRequestsToNoir(inputs.validationRequests), end: mapPublicAccumulatedDataToNoir(inputs.end), end_non_revertible: mapPublicAccumulatedDataToNoir(inputs.endNonRevertibleData), revert_code: mapRevertCodeToNoir(inputs.revertCode), @@ -1502,7 +1537,7 @@ export function mapPrivateKernelCircuitPublicInputsFromNoir( ): PrivateKernelCircuitPublicInputs { return new PrivateKernelCircuitPublicInputs( mapFieldFromNoir(inputs.min_revertible_side_effect_counter), - mapValidationRequestsFromNoir(inputs.validation_requests), + mapPrivateValidationRequestsFromNoir(inputs.validation_requests), mapPrivateAccumulatedDataFromNoir(inputs.end), mapCombinedConstantDataFromNoir(inputs.constants), mapPublicCallRequestFromNoir(inputs.public_teardown_call_request), @@ -1515,7 +1550,7 @@ export function mapPrivateKernelCircuitPublicInputsToNoir( ): PrivateKernelCircuitPublicInputsNoir { return { constants: mapCombinedConstantDataToNoir(inputs.constants), - validation_requests: mapValidationRequestsToNoir(inputs.validationRequests), + validation_requests: mapPrivateValidationRequestsToNoir(inputs.validationRequests), end: mapPrivateAccumulatedDataToNoir(inputs.end), min_revertible_side_effect_counter: mapFieldToNoir(inputs.minRevertibleSideEffectCounter), public_teardown_call_request: mapPublicCallRequestToNoir(inputs.publicTeardownCallRequest), @@ -1557,7 +1592,7 @@ export function mapPrivateKernelTailCircuitPublicInputsForPublicFromNoir( inputs: PublicKernelCircuitPublicInputsNoir, ): PrivateKernelTailCircuitPublicInputs { const forPublic = new PartialPrivateTailPublicInputsForPublic( - mapValidationRequestsFromNoir(inputs.validation_requests), + mapPublicValidationRequestsFromNoir(inputs.validation_requests), mapPublicAccumulatedDataFromNoir(inputs.end_non_revertible), mapPublicAccumulatedDataFromNoir(inputs.end), mapPublicCallRequestFromNoir(inputs.public_teardown_call_stack[0]), @@ -1616,6 +1651,7 @@ function mapPrivateKernelResetHintsToNoir< KeyValidationHintNoir, KEY_VALIDATION_REQUESTS >, + validation_requests_split_counter: mapNumberToNoir(inputs.validationRequestsSplitCounter), }; } @@ -1718,7 +1754,7 @@ export function mapPublicKernelCircuitPublicInputsFromNoir( inputs: PublicKernelCircuitPublicInputsNoir, ): PublicKernelCircuitPublicInputs { return new PublicKernelCircuitPublicInputs( - mapValidationRequestsFromNoir(inputs.validation_requests), + mapPublicValidationRequestsFromNoir(inputs.validation_requests), mapPublicAccumulatedDataFromNoir(inputs.end_non_revertible), mapPublicAccumulatedDataFromNoir(inputs.end), mapCombinedConstantDataFromNoir(inputs.constants), diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts b/yarn-project/pxe/src/kernel_prover/hints/build_private_kernel_reset_hints.ts similarity index 98% rename from yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts rename to yarn-project/pxe/src/kernel_prover/hints/build_private_kernel_reset_hints.ts index e46d1497a2d..fa05d462d52 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts +++ b/yarn-project/pxe/src/kernel_prover/hints/build_private_kernel_reset_hints.ts @@ -91,6 +91,7 @@ export async function buildPrivateKernelResetInputs( previousKernelData: PrivateKernelData, noteHashLeafIndexMap: Map, noteHashNullifierCounterMap: Map, + validationRequestsSplitCounter: number, oracle: ProvingDataOracle, ) { const publicInputs = previousKernelData.publicInputs; @@ -181,6 +182,7 @@ export async function buildPrivateKernelResetInputs( noteHashReadRequestHints, nullifierReadRequestHints, keysHints, + validationRequestsSplitCounter, ).trimToSizes( hintSizes.NOTE_HASH_PENDING_AMOUNT, hintSizes.NOTE_HASH_SETTLED_AMOUNT, diff --git a/yarn-project/pxe/src/kernel_prover/hints/index.ts b/yarn-project/pxe/src/kernel_prover/hints/index.ts new file mode 100644 index 00000000000..4ec3f8a5ec0 --- /dev/null +++ b/yarn-project/pxe/src/kernel_prover/hints/index.ts @@ -0,0 +1,2 @@ +export * from './build_private_kernel_reset_hints.js'; +export * from './needs_reset.js'; diff --git a/yarn-project/pxe/src/kernel_prover/hints/needs_reset.ts b/yarn-project/pxe/src/kernel_prover/hints/needs_reset.ts new file mode 100644 index 00000000000..c9eb7bc5f41 --- /dev/null +++ b/yarn-project/pxe/src/kernel_prover/hints/needs_reset.ts @@ -0,0 +1,51 @@ +import { + MAX_KEY_VALIDATION_REQUESTS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + MAX_NULLIFIERS_PER_TX, + MAX_NULLIFIER_READ_REQUESTS_PER_TX, + type PrivateKernelCircuitPublicInputs, + getNonEmptyItems, +} from '@aztec/circuits.js'; +import { type ExecutionResult } from '@aztec/simulator'; + +export function needsReset(publicInputs: PrivateKernelCircuitPublicInputs, executionStack: ExecutionResult[]) { + const nextIteration = executionStack[executionStack.length - 1]; + return ( + getNonEmptyItems(nextIteration.callStackItem.publicInputs.noteHashes).length + + getNonEmptyItems(publicInputs.end.noteHashes).length > + MAX_NOTE_HASHES_PER_TX || + getNonEmptyItems(nextIteration.callStackItem.publicInputs.nullifiers).length + + getNonEmptyItems(publicInputs.end.nullifiers).length > + MAX_NULLIFIERS_PER_TX || + getNonEmptyItems(nextIteration.callStackItem.publicInputs.noteEncryptedLogsHashes).length + + getNonEmptyItems(publicInputs.end.noteEncryptedLogsHashes).length > + MAX_NOTE_ENCRYPTED_LOGS_PER_TX || + getNonEmptyItems(nextIteration.callStackItem.publicInputs.noteHashReadRequests).length + + getNonEmptyItems(publicInputs.validationRequests.noteHashReadRequests).length > + MAX_NOTE_HASH_READ_REQUESTS_PER_TX || + getNonEmptyItems(nextIteration.callStackItem.publicInputs.nullifierReadRequests).length + + getNonEmptyItems(publicInputs.validationRequests.nullifierReadRequests).length > + MAX_NULLIFIER_READ_REQUESTS_PER_TX || + getNonEmptyItems(nextIteration.callStackItem.publicInputs.keyValidationRequestsAndGenerators).length + + getNonEmptyItems(publicInputs.validationRequests.scopedKeyValidationRequestsAndGenerators).length > + MAX_KEY_VALIDATION_REQUESTS_PER_TX + ); +} + +function hasTransientNullifier(publicInputs: PrivateKernelCircuitPublicInputs) { + const noteHashSet = new Set(); + publicInputs.end.noteHashes.forEach(n => noteHashSet.add(n.noteHash.value.toBigInt())); + noteHashSet.delete(0n); + return publicInputs.end.nullifiers.some(n => noteHashSet.has(n.nullifiedNoteHash.toBigInt())); +} + +export function somethingToReset(publicInputs: PrivateKernelCircuitPublicInputs) { + return ( + getNonEmptyItems(publicInputs.validationRequests.noteHashReadRequests).length > 0 || + getNonEmptyItems(publicInputs.validationRequests.nullifierReadRequests).length > 0 || + getNonEmptyItems(publicInputs.validationRequests.scopedKeyValidationRequestsAndGenerators).length > 0 || + hasTransientNullifier(publicInputs) + ); +} diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts index 78da12312cf..70010c0eb9a 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts @@ -67,7 +67,7 @@ describe('Kernel Prover', () => { nestedExecutions: (dependencies[fnName] || []).map(name => createExecutionResult(name)), vk: VerificationKey.makeFake().toBuffer(), newNotes: newNoteIndices.map(idx => notesAndSlots[idx]), - nullifiedNoteHashCounters: new Map(), + noteHashNullifierCounterMap: new Map(), noteHashLeafIndexMap: new Map(), returnValues: [], acir: Buffer.alloc(0), diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts index e1831598666..26b4dfe0586 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts @@ -1,12 +1,6 @@ import { type PrivateKernelProver, type PrivateKernelSimulateOutput } from '@aztec/circuit-types'; import { Fr, - MAX_KEY_VALIDATION_REQUESTS_PER_TX, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, - MAX_NOTE_HASHES_PER_TX, - MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_NULLIFIERS_PER_TX, - MAX_NULLIFIER_READ_REQUESTS_PER_TX, PrivateCallData, PrivateKernelCircuitPublicInputs, PrivateKernelData, @@ -17,7 +11,6 @@ import { type TxRequest, VK_TREE_HEIGHT, VerificationKeyAsFields, - getNonEmptyItems, } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { assertLength } from '@aztec/foundation/serialize'; @@ -27,11 +20,18 @@ import { PrivateResetTagToArtifactName, getVKTreeRoot, } from '@aztec/noir-protocol-circuits-types'; -import { type ExecutionResult, collectNoteHashLeafIndexMap, collectNullifiedNoteHashCounters } from '@aztec/simulator'; +import { + type ExecutionResult, + collectEnqueuedPublicFunctionCalls, + collectNoteHashLeafIndexMap, + collectNoteHashNullifierCounterMap, + collectPublicTeardownFunctionCall, + getFinalMinRevertibleSideEffectCounter, +} from '@aztec/simulator'; import { type WitnessMap } from '@noir-lang/types'; -import { buildPrivateKernelResetInputs } from './private_inputs_builders/index.js'; +import { buildPrivateKernelResetInputs, needsReset, somethingToReset } from './hints/index.js'; import { type ProvingDataOracle } from './proving_data_oracle.js'; const NULL_PROVE_OUTPUT: PrivateKernelSimulateOutput = { @@ -71,18 +71,23 @@ export class KernelProver { let output = NULL_PROVE_OUTPUT; const noteHashLeafIndexMap = collectNoteHashLeafIndexMap(executionResult); - const noteHashNullifierCounterMap = collectNullifiedNoteHashCounters(executionResult); + const noteHashNullifierCounterMap = collectNoteHashNullifierCounterMap(executionResult); + const enqueuedPublicFunctions = collectEnqueuedPublicFunctionCalls(executionResult); + const hasPublicCalls = + enqueuedPublicFunctions.length > 0 || !collectPublicTeardownFunctionCall(executionResult).isEmpty(); + const validationRequestsSplitCounter = hasPublicCalls ? getFinalMinRevertibleSideEffectCounter(executionResult) : 0; // vector of gzipped bincode acirs const acirs: Buffer[] = []; const witnessStack: WitnessMap[] = []; while (executionStack.length) { - if (!firstIteration && this.needsReset(executionStack, output)) { + if (!firstIteration && needsReset(output.publicInputs, executionStack)) { const resetInputs = await this.getPrivateKernelResetInputs( executionStack, output, noteHashLeafIndexMap, noteHashNullifierCounterMap, + validationRequestsSplitCounter, ); output = await this.proofCreator.simulateProofReset(resetInputs); // TODO(#7368) consider refactoring this redundant bytecode pushing @@ -130,12 +135,13 @@ export class KernelProver { firstIteration = false; } - if (this.somethingToReset(output)) { + if (somethingToReset(output.publicInputs)) { const resetInputs = await this.getPrivateKernelResetInputs( executionStack, output, noteHashLeafIndexMap, noteHashNullifierCounterMap, + validationRequestsSplitCounter, ); output = await this.proofCreator.simulateProofReset(resetInputs); // TODO(#7368) consider refactoring this redundant bytecode pushing @@ -176,47 +182,12 @@ export class KernelProver { return tailOutput; } - private needsReset( - executionStack: ExecutionResult[], - output: PrivateKernelSimulateOutput, - ) { - const nextIteration = executionStack[executionStack.length - 1]; - return ( - getNonEmptyItems(nextIteration.callStackItem.publicInputs.noteHashes).length + - getNonEmptyItems(output.publicInputs.end.noteHashes).length > - MAX_NOTE_HASHES_PER_TX || - getNonEmptyItems(nextIteration.callStackItem.publicInputs.nullifiers).length + - getNonEmptyItems(output.publicInputs.end.nullifiers).length > - MAX_NULLIFIERS_PER_TX || - getNonEmptyItems(nextIteration.callStackItem.publicInputs.noteEncryptedLogsHashes).length + - getNonEmptyItems(output.publicInputs.end.noteEncryptedLogsHashes).length > - MAX_NOTE_ENCRYPTED_LOGS_PER_TX || - getNonEmptyItems(nextIteration.callStackItem.publicInputs.noteHashReadRequests).length + - getNonEmptyItems(output.publicInputs.validationRequests.noteHashReadRequests).length > - MAX_NOTE_HASH_READ_REQUESTS_PER_TX || - getNonEmptyItems(nextIteration.callStackItem.publicInputs.nullifierReadRequests).length + - getNonEmptyItems(output.publicInputs.validationRequests.nullifierReadRequests).length > - MAX_NULLIFIER_READ_REQUESTS_PER_TX || - getNonEmptyItems(nextIteration.callStackItem.publicInputs.keyValidationRequestsAndGenerators).length + - getNonEmptyItems(output.publicInputs.validationRequests.scopedKeyValidationRequestsAndGenerators).length > - MAX_KEY_VALIDATION_REQUESTS_PER_TX - ); - } - - private somethingToReset(output: PrivateKernelSimulateOutput) { - return ( - getNonEmptyItems(output.publicInputs.validationRequests.noteHashReadRequests).length > 0 || - getNonEmptyItems(output.publicInputs.validationRequests.nullifierReadRequests).length > 0 || - getNonEmptyItems(output.publicInputs.validationRequests.scopedKeyValidationRequestsAndGenerators).length > 0 || - output.publicInputs.end.nullifiers.find(nullifier => !nullifier.nullifiedNoteHash.equals(Fr.zero())) - ); - } - private async getPrivateKernelResetInputs( executionStack: ExecutionResult[], output: PrivateKernelSimulateOutput, noteHashLeafIndexMap: Map, noteHashNullifierCounterMap: Map, + validationRequestsSplitCounter: number, ) { const previousVkMembershipWitness = await this.oracle.getVkMembershipWitness(output.verificationKey); const previousKernelData = new PrivateKernelData( @@ -231,6 +202,7 @@ export class KernelProver { previousKernelData, noteHashLeafIndexMap, noteHashNullifierCounterMap, + validationRequestsSplitCounter, this.oracle, ); } diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/index.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/index.ts deleted file mode 100644 index e63ee6b45bb..00000000000 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { buildPrivateKernelResetInputs } from './build_private_kernel_reset_hints.js'; diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 4714b23832f..2c6de5ba7f6 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -440,25 +440,6 @@ export class Oracle { return [endSideEffectCounter, returnsHash].map(toACVMField); } - async callPublicFunction( - [contractAddress]: ACVMField[], - [functionSelector]: ACVMField[], - [argsHash]: ACVMField[], - [sideEffectCounter]: ACVMField[], - [isStaticCall]: ACVMField[], - [isDelegateCall]: ACVMField[], - ): Promise { - const returnValues = await this.typedOracle.callPublicFunction( - AztecAddress.fromField(fromACVMField(contractAddress)), - FunctionSelector.fromField(fromACVMField(functionSelector)), - fromACVMField(argsHash), - frToNumber(fromACVMField(sideEffectCounter)), - frToBoolean(fromACVMField(isStaticCall)), - frToBoolean(fromACVMField(isDelegateCall)), - ); - return returnValues.map(toACVMField); - } - async enqueuePublicFunctionCall( [contractAddress]: ACVMField[], [functionSelector]: ACVMField[], @@ -495,6 +476,10 @@ export class Oracle { ); } + notifySetMinRevertibleSideEffectCounter([minRevertibleSideEffectCounter]: ACVMField[]) { + this.typedOracle.notifySetMinRevertibleSideEffectCounter(frToNumber(fromACVMField(minRevertibleSideEffectCounter))); + } + aes128Encrypt(input: ACVMField[], initializationVector: ACVMField[], key: ACVMField[]): ACVMField[] { // Convert each field to a number and then to a buffer (1 byte is stored in 1 field) const processedInput = Buffer.from(input.map(fromACVMField).map(f => f.toNumber())); diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 28c08526b1d..872e0b2b5af 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -253,17 +253,6 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('callPrivateFunction'); } - callPublicFunction( - _targetContractAddress: AztecAddress, - _functionSelector: FunctionSelector, - _argsHash: Fr, - _sideEffectCounter: number, - _isStaticCall: boolean, - _isDelegateCall: boolean, - ): Promise { - throw new OracleMethodNotAvailableError('callPublicFunction'); - } - enqueuePublicFunctionCall( _targetContractAddress: AztecAddress, _functionSelector: FunctionSelector, @@ -286,6 +275,10 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('setPublicTeardownFunctionCall'); } + notifySetMinRevertibleSideEffectCounter(_minRevertibleSideEffectCounter: number): void { + throw new OracleMethodNotAvailableError('notifySetMinRevertibleSideEffectCounter'); + } + aes128Encrypt(_input: Buffer, _initializationVector: Buffer, _key: Buffer): Buffer { throw new OracleMethodNotAvailableError('encrypt'); } diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index e79d6ea6c12..5b16971e641 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -71,7 +71,7 @@ export class ClientExecutionContext extends ViewDataOracle { * They should act as references for the read requests output by an app circuit via public inputs. */ private noteHashLeafIndexMap: Map = new Map(); - private nullifiedNoteHashCounters: Map = new Map(); + private noteHashNullifierCounterMap: Map = new Map(); private noteEncryptedLogs: CountedNoteLog[] = []; private encryptedLogs: CountedLog[] = []; private unencryptedLogs: CountedLog[] = []; @@ -141,8 +141,8 @@ export class ClientExecutionContext extends ViewDataOracle { return this.newNotes; } - public getNullifiedNoteHashCounters() { - return this.nullifiedNoteHashCounters; + public getNoteHashNullifierCounterMap() { + return this.noteHashNullifierCounterMap; } /** @@ -337,7 +337,7 @@ export class ClientExecutionContext extends ViewDataOracle { slottedNoteHash, ); if (nullifiedNoteHashCounter !== undefined) { - this.nullifiedNoteHashCounters.set(nullifiedNoteHashCounter, counter); + this.noteHashNullifierCounterMap.set(nullifiedNoteHashCounter, counter); } return Promise.resolve(); } @@ -645,6 +645,10 @@ export class ClientExecutionContext extends ViewDataOracle { ); } + public override notifySetMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: number): void { + this.noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter); + } + /** * Derives the call context for a nested execution. * @param targetContractAddress - The address of the contract being called. diff --git a/yarn-project/simulator/src/client/execution_note_cache.ts b/yarn-project/simulator/src/client/execution_note_cache.ts index 2405870f927..b97dfda9aeb 100644 --- a/yarn-project/simulator/src/client/execution_note_cache.ts +++ b/yarn-project/simulator/src/client/execution_note_cache.ts @@ -1,12 +1,13 @@ -import { siloNullifier } from '@aztec/circuits.js/hash'; +import { computeNoteHashNonce, computeUniqueNoteHash, siloNoteHash, siloNullifier } from '@aztec/circuits.js/hash'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { Fr } from '@aztec/foundation/fields'; +import { type Fr } from '@aztec/foundation/fields'; import { type NoteData } from '../acvm/index.js'; -export interface PendingNote { +interface PendingNote { note: NoteData; counter: number; + noteHashForConsumption: Fr; } /** @@ -15,9 +16,13 @@ export interface PendingNote { export class ExecutionNoteCache { /** * New notes created in this transaction. + * They are pushed to this array in the same order as they are emitted. + */ + private notes: PendingNote[] = []; + /** * This mapping maps from a contract address to the notes in the contract. */ - private newNotes: Map = new Map(); + private noteMap: Map = new Map(); /** * The list of nullifiers created in this transaction. @@ -25,22 +30,58 @@ export class ExecutionNoteCache { * The note which is nullified might be new or not (i.e., was generated in a previous transaction). * Note that their value (bigint representation) is used because Frs cannot be looked up in Sets. */ - private nullifiers: Map> = new Map(); + private nullifierMap: Map> = new Map(); + + private minRevertibleSideEffectCounter = 0; + + constructor(private readonly txHash: Fr) {} + + public setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: number) { + if (this.minRevertibleSideEffectCounter && this.minRevertibleSideEffectCounter !== minRevertibleSideEffectCounter) { + throw new Error( + `Cannot override minRevertibleSideEffectCounter. Current value: ${minRevertibleSideEffectCounter}. Previous value: ${this.minRevertibleSideEffectCounter}`, + ); + } + + this.minRevertibleSideEffectCounter = minRevertibleSideEffectCounter; + + // The existing pending notes are all non-revertible. + // They cannot be squashed by nullifiers emitted after minRevertibleSideEffectCounter is set. + // Their indexes in the tx are known at this point and won't change. So we can assign a nonce to each one of them. + // The nonces will be used to create the "complete" nullifier. + const updatedNotes = this.notes.map(({ note, counter }, i) => { + const nonce = computeNoteHashNonce(this.txHash, i); + const uniqueNoteHash = computeUniqueNoteHash(nonce, note.slottedNoteHash); + return { + counter, + note: { ...note, nonce }, + noteHashForConsumption: siloNoteHash(note.contractAddress, uniqueNoteHash), + }; + }); + // Rebuild the data. + this.notes = []; + this.noteMap = new Map(); + updatedNotes.forEach(n => this.#addNote(n)); + } /** * Add a new note to cache. * @param note - New note created during execution. */ public addNewNote(note: NoteData, counter: number) { - const notes = this.newNotes.get(note.contractAddress.toBigInt()) ?? []; - notes.push({ note, counter }); - this.newNotes.set(note.contractAddress.toBigInt(), notes); + const previousNote = this.notes[this.notes.length - 1]; + if (previousNote && previousNote.counter >= counter) { + throw new Error( + `Note hash counters must be strictly increasing. Current counter: ${counter}. Previous counter: ${previousNote.counter}.`, + ); + } + + this.#addNote({ note, counter, noteHashForConsumption: note.slottedNoteHash }); } /** * Add a nullifier to cache. It could be for a db note or a new note created during execution. * @param contractAddress - Contract address of the note. - * @param storageSlot - Storage slot of the note. * @param innerNullifier - Inner nullifier of the note. * @param slottedNoteHash - Slotted note hash of the note. If this value equals 0, it means the * note being nullified is from a previous transaction (and thus not a new note). @@ -49,19 +90,21 @@ export class ExecutionNoteCache { const siloedNullifier = siloNullifier(contractAddress, innerNullifier); const nullifiers = this.getNullifiers(contractAddress); nullifiers.add(siloedNullifier.value); - this.nullifiers.set(contractAddress.toBigInt(), nullifiers); + this.nullifierMap.set(contractAddress.toBigInt(), nullifiers); let nullifiedNoteHashCounter: number | undefined = undefined; // Find and remove the matching new note and log(s) if the emitted slottedNoteHash is not empty. - if (!slottedNoteHash.equals(Fr.ZERO)) { - const notes = this.newNotes.get(contractAddress.toBigInt()) ?? []; - const noteIndexToRemove = notes.findIndex(n => n.note.slottedNoteHash.equals(slottedNoteHash)); + if (!slottedNoteHash.isEmpty()) { + const notesInContract = this.noteMap.get(contractAddress.toBigInt()) ?? []; + const noteIndexToRemove = notesInContract.findIndex(n => n.noteHashForConsumption.equals(slottedNoteHash)); if (noteIndexToRemove === -1) { throw new Error('Attempt to remove a pending note that does not exist.'); } - const note = notes.splice(noteIndexToRemove, 1)[0]; + + const note = notesInContract.splice(noteIndexToRemove, 1)[0]; nullifiedNoteHashCounter = note.counter; - this.newNotes.set(contractAddress.toBigInt(), notes); + this.noteMap.set(contractAddress.toBigInt(), notesInContract); + this.notes = this.notes.filter(n => n.counter !== note.counter); } return nullifiedNoteHashCounter; } @@ -73,7 +116,7 @@ export class ExecutionNoteCache { * @param storageSlot - Storage slot of the notes. **/ public getNotes(contractAddress: AztecAddress, storageSlot: Fr) { - const notes = this.newNotes.get(contractAddress.toBigInt()) ?? []; + const notes = this.noteMap.get(contractAddress.toBigInt()) ?? []; return notes.filter(n => n.note.storageSlot.equals(storageSlot)).map(n => n.note); } @@ -84,7 +127,7 @@ export class ExecutionNoteCache { * @param slottedNoteHash - Slotted note hash of the note. **/ public checkNoteExists(contractAddress: AztecAddress, slottedNoteHash: Fr) { - const notes = this.newNotes.get(contractAddress.toBigInt()) ?? []; + const notes = this.noteMap.get(contractAddress.toBigInt()) ?? []; return notes.some(n => n.note.slottedNoteHash.equals(slottedNoteHash)); } @@ -93,6 +136,14 @@ export class ExecutionNoteCache { * @param contractAddress - Address of the contract. */ public getNullifiers(contractAddress: AztecAddress): Set { - return this.nullifiers.get(contractAddress.toBigInt()) ?? new Set(); + return this.nullifierMap.get(contractAddress.toBigInt()) ?? new Set(); + } + + #addNote(note: PendingNote) { + this.notes.push(note); + + const notes = this.noteMap.get(note.note.contractAddress.toBigInt()) ?? []; + notes.push(note); + this.noteMap.set(note.note.contractAddress.toBigInt(), notes); } } diff --git a/yarn-project/simulator/src/client/execution_result.test.ts b/yarn-project/simulator/src/client/execution_result.test.ts index 87d83686b48..d458a2a0a11 100644 --- a/yarn-project/simulator/src/client/execution_result.test.ts +++ b/yarn-project/simulator/src/client/execution_result.test.ts @@ -1,10 +1,11 @@ import { PublicExecutionRequest } from '@aztec/circuit-types'; -import { PrivateCallStackItem } from '@aztec/circuits.js'; +import { Fr, PrivateCallStackItem } from '@aztec/circuits.js'; import { type ExecutionResult, collectNoteHashLeafIndexMap, - collectNullifiedNoteHashCounters, + collectNoteHashNullifierCounterMap, + getFinalMinRevertibleSideEffectCounter, } from './execution_result.js'; function emptyExecutionResult(): ExecutionResult { @@ -15,7 +16,7 @@ function emptyExecutionResult(): ExecutionResult { callStackItem: PrivateCallStackItem.empty(), noteHashLeafIndexMap: new Map(), newNotes: [], - nullifiedNoteHashCounters: new Map(), + noteHashNullifierCounterMap: new Map(), returnValues: [], nestedExecutions: [], enqueuedPublicFunctionCalls: [], @@ -26,86 +27,109 @@ function emptyExecutionResult(): ExecutionResult { }; } -describe('collectNoteHashLeafIndexMap', () => { +describe('execution_result', () => { let executionResult: ExecutionResult; beforeEach(() => { executionResult = emptyExecutionResult(); }); - it('returns a map for note hash leaf indexes', () => { - executionResult.noteHashLeafIndexMap = new Map(); - executionResult.noteHashLeafIndexMap.set(12n, 99n); - executionResult.noteHashLeafIndexMap.set(34n, 88n); - const res = collectNoteHashLeafIndexMap(executionResult); - expect(res.size).toBe(2); - expect(res.get(12n)).toBe(99n); - expect(res.get(34n)).toBe(88n); + describe('collectNoteHashLeafIndexMap', () => { + it('returns a map for note hash leaf indexes', () => { + executionResult.noteHashLeafIndexMap = new Map(); + executionResult.noteHashLeafIndexMap.set(12n, 99n); + executionResult.noteHashLeafIndexMap.set(34n, 88n); + const res = collectNoteHashLeafIndexMap(executionResult); + expect(res.size).toBe(2); + expect(res.get(12n)).toBe(99n); + expect(res.get(34n)).toBe(88n); + }); + + it('returns a map containing note hash leaf indexes for nested executions', () => { + executionResult.noteHashLeafIndexMap.set(12n, 99n); + executionResult.noteHashLeafIndexMap.set(34n, 88n); + + const childExecution0 = emptyExecutionResult(); + childExecution0.noteHashLeafIndexMap.set(56n, 77n); + + const childExecution1 = emptyExecutionResult(); + childExecution1.noteHashLeafIndexMap.set(78n, 66n); + const grandchildExecution = emptyExecutionResult(); + grandchildExecution.noteHashLeafIndexMap.set(90n, 55n); + childExecution1.nestedExecutions = [grandchildExecution]; + + executionResult.nestedExecutions = [childExecution0, childExecution1]; + + const res = collectNoteHashLeafIndexMap(executionResult); + expect(res.size).toBe(5); + expect(res.get(12n)).toBe(99n); + expect(res.get(34n)).toBe(88n); + expect(res.get(56n)).toBe(77n); + expect(res.get(78n)).toBe(66n); + expect(res.get(90n)).toBe(55n); + }); }); - it('returns a map containing note hash leaf indexes for nested executions', () => { - executionResult.noteHashLeafIndexMap.set(12n, 99n); - executionResult.noteHashLeafIndexMap.set(34n, 88n); - - const childExecution0 = emptyExecutionResult(); - childExecution0.noteHashLeafIndexMap.set(56n, 77n); - - const childExecution1 = emptyExecutionResult(); - childExecution1.noteHashLeafIndexMap.set(78n, 66n); - const grandchildExecution = emptyExecutionResult(); - grandchildExecution.noteHashLeafIndexMap.set(90n, 55n); - childExecution1.nestedExecutions = [grandchildExecution]; - - executionResult.nestedExecutions = [childExecution0, childExecution1]; - - const res = collectNoteHashLeafIndexMap(executionResult); - expect(res.size).toBe(5); - expect(res.get(12n)).toBe(99n); - expect(res.get(34n)).toBe(88n); - expect(res.get(56n)).toBe(77n); - expect(res.get(78n)).toBe(66n); - expect(res.get(90n)).toBe(55n); + describe('collectNoteHashNullifierCounterMap', () => { + it('returns a map for note hash leaf indexes', () => { + executionResult.noteHashNullifierCounterMap = new Map(); + executionResult.noteHashNullifierCounterMap.set(12, 99); + executionResult.noteHashNullifierCounterMap.set(34, 88); + const res = collectNoteHashNullifierCounterMap(executionResult); + expect(res.size).toBe(2); + expect(res.get(12)).toBe(99); + expect(res.get(34)).toBe(88); + }); + + it('returns a map containing note hash leaf indexes for nested executions', () => { + executionResult.noteHashNullifierCounterMap.set(12, 99); + executionResult.noteHashNullifierCounterMap.set(34, 88); + + const childExecution0 = emptyExecutionResult(); + childExecution0.noteHashNullifierCounterMap.set(56, 77); + + const childExecution1 = emptyExecutionResult(); + childExecution1.noteHashNullifierCounterMap.set(78, 66); + const grandchildExecution = emptyExecutionResult(); + grandchildExecution.noteHashNullifierCounterMap.set(90, 55); + childExecution1.nestedExecutions = [grandchildExecution]; + + executionResult.nestedExecutions = [childExecution0, childExecution1]; + + const res = collectNoteHashNullifierCounterMap(executionResult); + expect(res.size).toBe(5); + expect(res.get(12)).toBe(99); + expect(res.get(34)).toBe(88); + expect(res.get(56)).toBe(77); + expect(res.get(78)).toBe(66); + expect(res.get(90)).toBe(55); + }); }); -}); - -describe('collectNullifiedNoteHashCounters', () => { - let executionResult: ExecutionResult; - - beforeEach(() => { - executionResult = emptyExecutionResult(); - }); - - it('returns a map for note hash leaf indexes', () => { - executionResult.nullifiedNoteHashCounters = new Map(); - executionResult.nullifiedNoteHashCounters.set(12, 99); - executionResult.nullifiedNoteHashCounters.set(34, 88); - const res = collectNullifiedNoteHashCounters(executionResult); - expect(res.size).toBe(2); - expect(res.get(12)).toBe(99); - expect(res.get(34)).toBe(88); - }); - - it('returns a map containing note hash leaf indexes for nested executions', () => { - executionResult.nullifiedNoteHashCounters.set(12, 99); - executionResult.nullifiedNoteHashCounters.set(34, 88); - - const childExecution0 = emptyExecutionResult(); - childExecution0.nullifiedNoteHashCounters.set(56, 77); - - const childExecution1 = emptyExecutionResult(); - childExecution1.nullifiedNoteHashCounters.set(78, 66); - const grandchildExecution = emptyExecutionResult(); - grandchildExecution.nullifiedNoteHashCounters.set(90, 55); - childExecution1.nestedExecutions = [grandchildExecution]; - - executionResult.nestedExecutions = [childExecution0, childExecution1]; - const res = collectNullifiedNoteHashCounters(executionResult); - expect(res.size).toBe(5); - expect(res.get(12)).toBe(99); - expect(res.get(34)).toBe(88); - expect(res.get(56)).toBe(77); - expect(res.get(78)).toBe(66); - expect(res.get(90)).toBe(55); + describe('getFinalMinRevertibleSideEffectCounter', () => { + beforeEach(() => { + const childExecution0 = emptyExecutionResult(); + const childExecution1 = emptyExecutionResult(); + const grandchildExecution = emptyExecutionResult(); + childExecution1.nestedExecutions = [grandchildExecution]; + executionResult.nestedExecutions = [childExecution0, childExecution1]; + }); + + it('returns a zero counter', () => { + const res = getFinalMinRevertibleSideEffectCounter(executionResult); + expect(res).toBe(0); + }); + + it('returns the actual counter', () => { + executionResult.callStackItem.publicInputs.minRevertibleSideEffectCounter = new Fr(123); + const res = getFinalMinRevertibleSideEffectCounter(executionResult); + expect(res).toBe(123); + }); + + it('returns the actual counter in a nested call', () => { + executionResult.nestedExecutions[1].callStackItem.publicInputs.minRevertibleSideEffectCounter = new Fr(123); + const res = getFinalMinRevertibleSideEffectCounter(executionResult); + expect(res).toBe(123); + }); }); }); diff --git a/yarn-project/simulator/src/client/execution_result.ts b/yarn-project/simulator/src/client/execution_result.ts index 53ca908c8d1..c73aa43df53 100644 --- a/yarn-project/simulator/src/client/execution_result.ts +++ b/yarn-project/simulator/src/client/execution_result.ts @@ -67,7 +67,7 @@ export interface ExecutionResult { /** The notes created in the executed function. */ newNotes: NoteAndSlot[]; /** Mapping of note hash counter to the counter of its nullifier. */ - nullifiedNoteHashCounters: Map; + noteHashNullifierCounterMap: Map; /** The raw return values of the executed function. */ returnValues: Fr[]; /** The nested executions. */ @@ -99,9 +99,12 @@ export function collectNoteHashLeafIndexMap(execResult: ExecutionResult, accum: return accum; } -export function collectNullifiedNoteHashCounters(execResult: ExecutionResult, accum: Map = new Map()) { - execResult.nullifiedNoteHashCounters.forEach((value, key) => accum.set(key, value)); - execResult.nestedExecutions.forEach(nested => collectNullifiedNoteHashCounters(nested, accum)); +export function collectNoteHashNullifierCounterMap( + execResult: ExecutionResult, + accum: Map = new Map(), +) { + execResult.noteHashNullifierCounterMap.forEach((value, key) => accum.set(key, value)); + execResult.nestedExecutions.forEach(nested => collectNoteHashNullifierCounterMap(nested, accum)); return accum; } @@ -112,11 +115,20 @@ export function collectNullifiedNoteHashCounters(execResult: ExecutionResult, ac */ function collectNoteEncryptedLogs( execResult: ExecutionResult, - nullifiedNoteHashCounters: Map, + noteHashNullifierCounterMap: Map, + minRevertibleSideEffectCounter: number, ): CountedLog[] { return [ - execResult.noteEncryptedLogs.filter(noteLog => !nullifiedNoteHashCounters.has(noteLog.noteHashCounter)), - ...execResult.nestedExecutions.flatMap(res => collectNoteEncryptedLogs(res, nullifiedNoteHashCounters)), + execResult.noteEncryptedLogs.filter(noteLog => { + const nullifierCounter = noteHashNullifierCounterMap.get(noteLog.noteHashCounter); + return ( + nullifierCounter === undefined || + (noteLog.noteHashCounter < minRevertibleSideEffectCounter && nullifierCounter >= minRevertibleSideEffectCounter) + ); + }), + ...execResult.nestedExecutions.flatMap(res => + collectNoteEncryptedLogs(res, noteHashNullifierCounterMap, minRevertibleSideEffectCounter), + ), ].flat(); } @@ -126,8 +138,9 @@ function collectNoteEncryptedLogs( * @returns All encrypted logs. */ export function collectSortedNoteEncryptedLogs(execResult: ExecutionResult): EncryptedNoteFunctionL2Logs { - const nullifiedNoteHashCounters = collectNullifiedNoteHashCounters(execResult); - const allLogs = collectNoteEncryptedLogs(execResult, nullifiedNoteHashCounters); + const noteHashNullifierCounterMap = collectNoteHashNullifierCounterMap(execResult); + const minRevertibleSideEffectCounter = getFinalMinRevertibleSideEffectCounter(execResult); + const allLogs = collectNoteEncryptedLogs(execResult, noteHashNullifierCounterMap, minRevertibleSideEffectCounter); const sortedLogs = sortByCounter(allLogs); return new EncryptedNoteFunctionL2Logs(sortedLogs.map(l => l.log)); } @@ -206,3 +219,10 @@ export function collectPublicTeardownFunctionCall(execResult: ExecutionResult): return PublicExecutionRequest.empty(); } + +export function getFinalMinRevertibleSideEffectCounter(execResult: ExecutionResult): number { + return execResult.nestedExecutions.reduce((counter, exec) => { + const nestedCounter = getFinalMinRevertibleSideEffectCounter(exec); + return nestedCounter ? nestedCounter : counter; + }, execResult.callStackItem.publicInputs.minRevertibleSideEffectCounter.toNumber()); +} diff --git a/yarn-project/simulator/src/client/private_execution.ts b/yarn-project/simulator/src/client/private_execution.ts index 335fe84a31a..008f48fbfd9 100644 --- a/yarn-project/simulator/src/client/private_execution.ts +++ b/yarn-project/simulator/src/client/private_execution.ts @@ -68,7 +68,7 @@ export async function executePrivateFunction( const noteHashLeafIndexMap = context.getNoteHashLeafIndexMap(); const newNotes = context.getNewNotes(); - const nullifiedNoteHashCounters = context.getNullifiedNoteHashCounters(); + const noteHashNullifierCounterMap = context.getNoteHashNullifierCounterMap(); const nestedExecutions = context.getNestedExecutions(); const enqueuedPublicFunctionCalls = context.getEnqueuedPublicFunctionCalls(); const publicTeardownFunctionCall = context.getPublicTeardownFunctionCall(); @@ -82,7 +82,7 @@ export async function executePrivateFunction( returnValues: rawReturnValues, noteHashLeafIndexMap, newNotes, - nullifiedNoteHashCounters, + noteHashNullifierCounterMap, vk: Buffer.from(artifact.verificationKey!, 'hex'), nestedExecutions, enqueuedPublicFunctionCalls, diff --git a/yarn-project/simulator/src/client/simulator.ts b/yarn-project/simulator/src/client/simulator.ts index e23bb42ea6d..79e61faea77 100644 --- a/yarn-project/simulator/src/client/simulator.ts +++ b/yarn-project/simulator/src/client/simulator.ts @@ -68,6 +68,9 @@ export class AcirSimulator { false, entryPointArtifact.isStatic, ); + + const txHash = request.toTxRequest().hash(); + const context = new ClientExecutionContext( contractAddress, request.firstCallArgsHash, @@ -76,7 +79,7 @@ export class AcirSimulator { header, request.authWitnesses, PackedValuesCache.create(request.argsOfCalls), - new ExecutionNoteCache(), + new ExecutionNoteCache(txHash), this.db, this.node, startSideEffectCounter, diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index f70dc666f93..c40167c3b0c 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -415,11 +415,13 @@ export class TXE implements TypedOracle { }, counter, ); + this.sideEffectsCounter = counter + 1; return Promise.resolve(); } - notifyNullifiedNote(innerNullifier: Fr, slottedNoteHash: Fr, _counter: number) { + notifyNullifiedNote(innerNullifier: Fr, slottedNoteHash: Fr, counter: number) { this.noteCache.nullifyNote(this.contractAddress, innerNullifier, slottedNoteHash); + this.sideEffectsCounter = counter + 1; return Promise.resolve(); } @@ -510,11 +512,13 @@ export class TXE implements TypedOracle { return publicDataWrites.map(write => write.newValue); } - emitEncryptedLog(_contractAddress: AztecAddress, _randomness: Fr, _encryptedNote: Buffer, _counter: number): void { + emitEncryptedLog(_contractAddress: AztecAddress, _randomness: Fr, _encryptedNote: Buffer, counter: number): void { + this.sideEffectsCounter = counter + 1; return; } - emitEncryptedNoteLog(_noteHashCounter: number, _encryptedNote: Buffer, _counter: number): void { + emitEncryptedNoteLog(_noteHashCounter: number, _encryptedNote: Buffer, counter: number): void { + this.sideEffectsCounter = counter + 1; return; } @@ -536,7 +540,8 @@ export class TXE implements TypedOracle { return taggedNote.encrypt(ephSk, recipient, ivpkM, ovKeys); } - emitUnencryptedLog(_log: UnencryptedL2Log, _counter: number): void { + emitUnencryptedLog(_log: UnencryptedL2Log, counter: number): void { + this.sideEffectsCounter = counter + 1; return; } @@ -609,7 +614,7 @@ export class TXE implements TypedOracle { // Apply side effects const endSideEffectCounter = publicInputs.endSideEffectCounter; - this.sideEffectsCounter = endSideEffectCounter.toNumber(); + this.sideEffectsCounter = endSideEffectCounter.toNumber() + 1; await this.addNullifiers( targetContractAddress, @@ -676,7 +681,12 @@ export class TXE implements TypedOracle { return `${artifact.name}:${f.name}`; } - async executePublicFunction(targetContractAddress: AztecAddress, args: Fr[], callContext: CallContext) { + async executePublicFunction( + targetContractAddress: AztecAddress, + args: Fr[], + callContext: CallContext, + counter: number, + ) { const header = Header.empty(); header.state = await this.trees.getStateReference(true); header.globalVariables.blockNumber = new Fr(await this.getBlockNumber()); @@ -707,6 +717,7 @@ export class TXE implements TypedOracle { TxContext.empty(), /* pendingNullifiers */ [], /* transactionFee */ Fr.ONE, + counter, ); } @@ -732,11 +743,16 @@ export class TXE implements TypedOracle { callContext.isStaticCall = isStaticCall; callContext.isDelegateCall = isDelegateCall; - const executionResult = await this.executePublicFunction(targetContractAddress, args, callContext); + const executionResult = await this.executePublicFunction( + targetContractAddress, + args, + callContext, + this.sideEffectsCounter, + ); // Apply side effects if (!executionResult.reverted) { - this.sideEffectsCounter += executionResult.endSideEffectCounter.toNumber(); + this.sideEffectsCounter = executionResult.endSideEffectCounter.toNumber() + 1; } this.setContractAddress(currentContractAddress); this.setMsgSender(currentMessageSender); @@ -745,51 +761,11 @@ export class TXE implements TypedOracle { return executionResult; } - async callPublicFunction( - targetContractAddress: AztecAddress, - functionSelector: FunctionSelector, - argsHash: Fr, - _sideEffectCounter: number, - isStaticCall: boolean, - isDelegateCall: boolean, - ): Promise { - // Store and modify env - const currentContractAddress = AztecAddress.fromField(this.contractAddress); - const currentMessageSender = AztecAddress.fromField(this.msgSender); - const currentFunctionSelector = FunctionSelector.fromField(this.functionSelector.toField()); - this.setMsgSender(this.contractAddress); - this.setContractAddress(targetContractAddress); - this.setFunctionSelector(functionSelector); - - const callContext = CallContext.empty(); - callContext.msgSender = this.msgSender; - callContext.functionSelector = this.functionSelector; - callContext.storageContractAddress = targetContractAddress; - callContext.isStaticCall = isStaticCall; - callContext.isDelegateCall = isDelegateCall; - - const args = this.packedValuesCache.unpack(argsHash); - - const executionResult = await this.executePublicFunction(targetContractAddress, args, callContext); - - if (executionResult.reverted) { - throw new Error(`Execution reverted with reason: ${executionResult.revertReason}`); - } - - // Apply side effects - this.sideEffectsCounter += executionResult.endSideEffectCounter.toNumber(); - this.setContractAddress(currentContractAddress); - this.setMsgSender(currentMessageSender); - this.setFunctionSelector(currentFunctionSelector); - - return executionResult.returnValues; - } - async enqueuePublicFunctionCall( targetContractAddress: AztecAddress, functionSelector: FunctionSelector, argsHash: Fr, - _sideEffectCounter: number, + sideEffectCounter: number, isStaticCall: boolean, isDelegateCall: boolean, ) { @@ -810,14 +786,19 @@ export class TXE implements TypedOracle { const args = this.packedValuesCache.unpack(argsHash); - const executionResult = await this.executePublicFunction(targetContractAddress, args, callContext); + const executionResult = await this.executePublicFunction( + targetContractAddress, + args, + callContext, + sideEffectCounter, + ); if (executionResult.reverted) { throw new Error(`Execution reverted with reason: ${executionResult.revertReason}`); } // Apply side effects - this.sideEffectsCounter += executionResult.endSideEffectCounter.toNumber(); + this.sideEffectsCounter = executionResult.endSideEffectCounter.toNumber() + 1; this.setContractAddress(currentContractAddress); this.setMsgSender(currentMessageSender); this.setFunctionSelector(currentFunctionSelector); @@ -843,6 +824,10 @@ export class TXE implements TypedOracle { ); } + notifySetMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: number) { + this.noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter); + } + aes128Encrypt(input: Buffer, initializationVector: Buffer, key: Buffer): Buffer { const aes128 = new Aes128(); return aes128.encryptBufferCBC(input, initializationVector, key); @@ -856,8 +841,9 @@ export class TXE implements TypedOracle { _contractAddress: AztecAddress, _randomness: Fr, _encryptedEvent: Buffer, - _counter: number, + counter: number, ): void { + this.sideEffectsCounter = counter + 1; return; } diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index a71ec4a388d..7918cd2d6ef 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -40,7 +40,8 @@ export class TXEService { const store = openTmpStore(true); const trees = await MerkleTrees.new(store, logger); const packedValuesCache = new PackedValuesCache(); - const noteCache = new ExecutionNoteCache(); + const txHash = new Fr(1); // The txHash is used for computing the revertible nullifiers for non-revertible note hashes. It can be any value for testing. + const noteCache = new ExecutionNoteCache(txHash); const keyStore = new KeyStore(store); const txeDatabase = new TXEDatabase(store); logger.info(`TXE service initialized`); @@ -711,6 +712,10 @@ export class TXEService { return toForeignCallResult([]); } + public notifySetMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: ForeignCallSingle) { + this.typedOracle.notifySetMinRevertibleSideEffectCounter(fromSingle(minRevertibleSideEffectCounter).toNumber()); + } + async getChainId() { return toForeignCallResult([toSingle(await this.typedOracle.getChainId())]); }