diff --git a/avm-transpiler/src/opcodes.rs b/avm-transpiler/src/opcodes.rs index 1de1f7803c89..d3ad47af1f44 100644 --- a/avm-transpiler/src/opcodes.rs +++ b/avm-transpiler/src/opcodes.rs @@ -72,14 +72,11 @@ pub enum AvmOpcode { // Misc DEBUGLOG, // Gadgets - KECCAK, POSEIDON2, SHA256COMPRESSION, KECCAKF1600, - PEDERSEN, // temp - may be removed, but alot of contracts rely on it ECADD, MSM, - PEDERSENCOMMITMENT, // temp // Conversions TORADIXLE, } @@ -170,14 +167,11 @@ impl AvmOpcode { AvmOpcode::DEBUGLOG => "DEBUGLOG", // Gadgets - AvmOpcode::KECCAK => "KECCAK", - AvmOpcode::KECCAKF1600 => "KECCAKF1600", AvmOpcode::POSEIDON2 => "POSEIDON2", AvmOpcode::SHA256COMPRESSION => "SHA256COMPRESSION", - AvmOpcode::PEDERSEN => "PEDERSEN", + AvmOpcode::KECCAKF1600 => "KECCAKF1600", AvmOpcode::ECADD => "ECADD", AvmOpcode::MSM => "MSM", - AvmOpcode::PEDERSENCOMMITMENT => "PEDERSENCOMMITMENT", // Conversions AvmOpcode::TORADIXLE => "TORADIXLE", } diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index 1b48fa90b7df..c453c1476f2e 100644 --- a/avm-transpiler/src/transpile.rs +++ b/avm-transpiler/src/transpile.rs @@ -963,7 +963,7 @@ fn generate_mov_instruction( } } -/// Black box functions, for the meantime only covers pedersen operations as the blackbox function api suits our current needs. +/// Black box functions /// (array goes in -> field element comes out) fn handle_black_box_function(avm_instrs: &mut Vec, operation: &BlackBoxOp) { match operation { @@ -989,32 +989,6 @@ fn handle_black_box_function(avm_instrs: &mut Vec, operation: &B ..Default::default() }); } - BlackBoxOp::PedersenHash { inputs, domain_separator, output } => { - let message_offset = inputs.pointer.to_usize(); - let message_size_offset = inputs.size.to_usize(); - - let index_offset = domain_separator.to_usize(); - let dest_offset = output.to_usize(); - - avm_instrs.push(AvmInstruction { - opcode: AvmOpcode::PEDERSEN, - indirect: Some( - AddressingModeBuilder::default() - .direct_operand(domain_separator) - .direct_operand(output) - .indirect_operand(&inputs.pointer) - .direct_operand(&inputs.size) - .build(), - ), - operands: vec![ - AvmOperand::U32 { value: index_offset as u32 }, - AvmOperand::U32 { value: dest_offset as u32 }, - AvmOperand::U32 { value: message_offset as u32 }, - AvmOperand::U32 { value: message_size_offset as u32 }, - ], - ..Default::default() - }); - } BlackBoxOp::Poseidon2Permutation { message, output, @@ -1151,31 +1125,6 @@ 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.to_usize(); - let input_size_offset = inputs.size.to_usize(); - let index_offset = domain_separator.to_usize(); - let output_offset = output.pointer.to_usize(); - avm_instrs.push(AvmInstruction { - opcode: AvmOpcode::PEDERSENCOMMITMENT, - indirect: Some( - AddressingModeBuilder::default() - .indirect_operand(&inputs.pointer) - .indirect_operand(&output.pointer) - .direct_operand(&inputs.size) - .direct_operand(domain_separator) - .build(), - ), - 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/tests/execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp index e0fefd75bd4b..4088cdf0ace2 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp @@ -1047,125 +1047,6 @@ TEST_F(AvmExecutionTests, keccakf1600OpCode) validate_trace(std::move(trace), public_inputs, calldata, returndata); } -// Positive test with Keccak. -TEST_F(AvmExecutionTests, keccakOpCode) -{ - // Test vectors from keccak256_test_cases in noir/noir-repo/acvm-repo/blackbox_solver/ - // Input: Uint8Array.from([0xbd]), - // Output: Uint8Array.from([ - // 0x5a, 0x50, 0x2f, 0x9f, 0xca, 0x46, 0x7b, 0x26, 0x6d, 0x5b, 0x78, 0x33, 0x65, 0x19, 0x37, 0xe8, 0x05, 0x27, - // 0x0c, 0xa3, 0xf3, 0xaf, 0x1c, 0x0d, 0xd2, 0x46, 0x2d, 0xca, 0x4b, 0x3b, 0x1a, 0xbf, - // ]), - std::vector expected_output = { - FF(0x5a), FF(0x50), FF(0x2f), FF(0x9f), FF(0xca), FF(0x46), FF(0x7b), FF(0x26), FF(0x6d), FF(0x5b), FF(0x78), - FF(0x33), FF(0x65), FF(0x19), FF(0x37), FF(0xe8), FF(0x05), FF(0x27), FF(0x0c), FF(0xa3), FF(0xf3), FF(0xaf), - FF(0x1c), FF(0x0d), FF(0xd2), FF(0x46), FF(0x2d), FF(0xca), FF(0x4b), FF(0x3b), FF(0x1a), FF(0xbf) - }; - std::string bytecode_hex = to_hex(OpCode::SET_8) + // Initial SET operations to store state and input - "00" // Indirect Flag - + to_hex(AvmMemoryTag::U8) + - "BD" // val 189 - "01" // dst_offset 1 - + to_hex(OpCode::SET_8) + // opcode SET for indirect src (input) - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "01" // value 1 (i.e. where the src will be read from) - "24" // input_offset 36 - + to_hex(OpCode::SET_8) + // - "00" // Indirect flag - + to_hex(AvmMemoryTag::U8) + - "01" // value 1 (i.e. where the length parameter is stored) - "25" // input_offset 37 - + to_hex(OpCode::SET_16) + // opcode SET for indirect dst (output) - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "0100" // value 256 (i.e. where the ouput will be written to) - "0023" // dst_offset 35 - + to_hex(OpCode::KECCAK) + // opcode KECCAK - "03" // Indirect flag (first 2 operands indirect) - "00000023" // output offset (indirect 35) - "00000024" // input offset (indirect 36) - "00000025" // length offset 37 - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "0100" // ret offset 256 - "0020"; // ret size 32 - - 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 calldata = std::vector(); - std::vector returndata = std::vector(); - 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 with Pedersen. -TEST_F(AvmExecutionTests, pedersenHashOpCode) -{ - // Test vectors from pedersen_hash in noir/noir-repo/acvm-repo/blackbox_solver/ - // input = [1,1] - // output = 0x1c446df60816b897cda124524e6b03f36df0cec333fad87617aab70d7861daa6 - // hash_index = 5; - FF expected_output = FF("0x1c446df60816b897cda124524e6b03f36df0cec333fad87617aab70d7861daa6"); - std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "00" // val - "00" // dst_offset - + to_hex(OpCode::SET_8) + // opcode SET - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "02" // val - "01" // dst_offset - + to_hex(OpCode::CALLDATACOPY) + // Calldatacopy - "00" // Indirect flag - "0000" // cd_offset - "0001" // copy_size - "0000" // dst_offset - + to_hex(OpCode::SET_8) + // opcode SET for direct hash index offset - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "05" // value 5 - "02" // input_offset 2 - + to_hex(OpCode::SET_8) + // opcode SET for indirect src - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "00" // value 0 (i.e. where the src will be read from) - "04" // dst_offset 4 - + to_hex(OpCode::SET_8) + // opcode SET for direct src_length - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "02" // value 2 - "05" // dst_offset - + to_hex(OpCode::PEDERSEN) + // opcode PEDERSEN - "04" // Indirect flag (3rd operand indirect) - "00000002" // hash_index offset (direct) - "00000003" // dest offset (direct) - "00000004" // input offset (indirect) - "00000005" // length offset (direct) - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "0003" // ret offset 3 - "0001"; // ret size 1 - - 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 = std::vector(); - std::vector calldata = { FF(1), FF(1) }; - auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec); - - EXPECT_EQ(returndata[0], expected_output); - - validate_trace(std::move(trace), public_inputs, calldata, returndata); -} -// // Positive test with EmbeddedCurveAdd TEST_F(AvmExecutionTests, embeddedCurveAddOpCode) { @@ -1320,79 +1201,6 @@ 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::SET_8) + // opcode SET - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "00" // val - "00" // dst_offset - + to_hex(OpCode::SET_8) + // opcode SET - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "02" // val - "01" + - to_hex(OpCode::CALLDATACOPY) + // Calldatacopy - "00" // Indirect flag - "0000" // cd_offset 0 - "0001" // copy_size (2 elements) - "0000" // dst_offset 0 - + to_hex(OpCode::SET_8) + // opcode SET for indirect input - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "00" // Input stored at memory 0 - "0b" // dst offset (11) - + to_hex(OpCode::SET_8) + // opcode SET for indirect output - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "20" // output offset - "0d" // dst offset - + to_hex(OpCode::SET_8) + // opcode SET for input length - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "02" // scalars length (2) - "02" + // dst offset (2) - to_hex(OpCode::SET_8) + // opcode SET for ctx index - "00" // Indirect flag - + to_hex(AvmMemoryTag::U32) + - "00" // ctx index (0) - "0f" + // 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 - "0020" // ret offset - "0003"; // 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/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.cpp index 8486677b3651..4ca2e3351b12 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/deserialization.cpp @@ -160,13 +160,10 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = // Gadgets // Gadgets - Hashing - { OpCode::KECCAK, { OperandType::INDIRECT8, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, { OpCode::POSEIDON2, { OperandType::INDIRECT8, OperandType::UINT16, OperandType::UINT16 } }, { OpCode::SHA256COMPRESSION, { OperandType::INDIRECT8, OperandType::UINT16, OperandType::UINT16, OperandType::UINT16 } }, { OpCode::KECCAKF1600, { OperandType::INDIRECT8, OperandType::UINT16, OperandType::UINT16, OperandType::UINT16 } }, - { OpCode::PEDERSEN, - { OperandType::INDIRECT8, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, // TEMP ECADD without relative memory { OpCode::ECADD, { OperandType::INDIRECT16, @@ -179,8 +176,6 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = OperandType::UINT16 } }, // dst_offset { OpCode::MSM, { OperandType::INDIRECT8, OperandType::UINT16, OperandType::UINT16, OperandType::UINT16, OperandType::UINT16 } }, - { OpCode::PEDERSENCOMMITMENT, - { OperandType::INDIRECT8, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, // Gadget - Conversion { OpCode::TORADIXLE, { OperandType::INDIRECT8, @@ -189,10 +184,6 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = OperandType::UINT16, OperandType::UINT16, OperandType::UINT8 } }, - // Gadgets - Unused for now - { OpCode::SHA256COMPRESSION, - { OperandType::INDIRECT8, OperandType::UINT16, OperandType::UINT16, OperandType::UINT16 } }, - { OpCode::KECCAKF1600, { OperandType::INDIRECT8, OperandType::UINT16, OperandType::UINT16, OperandType::UINT16 } }, }; const std::unordered_map OPERAND_TYPE_SIZE = { diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp index eedeac2f9846..28f69316bafe 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp @@ -693,26 +693,28 @@ std::vector Execution::gen_trace(std::vector const& instructio break; // Gadgets - case OpCode::KECCAK: - trace_builder.op_keccak(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3))); - - break; case OpCode::POSEIDON2: trace_builder.op_poseidon2_permutation(std::get(inst.operands.at(0)), std::get(inst.operands.at(1)), std::get(inst.operands.at(2))); break; - case OpCode::PEDERSEN: - trace_builder.op_pedersen_hash(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))); + + case OpCode::SHA256COMPRESSION: + trace_builder.op_sha256_compression(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3))); break; + + case OpCode::KECCAKF1600: + trace_builder.op_keccakf1600(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3))); + + break; + case OpCode::ECADD: trace_builder.op_ec_add(std::get(inst.operands.at(0)), std::get(inst.operands.at(1)), @@ -741,28 +743,6 @@ std::vector Execution::gen_trace(std::vector const& instructio std::get(inst.operands.at(5))); break; - case OpCode::SHA256COMPRESSION: - trace_builder.op_sha256_compression(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3))); - break; - - case OpCode::KECCAKF1600: - trace_builder.op_keccakf1600(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - 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/fixed_gas.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp index 9f37ad46e98d..e83ef216b5dd 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/fixed_gas.cpp @@ -83,15 +83,11 @@ const std::unordered_map GAS_COST_TABLE = { { OpCode::REVERT_8, make_cost(AVM_REVERT_BASE_L2_GAS, 0, AVM_REVERT_DYN_L2_GAS, 0) }, { OpCode::REVERT_16, make_cost(AVM_REVERT_BASE_L2_GAS, 0, AVM_REVERT_DYN_L2_GAS, 0) }, { OpCode::DEBUGLOG, make_cost(AVM_DEBUGLOG_BASE_L2_GAS, 0, 0, 0) }, - { OpCode::KECCAK, make_cost(AVM_KECCAK_BASE_L2_GAS, 0, AVM_KECCAK_DYN_L2_GAS, 0) }, { OpCode::POSEIDON2, make_cost(AVM_POSEIDON2_BASE_L2_GAS, 0, 0, 0) }, { OpCode::SHA256COMPRESSION, make_cost(AVM_SHA256COMPRESSION_BASE_L2_GAS, 0, 0, 0) }, { OpCode::KECCAKF1600, make_cost(AVM_KECCAKF1600_BASE_L2_GAS, 0, 0, 0) }, - { OpCode::PEDERSEN, make_cost(AVM_PEDERSEN_BASE_L2_GAS, 0, AVM_PEDERSEN_DYN_L2_GAS, 0) }, { OpCode::ECADD, make_cost(AVM_ECADD_BASE_L2_GAS, 0, 0, 0) }, { OpCode::MSM, make_cost(AVM_MSM_BASE_L2_GAS, 0, AVM_MSM_DYN_L2_GAS, 0) }, - { OpCode::PEDERSENCOMMITMENT, - make_cost(AVM_PEDERSENCOMMITMENT_BASE_L2_GAS, 0, AVM_PEDERSENCOMMITMENT_DYN_L2_GAS, 0) }, { OpCode::TORADIXLE, make_cost(AVM_TORADIXLE_BASE_L2_GAS, 0, AVM_TORADIXLE_DYN_L2_GAS, 0) }, }; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/keccak.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/keccak.cpp index f998505aa48c..d7f90159e631 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/keccak.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/keccak.cpp @@ -42,44 +42,4 @@ std::array AvmKeccakTraceBuilder::keccakf1600(uint32_t clk, std::a return output; } -std::array AvmKeccakTraceBuilder::keccak(uint32_t clk, std::vector input, uint32_t size) -{ - // Pad input to a multiple of 8 bytes - if (!input.empty()) { - input.resize(8 * ((input.size() - 1) / 8 + 1)); - } - - // We treat the input vector as an array of 64-bit integers for the avm (even though keccak takes in bytes). - std::vector vector_input; - for (size_t i = 0; i < input.size(); i += 8) { - auto uint64 = from_buffer(input, i); - vector_input.push_back(uint64); - } - auto result = ethash_keccak256(&input[0], size); - std::vector output_vector = {}; - std::array output_bytes = {}; - // The result encodes each limb in LE, we need to swap them to BE - // If we had C++23 we could use std::byteswap, but instead we write our own - for (size_t i = 0; i < 4; i++) { - std::vector le_bytes = to_buffer(result.word64s[i]); - // Reverse the bytes - std::ranges::reverse(le_bytes); - // Convert the bytes back to a uint64_t - auto be_u64 = from_buffer(le_bytes); - output_vector.push_back(be_u64); - // Copy the bytes to the output - for (size_t j = 0; j < 8; j++) { - output_bytes[i * 8 + j] = le_bytes[j]; - } - } - keccak_trace.push_back(KeccakTraceEntry{ - .clk = clk, - .input = vector_input, - .output = output_vector, - .input_size = size, - .output_size = 4, - }); - return output_bytes; -} - } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/keccak.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/keccak.hpp index 925feaf34400..621b8985f942 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/keccak.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/keccak.hpp @@ -24,7 +24,6 @@ class AvmKeccakTraceBuilder { std::vector finalize(); std::array keccakf1600(uint32_t clk, std::array input); - std::array keccak(uint32_t clk, std::vector input, uint32_t size); private: std::vector keccak_trace; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/pedersen.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/pedersen.cpp deleted file mode 100644 index 3d94837692bf..000000000000 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/pedersen.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "barretenberg/crypto/pedersen_hash/pedersen.hpp" -#include "barretenberg/vm/avm/trace/common.hpp" -#include "barretenberg/vm/avm/trace/gadgets/pedersen.hpp" - -namespace bb::avm_trace { - -std::vector AvmPedersenTraceBuilder::finalize() -{ - return std::move(pedersen_trace); -} - -void AvmPedersenTraceBuilder::reset() -{ - pedersen_trace.clear(); - pedersen_trace.shrink_to_fit(); // Reclaim memory. -} - -FF AvmPedersenTraceBuilder::pedersen_hash(const std::vector& inputs, uint32_t offset, uint32_t clk) -{ - crypto::GeneratorContext ctx; - ctx.offset = offset; - // Use the standard domain separator starting at ctx.offset - FF output = crypto::pedersen_hash::hash(inputs, ctx); - pedersen_trace.push_back({ clk, inputs, output }); - - return output; -} - -} // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/pedersen.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/pedersen.hpp deleted file mode 100644 index 9fce7b70cb75..000000000000 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/pedersen.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "barretenberg/vm/avm/trace/common.hpp" - -#include -#include - -namespace bb::avm_trace { - -class AvmPedersenTraceBuilder { - public: - struct PedersenTraceEntry { - uint32_t clk = 0; - std::vector input; - FF output; - }; - - AvmPedersenTraceBuilder() = default; - void reset(); - // Finalize the trace - std::vector finalize(); - - // Note that this version of pedersen_hash is defined over Grumpkin (we could make it generic later if we wanted to - // also support BBJubJub) The inputs are Fr_BN254, and the output is Fq_Grumpkin (which is also Fr_BN254 since - // Grumpkin and BN254 form a 2-cycle). - FF pedersen_hash(const std::vector& inputs, uint32_t offset, uint32_t clk); - - private: - std::vector pedersen_trace; -}; - -} // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/sha256.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/sha256.cpp index ff51cbab113f..848e4a4eb57d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/sha256.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/sha256.cpp @@ -118,12 +118,4 @@ std::array AvmSha256TraceBuilder::sha256_compression(const std::arr return output; } -std::array AvmSha256TraceBuilder::sha256(const std::vector& input, uint32_t clk) -{ - auto output = crypto::sha256(input); - // Cant push here since we are not using the same format as the sha256_compression - sha256_trace.push_back(Sha256TraceEntry{ clk, {}, {}, {} }); - return output; -} - } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/sha256.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/sha256.hpp index 38a4272e08ac..d52fe438d61b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/sha256.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/sha256.hpp @@ -25,7 +25,6 @@ class AvmSha256TraceBuilder { std::array sha256_compression(const std::array& h_init, const std::array& input, uint32_t clk); - std::array sha256(const std::vector& input, uint32_t clk); private: std::vector sha256_trace; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.cpp index 724ee32e2cc0..ad9b5b39ecaf 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.cpp @@ -159,16 +159,12 @@ std::string to_string(OpCode opcode) case OpCode::DEBUGLOG: return "DEBUGLOG"; // Gadgets - case OpCode::KECCAK: - return "KECCAK"; case OpCode::POSEIDON2: return "POSEIDON2"; case OpCode::SHA256COMPRESSION: return "SHA256COMPRESSION"; case OpCode::KECCAKF1600: return "KECCAKF1600"; - case OpCode::PEDERSEN: - return "PEDERSEN"; case OpCode::ECADD: return "ECADD"; case OpCode::MSM: diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.hpp index feab28e807a7..afea3e251da5 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/opcode.hpp @@ -99,14 +99,11 @@ enum class OpCode : uint8_t { DEBUGLOG, // Gadgets - KECCAK, POSEIDON2, SHA256COMPRESSION, KECCAKF1600, - PEDERSEN, ECADD, MSM, - PEDERSENCOMMITMENT, // Conversions TORADIXLE, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp index 0f638ca0811f..c623f257309a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp @@ -16,7 +16,6 @@ #include "barretenberg/common/assert.hpp" #include "barretenberg/common/serialize.hpp" #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" @@ -2763,65 +2762,6 @@ std::vector AvmTraceBuilder::op_revert(uint8_t indirect, uint32_t ret_offset * GADGETS **************************************************************************************************/ -/** - * @brief Keccak with direct or indirect memory access. - * Keccak is TEMPORARY while we wait for the transition to keccakf1600, so we do the minimal to store the result - * @param indirect byte encoding information about indirect/direct memory access. - * @param output_offset An index in memory pointing to where the first u8 value of the output array should be - * stored. - * @param input_offset An index in memory pointing to the first u8 value of the input array to be used - * @param input_size offset An index in memory pointing to the size of the input array. - */ -void AvmTraceBuilder::op_keccak(uint8_t indirect, - uint32_t output_offset, - uint32_t input_offset, - uint32_t input_size_offset) -{ - auto clk = static_cast(main_trace.size()) + 1; - - auto [resolved_output_offset, resolved_input_offset, resolved_input_size_offset] = - Addressing<3>::fromWire(indirect, call_ptr) - .resolve({ output_offset, input_offset, input_size_offset }, mem_trace_builder); - - // Read the input length first - auto input_length_read = constrained_read_from_memory( - call_ptr, clk, resolved_input_size_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IB); - - // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::KECCAK, static_cast(input_length_read.val)); - - // Store the clock time that we will use to line up the gadget later - auto keccak_op_clk = clk; - main_trace.push_back(Row{ - .main_clk = clk, - .main_ib = input_length_read.val, // Message Length - .main_ind_addr_b = FF(input_length_read.indirect_address), - .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_b = FF(input_length_read.direct_address), // length - .main_pc = FF(pc++), - .main_r_in_tag = FF(static_cast(AvmMemoryTag::U32)), - .main_sel_mem_op_b = FF(1), - .main_sel_op_keccak = FF(1), - .main_sel_resolve_ind_addr_b = FF(static_cast(input_length_read.is_indirect)), - .main_tag_err = FF(static_cast(!input_length_read.tag_match)), - }); - clk++; - - std::vector input; - input.reserve(uint32_t(input_length_read.val)); - // Read the slice length from memory - read_slice_from_memory(resolved_input_offset, uint32_t(input_length_read.val), input); - - std::array result = keccak_trace_builder.keccak(keccak_op_clk, input, uint32_t(input_length_read.val)); - // We convert the results to field elements here - std::vector ff_result; - for (uint32_t i = 0; i < 32; i++) { - ff_result.emplace_back(result[i]); - } - // Write the result to memory after - write_slice_to_memory(resolved_output_offset, AvmMemoryTag::U8, ff_result); -} - /** * @brief Poseidon2 Permutation with direct or indirect memory access. * @@ -2935,55 +2875,158 @@ void AvmTraceBuilder::op_poseidon2_permutation(uint8_t indirect, uint32_t input_ } /** - * @brief Pedersen Hash with direct or indirect memory access. + * @brief SHA256 Compression with direct or indirect memory access. + * * @param indirect byte encoding information about indirect/direct memory access. - * @param gen_ctx_offset An index in memory pointing to where the u32 offset for the pedersen hash generators. - * @param input_offset An index in memory pointing to the first FF value of the input array to be used in the next - * @param input_size offset An index in memory pointing to the size of the input array. + * @param state_offset An index in memory pointing to the first U32 value of the state array to be used in the next + * instance of sha256 compression. + * @param input_offset An index in memory pointing to the first U32 value of the input array to be used in the next + * instance of sha256 compression. + * @param output_offset An index in memory pointing to where the first U32 value of the output array should be + * stored. */ -void AvmTraceBuilder::op_pedersen_hash(uint8_t indirect, - uint32_t gen_ctx_offset, - uint32_t output_offset, - uint32_t input_offset, - uint32_t input_size_offset) +void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, + uint32_t output_offset, + uint32_t state_offset, + uint32_t inputs_offset) { + // The clk plays a crucial role in this function as we attempt to write across multiple lines in the main trace. auto clk = static_cast(main_trace.size()) + 1; - auto [resolved_gen_ctx_offset, resolved_output_offset, resolved_input_offset, resolved_input_size_offset] = - Addressing<4>::fromWire(indirect, call_ptr) - .resolve({ gen_ctx_offset, output_offset, input_offset, input_size_offset }, mem_trace_builder); + // Resolve the indirect flags, the results of this function are used to determine the memory offsets + // that point to the starting memory addresses for the input and output values. + auto [resolved_output_offset, resolved_state_offset, resolved_inputs_offset] = + Addressing<3>::fromWire(indirect, call_ptr) + .resolve({ output_offset, state_offset, inputs_offset }, mem_trace_builder); + + auto read_a = constrained_read_from_memory( + call_ptr, clk, resolved_state_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IA); + auto read_b = constrained_read_from_memory( + call_ptr, clk, resolved_inputs_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; + + // Constrain gas cost + gas_trace_builder.constrain_gas(clk, OpCode::SHA256COMPRESSION); + + // Since the above adds mem_reads in the mem_trace_builder at clk, we need to follow up resolving the reads in + // the main trace at the same clk cycle to preserve the cross-table permutation + // + // TODO<#6383>: We put the first value of each of the input, output (which is 0 at this point) and h_init arrays + // into the main trace at the intermediate registers simply for the permutation check, in the future this will + // change. + // Note: we could avoid output being zero if we loaded the input and state beforehand (with a new function that + // did not lay down constraints), but this is a simplification + main_trace.push_back(Row{ + .main_clk = clk, + .main_ia = read_a.val, // First element of state + .main_ib = read_b.val, // First element of input + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), + .main_internal_return_ptr = FF(internal_return_ptr), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), + .main_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_op_sha256 = FF(1), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_tag_err = FF(static_cast(!tag_match)), + }); + // We store the current clk this main trace row occurred so that we can line up the sha256 gadget operation at + // the same clk later. + auto sha_op_clk = clk; + // We need to increment the clk + clk++; + // State array input is fixed to 256 bits + std::vector h_init_vec; + // Input for hash is expanded to 512 bits + std::vector input_vec; + // Read results are written to h_init array. + read_slice_from_memory(resolved_state_offset, 8, h_init_vec); + // Read results are written to input array + read_slice_from_memory(resolved_inputs_offset, 16, input_vec); + + // Now that we have read all the values, we can perform the operation to get the resulting witness. + // Note: We use the sha_op_clk to ensure that the sha256 operation is performed at the same clock cycle as the + // main trace that has the selector + std::array h_init = vec_to_arr(h_init_vec); + std::array input = vec_to_arr(input_vec); + + std::array result = sha256_trace_builder.sha256_compression(h_init, input, sha_op_clk); + // We convert the results to field elements here + std::vector ff_result; + for (uint32_t i = 0; i < 8; i++) { + ff_result.emplace_back(result[i]); + } + + // Write the result to memory after + write_slice_to_memory(resolved_output_offset, AvmMemoryTag::U32, ff_result); +} + +/** + * @brief Keccakf1600 with direct or indirect memory access. + * This function temporarily has the same interface as the kecccak opcode for compatibility, when the keccak + * migration is complete (to keccakf1600) We will update this function call as we will not likely need + * input_size_offset + * @param indirect byte encoding information about indirect/direct memory access. + * @param output_offset An index in memory pointing to where the first u64 value of the output array should be + * stored. + * @param input_offset An index in memory pointing to the first u64 value of the input array to be used in the next + * instance of poseidon2 permutation. + * @param input_size offset An index in memory pointing to the size of the input array. Temporary while we maintain + * the same interface as keccak (this is fixed to 25) + */ +void AvmTraceBuilder::op_keccakf1600(uint8_t indirect, + uint32_t output_offset, + uint32_t input_offset, + [[maybe_unused]] uint32_t input_size_offset) +{ + // What happens if the input_size_offset is > 25 when the state is more that that? + auto clk = static_cast(main_trace.size()) + 1; + auto [resolved_output_offset, resolved_input_offset] = + Addressing<2>::fromWire(indirect, call_ptr).resolve({ output_offset, input_offset }, mem_trace_builder); auto input_read = constrained_read_from_memory( - call_ptr, clk, resolved_input_offset, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::IA); - // auto input_size_read = constrained_read_from_memory( - // call_ptr, clk, resolved_input_size_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IB); - // auto gen_ctx_read = constrained_read_from_memory( - // call_ptr, clk, resolved_gen_ctx_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IC); - auto input_size_read = unconstrained_read_from_memory(resolved_input_size_offset); - auto gen_ctx_read = unconstrained_read_from_memory(resolved_gen_ctx_offset); + call_ptr, clk, resolved_input_offset, AvmMemoryTag::U64, AvmMemoryTag::U0, IntermRegister::IA); + auto output_read = constrained_read_from_memory( + call_ptr, clk, resolved_output_offset, AvmMemoryTag::U64, AvmMemoryTag::U0, IntermRegister::IC); + bool tag_match = input_read.tag_match && output_read.tag_match; // Constrain gas cost - // TODO(dbanks12): need tag check u32 here on input size - gas_trace_builder.constrain_gas(clk, OpCode::PEDERSEN, static_cast(input_size_read)); + gas_trace_builder.constrain_gas(clk, OpCode::KECCAKF1600); - // We read the input and output addresses in one row as they should contain FF elements main_trace.push_back(Row{ .main_clk = clk, - .main_ia = input_read.val, // First element of input + .main_ia = input_read.val, // First element of input + .main_ic = output_read.val, // First element of output .main_ind_addr_a = FF(input_read.indirect_address), + .main_ind_addr_c = FF(output_read.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), .main_mem_addr_a = FF(input_read.direct_address), + .main_mem_addr_c = FF(output_read.direct_address), .main_pc = FF(pc++), - .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), + .main_r_in_tag = FF(static_cast(AvmMemoryTag::U64)), .main_sel_mem_op_a = FF(1), - .main_sel_op_pedersen = FF(1), + .main_sel_mem_op_c = FF(1), + .main_sel_op_keccak = FF(1), .main_sel_resolve_ind_addr_a = FF(static_cast(input_read.is_indirect)), - .main_tag_err = FF(static_cast(!input_read.tag_match)), + .main_sel_resolve_ind_addr_c = FF(static_cast(output_read.is_indirect)), + .main_tag_err = FF(static_cast(!tag_match)), }); - std::vector inputs; - read_slice_from_memory(resolved_input_offset, static_cast(input_size_read), inputs); - FF output = pedersen_trace_builder.pedersen_hash(inputs, static_cast(gen_ctx_read), clk); - write_slice_to_memory(resolved_output_offset, AvmMemoryTag::FF, std::vector{ output }); + // Array input is fixed to 1600 bits + std::vector input_vec; + // Read results are written to input array + read_slice_from_memory(resolved_input_offset, 25, input_vec); + std::array input = vec_to_arr(input_vec); + + // Now that we have read all the values, we can perform the operation to get the resulting witness. + // Note: We use the keccak_op_clk to ensure that the keccakf1600 operation is performed at the same clock cycle + // as the main trace that has the selector + std::array result = keccak_trace_builder.keccakf1600(clk, input); + // Write the result to memory after + write_slice_to_memory(resolved_output_offset, AvmMemoryTag::U64, result); } void AvmTraceBuilder::op_ec_add(uint16_t indirect, @@ -3129,43 +3172,6 @@ void AvmTraceBuilder::op_variable_msm(uint8_t indirect, write_to_memory(resolved_output_offset + 2, result.is_point_at_infinity(), AvmMemoryTag::U8); } -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] = - Addressing<4>::fromWire(indirect, call_ptr) - .resolve({ input_offset, output_offset, input_size_offset, gen_ctx_offset }, mem_trace_builder); - - auto input_length_read = unconstrained_read_from_memory(resolved_input_size_offset); - auto gen_ctx_read = unconstrained_read_from_memory(resolved_gen_ctx_offset); - - std::vector inputs; - read_slice_from_memory(resolved_input_offset, uint32_t(input_length_read), inputs); - - grumpkin::g1::affine_element result = crypto::pedersen_commitment::commit_native(inputs, uint32_t(gen_ctx_read)); - - main_trace.push_back(Row{ - .main_clk = clk, - .main_internal_return_ptr = FF(internal_return_ptr), - .main_pc = FF(pc++), - .main_sel_op_pedersen_commit = 1, - .main_tag_err = FF(0), - }); - - // TODO(dbanks12): length needs to fit into u32 here or it will certainly - // run out of gas. Casting/truncating here is not secure. - gas_trace_builder.constrain_gas(clk, OpCode::PEDERSENCOMMITMENT, static_cast(input_length_read)); - - // Write the result back to memory [x, y, inf] with tags [FF, FF, U8] - write_to_memory(resolved_output_offset, result.x, AvmMemoryTag::FF); - write_to_memory(resolved_output_offset + 1, result.y, AvmMemoryTag::FF); - write_to_memory(resolved_output_offset + 2, result.is_point_at_infinity(), AvmMemoryTag::U8); -} - /************************************************************************************************** * CONVERSIONS **************************************************************************************************/ @@ -3254,165 +3260,6 @@ void AvmTraceBuilder::op_to_radix_le(uint8_t indirect, write_slice_to_memory(resolved_dst_offset, w_in_tag, res); } -/************************************************************************************************** - * FUTURE GADGETS -- pending changes in noir - **************************************************************************************************/ - -/** - * @brief SHA256 Compression with direct or indirect memory access. - * - * @param indirect byte encoding information about indirect/direct memory access. - * @param state_offset An index in memory pointing to the first U32 value of the state array to be used in the next - * instance of sha256 compression. - * @param input_offset An index in memory pointing to the first U32 value of the input array to be used in the next - * instance of sha256 compression. - * @param output_offset An index in memory pointing to where the first U32 value of the output array should be - * stored. - */ -void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, - uint32_t output_offset, - uint32_t state_offset, - uint32_t inputs_offset) -{ - // The clk plays a crucial role in this function as we attempt to write across multiple lines in the main trace. - auto clk = static_cast(main_trace.size()) + 1; - - // Resolve the indirect flags, the results of this function are used to determine the memory offsets - // that point to the starting memory addresses for the input and output values. - auto [resolved_output_offset, resolved_state_offset, resolved_inputs_offset] = - Addressing<3>::fromWire(indirect, call_ptr) - .resolve({ output_offset, state_offset, inputs_offset }, mem_trace_builder); - - auto read_a = constrained_read_from_memory( - call_ptr, clk, resolved_state_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IA); - auto read_b = constrained_read_from_memory( - call_ptr, clk, resolved_inputs_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IB); - bool tag_match = read_a.tag_match && read_b.tag_match; - - // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::SHA256COMPRESSION); - - // Since the above adds mem_reads in the mem_trace_builder at clk, we need to follow up resolving the reads in - // the main trace at the same clk cycle to preserve the cross-table permutation - // - // TODO<#6383>: We put the first value of each of the input, output (which is 0 at this point) and h_init arrays - // into the main trace at the intermediate registers simply for the permutation check, in the future this will - // change. - // Note: we could avoid output being zero if we loaded the input and state beforehand (with a new function that - // did not lay down constraints), but this is a simplification - main_trace.push_back(Row{ - .main_clk = clk, - .main_ia = read_a.val, // First element of state - .main_ib = read_b.val, // First element of input - .main_ind_addr_a = FF(read_a.indirect_address), - .main_ind_addr_b = FF(read_b.indirect_address), - .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(read_a.direct_address), - .main_mem_addr_b = FF(read_b.direct_address), - .main_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_op_sha256 = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), - .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), - .main_tag_err = FF(static_cast(!tag_match)), - }); - // We store the current clk this main trace row occurred so that we can line up the sha256 gadget operation at - // the same clk later. - auto sha_op_clk = clk; - // We need to increment the clk - clk++; - // State array input is fixed to 256 bits - std::vector h_init_vec; - // Input for hash is expanded to 512 bits - std::vector input_vec; - // Read results are written to h_init array. - read_slice_from_memory(resolved_state_offset, 8, h_init_vec); - // Read results are written to input array - read_slice_from_memory(resolved_inputs_offset, 16, input_vec); - - // Now that we have read all the values, we can perform the operation to get the resulting witness. - // Note: We use the sha_op_clk to ensure that the sha256 operation is performed at the same clock cycle as the - // main trace that has the selector - std::array h_init = vec_to_arr(h_init_vec); - std::array input = vec_to_arr(input_vec); - - std::array result = sha256_trace_builder.sha256_compression(h_init, input, sha_op_clk); - // We convert the results to field elements here - std::vector ff_result; - for (uint32_t i = 0; i < 8; i++) { - ff_result.emplace_back(result[i]); - } - - // Write the result to memory after - write_slice_to_memory(resolved_output_offset, AvmMemoryTag::U32, ff_result); -} - -/** - * @brief Keccakf1600 with direct or indirect memory access. - * This function temporarily has the same interface as the kecccak opcode for compatibility, when the keccak - * migration is complete (to keccakf1600) We will update this function call as we will not likely need - * input_size_offset - * @param indirect byte encoding information about indirect/direct memory access. - * @param output_offset An index in memory pointing to where the first u64 value of the output array should be - * stored. - * @param input_offset An index in memory pointing to the first u64 value of the input array to be used in the next - * instance of poseidon2 permutation. - * @param input_size offset An index in memory pointing to the size of the input array. Temporary while we maintain - * the same interface as keccak (this is fixed to 25) - */ -void AvmTraceBuilder::op_keccakf1600(uint8_t indirect, - uint32_t output_offset, - uint32_t input_offset, - [[maybe_unused]] uint32_t input_size_offset) -{ - // What happens if the input_size_offset is > 25 when the state is more that that? - auto clk = static_cast(main_trace.size()) + 1; - auto [resolved_output_offset, resolved_input_offset] = - Addressing<2>::fromWire(indirect, call_ptr).resolve({ output_offset, input_offset }, mem_trace_builder); - auto input_read = constrained_read_from_memory( - call_ptr, clk, resolved_input_offset, AvmMemoryTag::U64, AvmMemoryTag::U0, IntermRegister::IA); - auto output_read = constrained_read_from_memory( - call_ptr, clk, resolved_output_offset, AvmMemoryTag::U64, AvmMemoryTag::U0, IntermRegister::IC); - bool tag_match = input_read.tag_match && output_read.tag_match; - - // Constrain gas cost - gas_trace_builder.constrain_gas(clk, OpCode::KECCAKF1600); - - main_trace.push_back(Row{ - .main_clk = clk, - .main_ia = input_read.val, // First element of input - .main_ic = output_read.val, // First element of output - .main_ind_addr_a = FF(input_read.indirect_address), - .main_ind_addr_c = FF(output_read.indirect_address), - .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(input_read.direct_address), - .main_mem_addr_c = FF(output_read.direct_address), - .main_pc = FF(pc++), - .main_r_in_tag = FF(static_cast(AvmMemoryTag::U64)), - .main_sel_mem_op_a = FF(1), - .main_sel_mem_op_c = FF(1), - .main_sel_op_keccak = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(input_read.is_indirect)), - .main_sel_resolve_ind_addr_c = FF(static_cast(output_read.is_indirect)), - .main_tag_err = FF(static_cast(!tag_match)), - }); - - // Array input is fixed to 1600 bits - std::vector input_vec; - // Read results are written to input array - read_slice_from_memory(resolved_input_offset, 25, input_vec); - std::array input = vec_to_arr(input_vec); - - // Now that we have read all the values, we can perform the operation to get the resulting witness. - // Note: We use the keccak_op_clk to ensure that the keccakf1600 operation is performed at the same clock cycle - // as the main trace that has the selector - std::array result = keccak_trace_builder.keccakf1600(clk, input); - // Write the result to memory after - write_slice_to_memory(resolved_output_offset, AvmMemoryTag::U64, result); -} - /************************************************************************************************** * FINALIZE **************************************************************************************************/ @@ -3435,7 +3282,6 @@ std::vector AvmTraceBuilder::finalize() auto sha256_trace = sha256_trace_builder.finalize(); auto poseidon2_trace = poseidon2_trace_builder.finalize(); auto keccak_trace = keccak_trace_builder.finalize(); - auto pedersen_trace = pedersen_trace_builder.finalize(); auto slice_trace = slice_trace_builder.finalize(); const auto& fixed_gas_table = FixedGasTable::get(); size_t mem_trace_size = mem_trace.size(); @@ -3445,7 +3291,6 @@ std::vector AvmTraceBuilder::finalize() size_t sha256_trace_size = sha256_trace.size(); size_t poseidon2_trace_size = poseidon2_trace.size(); size_t keccak_trace_size = keccak_trace.size(); - size_t pedersen_trace_size = pedersen_trace.size(); size_t bin_trace_size = bin_trace_builder.size(); size_t gas_trace_size = gas_trace_builder.size(); size_t slice_trace_size = slice_trace.size(); @@ -3454,11 +3299,11 @@ std::vector AvmTraceBuilder::finalize() // Range check size is 1 less than it needs to be since we insert a "first row" at the top of the trace at the // end, with clk 0 (this doubles as our range check) size_t const range_check_size = range_check_required ? UINT16_MAX : 0; - std::vector trace_sizes = { mem_trace_size, main_trace_size + 1, alu_trace_size, - range_check_size, conv_trace_size, sha256_trace_size, - poseidon2_trace_size, pedersen_trace_size, gas_trace_size + 1, - KERNEL_INPUTS_LENGTH, KERNEL_OUTPUTS_LENGTH, kernel_trace_size, - fixed_gas_table.size(), slice_trace_size, calldata.size() }; + std::vector trace_sizes = { mem_trace_size, main_trace_size + 1, alu_trace_size, + range_check_size, conv_trace_size, sha256_trace_size, + poseidon2_trace_size, gas_trace_size + 1, KERNEL_INPUTS_LENGTH, + KERNEL_OUTPUTS_LENGTH, kernel_trace_size, fixed_gas_table.size(), + slice_trace_size, calldata.size() }; auto trace_size = std::max_element(trace_sizes.begin(), trace_sizes.end()); // Before making any changes to the main trace, mark the real rows. @@ -3655,15 +3500,6 @@ std::vector AvmTraceBuilder::finalize() dest.keccakf1600_sel_keccakf1600 = FF(1); } - // Add Pedersen Gadget table - for (size_t i = 0; i < pedersen_trace_size; i++) { - auto const& src = pedersen_trace.at(i); - auto& dest = main_trace.at(i); - dest.pedersen_clk = FF(src.clk); - dest.pedersen_input = FF(src.input[0]); - dest.pedersen_sel_pedersen = FF(1); - } - /********************************************************************************************** * SLICE TRACE INCLUSION **********************************************************************************************/ @@ -3856,8 +3692,6 @@ std::vector AvmTraceBuilder::finalize() sha256_trace_size, "\n\tposeidon2_trace_size: ", poseidon2_trace_size, - "\n\tpedersen_trace_size: ", - pedersen_trace_size, "\n\tgas_trace_size: ", gas_trace_size, "\n\tfixed_gas_table_size: ", @@ -3900,7 +3734,6 @@ void AvmTraceBuilder::reset() sha256_trace_builder.reset(); poseidon2_trace_builder.reset(); keccak_trace_builder.reset(); - pedersen_trace_builder.reset(); slice_trace_builder.reset(); external_call_counter = 0; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp index dc8e743c3d1e..3a3b275228d4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp @@ -8,7 +8,6 @@ #include "barretenberg/vm/avm/trace/gadgets/conversion_trace.hpp" #include "barretenberg/vm/avm/trace/gadgets/ecc.hpp" #include "barretenberg/vm/avm/trace/gadgets/keccak.hpp" -#include "barretenberg/vm/avm/trace/gadgets/pedersen.hpp" #include "barretenberg/vm/avm/trace/gadgets/poseidon2.hpp" #include "barretenberg/vm/avm/trace/gadgets/range_check.hpp" #include "barretenberg/vm/avm/trace/gadgets/sha256.hpp" @@ -146,11 +145,6 @@ class AvmTraceBuilder { // Gadgets void op_keccak(uint8_t indirect, uint32_t output_offset, uint32_t input_offset, uint32_t input_size_offset); void op_poseidon2_permutation(uint8_t indirect, uint32_t input_offset, uint32_t output_offset); - void op_pedersen_hash(uint8_t indirect, - uint32_t gen_ctx_offset, - uint32_t output_offset, - uint32_t input_offset, - uint32_t input_size_offset); void op_ec_add(uint16_t indirect, uint32_t lhs_x_offset, uint32_t lhs_y_offset, @@ -164,11 +158,6 @@ 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, @@ -228,7 +217,6 @@ class AvmTraceBuilder { AvmSha256TraceBuilder sha256_trace_builder; AvmPoseidon2TraceBuilder poseidon2_trace_builder; AvmKeccakTraceBuilder keccak_trace_builder; - AvmPedersenTraceBuilder pedersen_trace_builder; AvmEccTraceBuilder ecc_trace_builder; AvmSliceTraceBuilder slice_trace_builder; AvmRangeCheckBuilder range_check_builder; diff --git a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp index e86b21518a8e..628e2c7e140e 100644 --- a/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/aztec_constants.hpp @@ -110,16 +110,12 @@ #define AVM_RETURN_BASE_L2_GAS 28 #define AVM_REVERT_BASE_L2_GAS 28 #define AVM_DEBUGLOG_BASE_L2_GAS 12 -#define AVM_KECCAK_BASE_L2_GAS 3000 #define AVM_POSEIDON2_BASE_L2_GAS 78 -#define AVM_SHA256_BASE_L2_GAS 2610 -#define AVM_PEDERSEN_BASE_L2_GAS 1000 +#define AVM_SHA256COMPRESSION_BASE_L2_GAS 261 +#define AVM_KECCAKF1600_BASE_L2_GAS 300 #define AVM_ECADD_BASE_L2_GAS 62 #define AVM_MSM_BASE_L2_GAS 1000 -#define AVM_PEDERSENCOMMITMENT_BASE_L2_GAS 1000 #define AVM_TORADIXLE_BASE_L2_GAS 46 -#define AVM_SHA256COMPRESSION_BASE_L2_GAS 261 -#define AVM_KECCAKF1600_BASE_L2_GAS 300 #define AVM_CALLDATACOPY_DYN_L2_GAS 6 #define AVM_EMITUNENCRYPTEDLOG_DYN_L2_GAS 146 #define AVM_CALL_DYN_L2_GAS 4 @@ -127,10 +123,6 @@ #define AVM_DELEGATECALL_DYN_L2_GAS 4 #define AVM_RETURN_DYN_L2_GAS 6 #define AVM_REVERT_DYN_L2_GAS 6 -#define AVM_KECCAK_DYN_L2_GAS 100 -#define AVM_SHA256_DYN_L2_GAS 100 -#define AVM_PEDERSEN_DYN_L2_GAS 100 -#define AVM_PEDERSENCOMMITMENT_DYN_L2_GAS 100 #define AVM_MSM_DYN_L2_GAS 100 #define AVM_TORADIXLE_DYN_L2_GAS 20 #define AVM_SSTORE_BASE_DA_GAS 512 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 56498fd6f809..1dda4eaa5f60 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -497,16 +497,13 @@ global AVM_DELEGATECALL_BASE_L2_GAS: u32 = 45 + (2 * L2_GAS_PER_NULLIFIER_READ_R global AVM_RETURN_BASE_L2_GAS: u32 = 28; global AVM_REVERT_BASE_L2_GAS: u32 = 28; global AVM_DEBUGLOG_BASE_L2_GAS: u32 = 12; // Must be equal to AVM_JUMP_BASE_L2_GAS as long as circuit implements debugLog as a jump -global AVM_KECCAK_BASE_L2_GAS: u32 = 3000; global AVM_POSEIDON2_BASE_L2_GAS: u32 = 78; -global AVM_SHA256_BASE_L2_GAS: u32 = 2610; -global AVM_PEDERSEN_BASE_L2_GAS: u32 = 1000; +global AVM_SHA256COMPRESSION_BASE_L2_GAS: u32 = 261; +global AVM_KECCAKF1600_BASE_L2_GAS: u32 = 300; global AVM_ECADD_BASE_L2_GAS: u32 = 62; global AVM_MSM_BASE_L2_GAS: u32 = 1000; -global AVM_PEDERSENCOMMITMENT_BASE_L2_GAS: u32 = 1000; global AVM_TORADIXLE_BASE_L2_GAS: u32 = 46; -global AVM_SHA256COMPRESSION_BASE_L2_GAS: u32 = 261; -global AVM_KECCAKF1600_BASE_L2_GAS: u32 = 300; + // Dynamic L2 GAS global AVM_CALLDATACOPY_DYN_L2_GAS: u32 = 6; // a single increment here corresponds to an entire additional field (hence x32 bytes per field) @@ -516,10 +513,6 @@ global AVM_STATICCALL_DYN_L2_GAS: u32 = 4; global AVM_DELEGATECALL_DYN_L2_GAS: u32 = 4; global AVM_RETURN_DYN_L2_GAS: u32 = 6; global AVM_REVERT_DYN_L2_GAS: u32 = 6; -global AVM_KECCAK_DYN_L2_GAS: u32 = 100; -global AVM_SHA256_DYN_L2_GAS: u32 = 100; -global AVM_PEDERSEN_DYN_L2_GAS: u32 = 100; -global AVM_PEDERSENCOMMITMENT_DYN_L2_GAS: u32 = 100; global AVM_MSM_DYN_L2_GAS: u32 = 100; global AVM_TORADIXLE_DYN_L2_GAS: u32 = 20; @@ -528,6 +521,7 @@ global AVM_SSTORE_BASE_DA_GAS: u32 = DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE; global AVM_EMITNOTEHASH_BASE_DA_GAS: u32 = DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE; global AVM_EMITNULLIFIER_BASE_DA_GAS: u32 = DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE; global AVM_SENDL2TOL1MSG_BASE_DA_GAS: u32 = DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE; + // Dynamic DA Gas // a single increment here corresponds to an entire additional field (hence x32 bytes per field) global AVM_EMITUNENCRYPTEDLOG_DYN_DA_GAS: u32 = DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE; diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 393289635a66..568394413404 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -292,16 +292,12 @@ export const AVM_DELEGATECALL_BASE_L2_GAS = 2445; export const AVM_RETURN_BASE_L2_GAS = 28; export const AVM_REVERT_BASE_L2_GAS = 28; export const AVM_DEBUGLOG_BASE_L2_GAS = 12; -export const AVM_KECCAK_BASE_L2_GAS = 3000; export const AVM_POSEIDON2_BASE_L2_GAS = 78; -export const AVM_SHA256_BASE_L2_GAS = 2610; -export const AVM_PEDERSEN_BASE_L2_GAS = 1000; +export const AVM_SHA256COMPRESSION_BASE_L2_GAS = 261; +export const AVM_KECCAKF1600_BASE_L2_GAS = 300; export const AVM_ECADD_BASE_L2_GAS = 62; export const AVM_MSM_BASE_L2_GAS = 1000; -export const AVM_PEDERSENCOMMITMENT_BASE_L2_GAS = 1000; export const AVM_TORADIXLE_BASE_L2_GAS = 46; -export const AVM_SHA256COMPRESSION_BASE_L2_GAS = 261; -export const AVM_KECCAKF1600_BASE_L2_GAS = 300; export const AVM_CALLDATACOPY_DYN_L2_GAS = 6; export const AVM_EMITUNENCRYPTEDLOG_DYN_L2_GAS = 146; export const AVM_CALL_DYN_L2_GAS = 4; @@ -309,10 +305,6 @@ export const AVM_STATICCALL_DYN_L2_GAS = 4; export const AVM_DELEGATECALL_DYN_L2_GAS = 4; export const AVM_RETURN_DYN_L2_GAS = 6; export const AVM_REVERT_DYN_L2_GAS = 6; -export const AVM_KECCAK_DYN_L2_GAS = 100; -export const AVM_SHA256_DYN_L2_GAS = 100; -export const AVM_PEDERSEN_DYN_L2_GAS = 100; -export const AVM_PEDERSENCOMMITMENT_DYN_L2_GAS = 100; export const AVM_MSM_DYN_L2_GAS = 100; export const AVM_TORADIXLE_DYN_L2_GAS = 20; export const AVM_SSTORE_BASE_DA_GAS = 512; diff --git a/yarn-project/simulator/src/avm/avm_gas.ts b/yarn-project/simulator/src/avm/avm_gas.ts index ea3e955517c4..6f2f84770680 100644 --- a/yarn-project/simulator/src/avm/avm_gas.ts +++ b/yarn-project/simulator/src/avm/avm_gas.ts @@ -118,14 +118,11 @@ const BASE_GAS_COSTS: Record = { [Opcode.REVERT_8]: makeCost(c.AVM_REVERT_BASE_L2_GAS, 0), [Opcode.REVERT_16]: makeCost(c.AVM_REVERT_BASE_L2_GAS, 0), [Opcode.DEBUGLOG]: makeCost(c.AVM_DEBUGLOG_BASE_L2_GAS, 0), - [Opcode.KECCAK]: makeCost(c.AVM_KECCAK_BASE_L2_GAS, 0), [Opcode.POSEIDON2]: makeCost(c.AVM_POSEIDON2_BASE_L2_GAS, 0), [Opcode.SHA256COMPRESSION]: makeCost(c.AVM_SHA256COMPRESSION_BASE_L2_GAS, 0), [Opcode.KECCAKF1600]: makeCost(c.AVM_KECCAKF1600_BASE_L2_GAS, 0), - [Opcode.PEDERSEN]: makeCost(c.AVM_PEDERSEN_BASE_L2_GAS, 0), [Opcode.ECADD]: makeCost(c.AVM_ECADD_BASE_L2_GAS, 0), [Opcode.MSM]: makeCost(c.AVM_MSM_BASE_L2_GAS, 0), - [Opcode.PEDERSENCOMMITMENT]: makeCost(c.AVM_PEDERSENCOMMITMENT_BASE_L2_GAS, 0), [Opcode.TORADIXLE]: makeCost(c.AVM_TORADIXLE_BASE_L2_GAS, 0), }; @@ -138,9 +135,7 @@ const DYNAMIC_GAS_COSTS = new Map([ [Opcode.RETURN, makeCost(c.AVM_RETURN_DYN_L2_GAS, 0)], [Opcode.REVERT_8, makeCost(c.AVM_REVERT_DYN_L2_GAS, 0)], [Opcode.REVERT_16, makeCost(c.AVM_REVERT_DYN_L2_GAS, 0)], - [Opcode.PEDERSEN, makeCost(c.AVM_PEDERSEN_DYN_L2_GAS, 0)], [Opcode.MSM, makeCost(c.AVM_MSM_DYN_L2_GAS, 0)], - [Opcode.PEDERSENCOMMITMENT, makeCost(c.AVM_PEDERSENCOMMITMENT_DYN_L2_GAS, 0)], [Opcode.TORADIXLE, makeCost(c.AVM_TORADIXLE_DYN_L2_GAS, 0)], ]); diff --git a/yarn-project/simulator/src/avm/opcodes/commitment.test.ts b/yarn-project/simulator/src/avm/opcodes/commitment.test.ts deleted file mode 100644 index 810d48a32dce..000000000000 --- a/yarn-project/simulator/src/avm/opcodes/commitment.test.ts +++ /dev/null @@ -1,120 +0,0 @@ -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 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([ - /*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 deleted file mode 100644 index a98a21abec23..000000000000 --- a/yarn-project/simulator/src/avm/opcodes/commitment.ts +++ /dev/null @@ -1,65 +0,0 @@ -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 operands = [this.inputOffset, this.outputOffset, this.inputSizeOffset, this.genIndexOffset]; - const addressing = Addressing.fromWire(this.indirect, operands.length); - const [inputOffset, outputOffset, inputSizeOffset, genIndexOffset] = addressing.resolve(operands, memory); - - const inputSize = memory.get(inputSizeOffset).toNumber(); - memory.checkTag(TypeTag.UINT32, inputSizeOffset); - - const inputs = memory.getSlice(inputOffset, inputSize); - memory.checkTagsRange(TypeTag.FIELD, inputOffset, inputSize); - - const generatorIndex = memory.get(genIndexOffset).toNumber(); - memory.checkTag(TypeTag.UINT32, genIndexOffset); - - context.machineState.consumeGas(this.gasCost(inputSize)); - - const inputBuffer: Buffer[] = inputs.map(input => input.toBuffer()); - // TODO: Add the generate index to the pedersenCommit function - 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)); - - 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({ reads: inputSize + 2, writes: 3, addressing }); - context.machineState.incrementPc(); - } -} diff --git a/yarn-project/simulator/src/avm/opcodes/hashing.test.ts b/yarn-project/simulator/src/avm/opcodes/hashing.test.ts index ddca0874f6ff..26020a6e0c70 100644 --- a/yarn-project/simulator/src/avm/opcodes/hashing.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/hashing.test.ts @@ -1,10 +1,10 @@ -import { keccak256, keccakf1600, pedersenHash, sha256Compression } from '@aztec/foundation/crypto'; +import { keccakf1600, sha256Compression } from '@aztec/foundation/crypto'; import { type AvmContext } from '../avm_context.js'; -import { Field, type Uint8, Uint32, Uint64 } from '../avm_memory_types.js'; -import { initContext, randomMemoryBytes, randomMemoryFields, randomMemoryUint32s } from '../fixtures/index.js'; +import { Field, Uint32, Uint64 } from '../avm_memory_types.js'; +import { initContext, randomMemoryUint32s } from '../fixtures/index.js'; import { Addressing, AddressingMode } from './addressing_mode.js'; -import { Keccak, KeccakF1600, Pedersen, Poseidon2, Sha256Compression } from './hashing.js'; +import { KeccakF1600, Poseidon2, Sha256Compression } from './hashing.js'; describe('Hashing Opcodes', () => { let context: AvmContext; @@ -67,75 +67,6 @@ describe('Hashing Opcodes', () => { }); }); - describe('Keccak', () => { - it('Should (de)serialize correctly', () => { - const buf = Buffer.from([ - Keccak.opcode, // opcode - 1, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ...Buffer.from('23456789', 'hex'), // messageOffset - ...Buffer.from('3456789a', 'hex'), // messageSizeOffset - ]); - const inst = new Keccak( - /*indirect=*/ 1, - /*dstOffset=*/ 0x12345678, - /*messageOffset=*/ 0x23456789, - /*messageSizeOffset=*/ 0x3456789a, - ); - - expect(Keccak.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); - }); - - it('Should hash correctly - direct', async () => { - const args = randomMemoryBytes(10); - const indirect = 0; - const messageOffset = 0; - const messageSizeOffset = 15; - const dstOffset = 20; - context.machineState.memory.set(messageSizeOffset, new Uint32(args.length)); - context.machineState.memory.setSlice(messageOffset, args); - - await new Keccak(indirect, dstOffset, messageOffset, messageSizeOffset).execute(context); - - const resultBuffer = Buffer.concat( - context.machineState.memory.getSliceAs(dstOffset, 32).map(byte => byte.toBuffer()), - ); - const inputBuffer = Buffer.concat(args.map(byte => byte.toBuffer())); - const expectedHash = keccak256(inputBuffer); - expect(resultBuffer).toEqual(expectedHash); - }); - - it('Should hash correctly - indirect', async () => { - const args = randomMemoryBytes(10); - const indirect = new Addressing([ - /*dstOffset=*/ AddressingMode.INDIRECT, - /*messageOffset*/ AddressingMode.INDIRECT, - /*messageSizeOffset*/ AddressingMode.INDIRECT, - ]).toWire(); - const messageOffset = 0; - const messageOffsetReal = 10; - const messageSizeOffset = 1; - const messageSizeOffsetReal = 100; - const dstOffset = 2; - const dstOffsetReal = 30; - context.machineState.memory.set(messageOffset, new Uint32(messageOffsetReal)); - context.machineState.memory.set(dstOffset, new Uint32(dstOffsetReal)); - context.machineState.memory.set(messageSizeOffset, new Uint32(messageSizeOffsetReal)); - context.machineState.memory.set(messageSizeOffsetReal, new Uint32(args.length)); - context.machineState.memory.setSlice(messageOffsetReal, args); - - await new Keccak(indirect, dstOffset, messageOffset, messageSizeOffset).execute(context); - - const resultBuffer = Buffer.concat( - context.machineState.memory.getSliceAs(dstOffsetReal, 32).map(byte => byte.toBuffer()), - ); - const inputBuffer = Buffer.concat(args.map(byte => byte.toBuffer())); - const expectedHash = keccak256(inputBuffer); - expect(resultBuffer).toEqual(expectedHash); - }); - }); - describe('Keccakf1600', () => { it('Should (de)serialize correctly', () => { const buf = Buffer.from([ @@ -257,77 +188,4 @@ describe('Hashing Opcodes', () => { expect(outputArray).toEqual(expectedOutput); }); }); - - describe('Pedersen', () => { - it('Should (de)serialize correctly', () => { - const buf = Buffer.from([ - Pedersen.opcode, // opcode - 1, // indirect - ...Buffer.from('02345678', 'hex'), // genIndexOffset - ...Buffer.from('12345678', 'hex'), // dstOffset - ...Buffer.from('23456789', 'hex'), // messageOffset - ...Buffer.from('3456789a', 'hex'), // hashSize - ]); - const inst = new Pedersen( - /*indirect=*/ 1, - /*genIndexOffset=*/ 0x02345678, - /*dstOffset=*/ 0x12345678, - /*messageOffset=*/ 0x23456789, - /*hashSizeOffset=*/ 0x3456789a, - ); - - expect(Pedersen.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); - }); - - it('Should hash correctly - direct', async () => { - const args = randomMemoryFields(10); - const messageOffset = 0; - const sizeOffset = 20; - const genIndexOffset = 30; - const indirect = 0; - const genIndex = 20; - - context.machineState.memory.setSlice(messageOffset, args); - context.machineState.memory.set(sizeOffset, new Uint32(args.length)); - context.machineState.memory.set(genIndexOffset, new Uint32(genIndex)); - - const dstOffset = 3; - - const expectedHash = pedersenHash(args, genIndex); - await new Pedersen(indirect, genIndexOffset, dstOffset, messageOffset, sizeOffset).execute(context); - - const result = context.machineState.memory.get(dstOffset); - expect(result).toEqual(new Field(expectedHash)); - }); - - it('Should hash correctly - indirect', async () => { - const args = randomMemoryFields(10); - const indirect = new Addressing([ - /*genIndexOffset=*/ AddressingMode.DIRECT, - /*dstOffset=*/ AddressingMode.DIRECT, - /*messageOffset*/ AddressingMode.INDIRECT, - /*messageSizeOffset*/ AddressingMode.INDIRECT, - ]).toWire(); - const messageOffset = 0; - const sizeOffset = 20; - const realLocation = 4; - const realSizeLocation = 21; - const genIndexOffset = 50; - - context.machineState.memory.set(messageOffset, new Uint32(realLocation)); - context.machineState.memory.set(sizeOffset, new Uint32(realSizeLocation)); - context.machineState.memory.setSlice(realLocation, args); - context.machineState.memory.set(realSizeLocation, new Uint32(args.length)); - context.machineState.memory.set(genIndexOffset, new Uint32(0)); - - const dstOffset = 300; - - const expectedHash = pedersenHash(args); - await new Pedersen(indirect, genIndexOffset, dstOffset, messageOffset, sizeOffset).execute(context); - - const result = context.machineState.memory.get(dstOffset); - expect(result).toEqual(new Field(expectedHash)); - }); - }); }); diff --git a/yarn-project/simulator/src/avm/opcodes/hashing.ts b/yarn-project/simulator/src/avm/opcodes/hashing.ts index a055d0a135e8..92e7bfb2a71d 100644 --- a/yarn-project/simulator/src/avm/opcodes/hashing.ts +++ b/yarn-project/simulator/src/avm/opcodes/hashing.ts @@ -1,15 +1,9 @@ -import { - keccak256, - keccakf1600, - pedersenHash, - poseidon2Permutation, - sha256Compression, -} from '@aztec/foundation/crypto'; +import { keccakf1600, poseidon2Permutation, sha256Compression } from '@aztec/foundation/crypto'; import { strict as assert } from 'assert'; import { type AvmContext } from '../avm_context.js'; -import { Field, TypeTag, Uint8, Uint32, Uint64 } from '../avm_memory_types.js'; +import { Field, TypeTag, Uint32, Uint64 } from '../avm_memory_types.js'; import { Opcode, OperandType } from '../serialization/instruction_serialization.js'; import { Addressing } from './addressing_mode.js'; import { Instruction } from './instruction.js'; @@ -52,52 +46,6 @@ export class Poseidon2 extends Instruction { } } -export class Keccak extends Instruction { - static type: string = 'KECCAK'; - static readonly opcode: Opcode = Opcode.KECCAK; - - // Informs (de)serialization. See Instruction.deserialize. - static readonly wireFormat: OperandType[] = [ - OperandType.UINT8, - OperandType.UINT8, - OperandType.UINT32, - OperandType.UINT32, - OperandType.UINT32, - ]; - - constructor( - private indirect: number, - private dstOffset: number, - private messageOffset: number, - private messageSizeOffset: number, - ) { - super(); - } - - // pub fn keccak256(input: [u8], message_size: u32) -> [u8; 32] - public async execute(context: AvmContext): Promise { - const memory = context.machineState.memory.track(this.type); - const operands = [this.dstOffset, this.messageOffset, this.messageSizeOffset]; - const addressing = Addressing.fromWire(this.indirect, operands.length); - const [dstOffset, messageOffset, messageSizeOffset] = addressing.resolve(operands, memory); - memory.checkTag(TypeTag.UINT32, messageSizeOffset); - const messageSize = memory.get(messageSizeOffset).toNumber(); - context.machineState.consumeGas(this.gasCost(messageSize)); - - memory.checkTagsRange(TypeTag.UINT8, messageOffset, messageSize); - - const messageData = Buffer.concat(memory.getSlice(messageOffset, messageSize).map(word => word.toBuffer())); - const hashBuffer = keccak256(messageData); - - // We need to convert the hashBuffer because map doesn't work as expected on an Uint8Array (Buffer). - const res = [...hashBuffer].map(byte => new Uint8(byte)); - memory.setSlice(dstOffset, res); - - memory.assert({ reads: messageSize + 1, writes: 32, addressing }); - context.machineState.incrementPc(); - } -} - export class KeccakF1600 extends Instruction { static type: string = 'KECCAKF1600'; static readonly opcode: Opcode = Opcode.KECCAKF1600; @@ -193,53 +141,3 @@ export class Sha256Compression extends Instruction { context.machineState.incrementPc(); } } - -export class Pedersen extends Instruction { - static type: string = 'PEDERSEN'; - static readonly opcode: Opcode = Opcode.PEDERSEN; - - // Informs (de)serialization. See Instruction.deserialize. - static readonly wireFormat: OperandType[] = [ - OperandType.UINT8, - OperandType.UINT8, - OperandType.UINT32, - OperandType.UINT32, - OperandType.UINT32, - OperandType.UINT32, - ]; - - constructor( - private indirect: number, - private genIndexOffset: number, - private dstOffset: number, - private messageOffset: number, - private messageSizeOffset: number, - ) { - super(); - } - - public async execute(context: AvmContext): Promise { - const memory = context.machineState.memory.track(this.type); - const operands = [this.genIndexOffset, this.dstOffset, this.messageOffset, this.messageSizeOffset]; - const addressing = Addressing.fromWire(this.indirect, operands.length); - const [genIndexOffset, dstOffset, messageOffset, messageSizeOffset] = addressing.resolve(operands, memory); - - // We hash a set of field elements - const genIndex = Number(memory.get(genIndexOffset).toBigInt()); - memory.checkTag(TypeTag.UINT32, genIndexOffset); - const messageSize = Number(memory.get(messageSizeOffset).toBigInt()); - memory.checkTag(TypeTag.UINT32, messageSizeOffset); - const hashData = memory.getSlice(messageOffset, messageSize); - - context.machineState.consumeGas(this.gasCost(messageSize)); - - memory.checkTagsRange(TypeTag.FIELD, messageOffset, messageSize); - - // No domain sep for now - const hash = pedersenHash(hashData, genIndex); - memory.set(dstOffset, new Field(hash)); - - memory.assert({ reads: messageSize + 2, writes: 1, addressing }); - context.machineState.incrementPc(); - } -} diff --git a/yarn-project/simulator/src/avm/opcodes/index.ts b/yarn-project/simulator/src/avm/opcodes/index.ts index 9ae06bd08c0b..a6169cd96788 100644 --- a/yarn-project/simulator/src/avm/opcodes/index.ts +++ b/yarn-project/simulator/src/avm/opcodes/index.ts @@ -13,4 +13,3 @@ export * from './environment_getters.js'; export * from './accrued_substate.js'; export * from './hashing.js'; export * from './ec_add.js'; -export * from './commitment.js'; diff --git a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts index 879a25279cb2..9528a0553b20 100644 --- a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts +++ b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts @@ -19,7 +19,6 @@ import { InternalReturn, Jump, JumpI, - Keccak, KeccakF1600, L1ToL2MessageExists, Lt, @@ -30,8 +29,6 @@ import { NoteHashExists, NullifierExists, Or, - Pedersen, - PedersenCommitment, Poseidon2, Return, Revert, @@ -141,12 +138,9 @@ const INSTRUCTION_SET = () => // Gadgets [EcAdd.opcode, Instruction.deserialize.bind(EcAdd)], - [Keccak.opcode, Instruction.deserialize.bind(Keccak)], [Poseidon2.opcode, Instruction.deserialize.bind(Poseidon2)], [Sha256Compression.opcode, Instruction.deserialize.bind(Sha256Compression)], - [Pedersen.opcode, Instruction.deserialize.bind(Pedersen)], [MultiScalarMul.opcode, Instruction.deserialize.bind(MultiScalarMul)], - [PedersenCommitment.opcode, Instruction.deserialize.bind(PedersenCommitment)], // Conversions [ToRadixLE.opcode, Instruction.deserialize.bind(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 e9ea67945fd9..b8a503ef4386 100644 --- a/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts +++ b/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts @@ -76,14 +76,11 @@ export enum Opcode { // Misc DEBUGLOG, // Gadgets - KECCAK, POSEIDON2, SHA256COMPRESSION, KECCAKF1600, - PEDERSEN, // temp - may be removed, but alot of contracts rely on it ECADD, MSM, - PEDERSENCOMMITMENT, // Conversion TORADIXLE, }