Skip to content

Commit 76e4ffd

Browse files
committed
12193: Addressing review feedback
1 parent fc71ec2 commit 76e4ffd

File tree

10 files changed

+109
-65
lines changed

10 files changed

+109
-65
lines changed

barretenberg/cpp/src/barretenberg/vm2/common/instruction_spec.test.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ TEST(InstructionSpecTest, CheckAllInstructionSizes)
3131
const auto wire_opcode = static_cast<WireOpCode>(i);
3232
const auto computed_size = compute_instruction_size(wire_opcode, wire_format, operand_type_sizes);
3333
EXPECT_EQ(WIRE_INSTRUCTION_SPEC.at(wire_opcode).size_in_bytes, computed_size)
34-
<< format("Incorrect size_in_bytes field for ", wire_opcode, " in WIRE_INSTRUCTION_SPEC.");
34+
<< "Incorrect size_in_bytes field for " << wire_opcode << " in WIRE_INSTRUCTION_SPEC.";
3535
}
3636
}
3737

barretenberg/cpp/src/barretenberg/vm2/common/memory_types.hpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace bb::avm2 {
88

9-
// Keep in sync with NUM_MEMORY_TAGS if we modify this enum.
9+
// Adapt NUM_MEMORY_TAGS in fixtures.cpp if this enum is modified.
1010
enum class MemoryTag {
1111
FF,
1212
U1,
@@ -17,8 +17,6 @@ enum class MemoryTag {
1717
U128,
1818
};
1919

20-
constexpr uint8_t NUM_MEMORY_TAGS = static_cast<int>(MemoryTag::U128) + 1;
21-
2220
using MemoryAddress = uint32_t;
2321
using MemoryValue = FF;
2422
constexpr auto MemoryAddressTag = MemoryTag::U32;

barretenberg/cpp/src/barretenberg/vm2/constraining/relations/instr_fetching.test.cpp

+54-37
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ using FF = AvmFlavorSettings::FF;
2828
using C = Column;
2929
using instr_fetching = bb::avm2::instr_fetching<FF>;
3030
using simulation::Instruction;
31+
using simulation::InstructionFetchingEvent;
3132
using simulation::Operand;
3233
using testing::random_bytes;
3334

@@ -47,7 +48,7 @@ TEST(InstrFetchingConstrainingTest, Add8WithTraceGen)
4748
.operands = { Operand::u8(0x34), Operand::u8(0x35), Operand::u8(0x36) },
4849
};
4950

50-
std::vector<uint8_t> bytecode = add_8_instruction.encode();
51+
std::vector<uint8_t> bytecode = add_8_instruction.serialize();
5152

5253
builder.process_instruction_fetching({ { .bytecode_id = 1,
5354
.pc = 0,
@@ -77,7 +78,7 @@ TEST(InstrFetchingConstrainingTest, EcaddWithTraceGen)
7778
Operand::u16(0x127f) },
7879
};
7980

80-
std::vector<uint8_t> bytecode = ecadd_instruction.encode();
81+
std::vector<uint8_t> bytecode = ecadd_instruction.serialize();
8182
builder.process_instruction_fetching({ { .bytecode_id = 1,
8283
.pc = 0,
8384
.instruction = ecadd_instruction,
@@ -89,33 +90,33 @@ TEST(InstrFetchingConstrainingTest, EcaddWithTraceGen)
8990
}
9091

9192
// Helper routine generating a vector of instruction fetching events for each
92-
// opcode. Note that operands of type TAG might fall outside of their valid range.
93-
std::vector<simulation::InstructionFetchingEvent> gen_instr_events_each_opcode()
93+
// opcode.
94+
std::vector<InstructionFetchingEvent> gen_instr_events_each_opcode()
9495
{
9596
std::vector<uint8_t> bytecode;
96-
std::vector<uint32_t> pc_positions;
97+
std::vector<Instruction> instructions;
9798
constexpr auto num_opcodes = static_cast<size_t>(WireOpCode::LAST_OPCODE_SENTINEL);
98-
pc_positions.reserve(num_opcodes);
99+
instructions.reserve(num_opcodes);
100+
std::array<uint32_t, num_opcodes> pc_positions;
99101

100102
for (size_t i = 0; i < num_opcodes; i++) {
101-
pc_positions.emplace_back(static_cast<uint32_t>(bytecode.size()));
102-
bytecode.emplace_back(i);
103-
const auto instruction_bytes =
104-
random_bytes(WIRE_INSTRUCTION_SPEC.at(static_cast<WireOpCode>(i)).size_in_bytes - 1);
103+
pc_positions.at(i) = static_cast<uint32_t>(bytecode.size());
104+
const auto instr = testing::random_instruction(static_cast<WireOpCode>(i));
105+
instructions.emplace_back(instr);
106+
const auto instruction_bytes = instr.serialize();
105107
bytecode.insert(bytecode.end(),
106108
std::make_move_iterator(instruction_bytes.begin()),
107109
std::make_move_iterator(instruction_bytes.end()));
108110
}
109111

110-
const auto bytecode_ptr = std::make_shared<std::vector<uint8_t>>(bytecode);
112+
const auto bytecode_ptr = std::make_shared<std::vector<uint8_t>>(std::move(bytecode));
113+
// Always use *bytecode_ptr from now on instead of bytecode as this one was moved.
111114

112-
std::vector<simulation::InstructionFetchingEvent> instr_events;
115+
std::vector<InstructionFetchingEvent> instr_events;
113116
instr_events.reserve(num_opcodes);
114-
115117
for (size_t i = 0; i < num_opcodes; i++) {
116-
const auto instr = simulation::decode_instruction(bytecode, pc_positions.at(i));
117-
instr_events.emplace_back(simulation::InstructionFetchingEvent{
118-
.bytecode_id = 1, .pc = pc_positions.at(i), .instruction = instr, .bytecode = bytecode_ptr });
118+
instr_events.emplace_back(InstructionFetchingEvent{
119+
.bytecode_id = 1, .pc = pc_positions.at(i), .instruction = instructions.at(i), .bytecode = bytecode_ptr });
119120
}
120121
return instr_events;
121122
}
@@ -149,20 +150,20 @@ TEST(InstrFetchingConstrainingTest, NegativeWrongOperand)
149150
instr_fetching::SR_OP6_BYTES_DECOMPOSITION, instr_fetching::SR_OP7_BYTES_DECOMPOSITION,
150151
};
151152

152-
const std::vector<C> operand_cols = {
153+
constexpr std::array<C, 8> operand_cols = {
153154
C::instr_fetching_indirect, C::instr_fetching_op1, C::instr_fetching_op2, C::instr_fetching_op3,
154155
C::instr_fetching_op4, C::instr_fetching_op5, C::instr_fetching_op6, C::instr_fetching_op7,
155156
};
156157

157158
for (const auto& opcode : opcodes) {
158159
TestTraceContainer trace;
159160
const auto instr = testing::random_instruction(opcode);
160-
builder.process_instruction_fetching({ simulation::InstructionFetchingEvent{
161-
.bytecode_id = 1,
162-
.pc = 0,
163-
.instruction = instr,
164-
.bytecode = std::make_shared<std::vector<uint8_t>>(instr.encode()) } },
165-
trace);
161+
builder.process_instruction_fetching(
162+
{ { .bytecode_id = 1,
163+
.pc = 0,
164+
.instruction = instr,
165+
.bytecode = std::make_shared<std::vector<uint8_t>>(instr.serialize()) } },
166+
trace);
166167
check_relation<instr_fetching>(trace);
167168

168169
EXPECT_EQ(trace.get_num_rows(), 1);
@@ -210,7 +211,7 @@ TEST(InstrFetchingConstrainingTest, BcDecompositionInteractions)
210211

211212
const auto instr_fetch_events = gen_instr_events_each_opcode();
212213
bytecode_builder.process_instruction_fetching(instr_fetch_events, trace);
213-
bytecode_builder.process_decomposition({ simulation::BytecodeDecompositionEvent{
214+
bytecode_builder.process_decomposition({ {
214215
.bytecode_id = instr_fetch_events.at(0).bytecode_id,
215216
.bytecode = instr_fetch_events.at(0).bytecode,
216217
} },
@@ -226,6 +227,7 @@ TEST(InstrFetchingConstrainingTest, BcDecompositionInteractions)
226227
TEST(InstrFetchingConstrainingTest, NegativeWrongWireInstructionSpecInteractions)
227228
{
228229
using wire_instr_spec_lookup = lookup_instr_fetching_wire_instruction_info_relation<FF>;
230+
using tracegen::LookupIntoIndexedByClk;
229231

230232
BytecodeTraceBuilder bytecode_builder;
231233
PrecomputedTraceBuilder precomputed_builder;
@@ -238,19 +240,20 @@ TEST(InstrFetchingConstrainingTest, NegativeWrongWireInstructionSpecInteractions
238240
TestTraceContainer trace;
239241
const auto instr = testing::random_instruction(opcode);
240242
bytecode_builder.process_instruction_fetching(
241-
{ simulation::InstructionFetchingEvent{ .bytecode_id = 1,
242-
.pc = 0,
243-
.instruction = instr,
244-
.bytecode =
245-
std::make_shared<std::vector<uint8_t>>(instr.encode()) } },
243+
{ { .bytecode_id = 1,
244+
.pc = 0,
245+
.instruction = instr,
246+
.bytecode = std::make_shared<std::vector<uint8_t>>(instr.serialize()) } },
246247
trace);
247248
precomputed_builder.process_wire_instruction_spec(trace);
248249
precomputed_builder.process_misc(trace, trace.get_num_rows()); // Limit to the number of rows we need.
249250

250-
tracegen::LookupIntoIndexedByClk<wire_instr_spec_lookup::Settings>().process(trace);
251+
LookupIntoIndexedByClk<wire_instr_spec_lookup::Settings>().process(trace);
252+
253+
ASSERT_EQ(trace.get(C::lookup_instr_fetching_wire_instruction_info_counts, static_cast<uint32_t>(opcode)), 1);
251254
check_interaction<wire_instr_spec_lookup>(trace);
252255

253-
const std::vector<C> mutated_cols = {
256+
constexpr std::array<C, 20> mutated_cols = {
254257
C::instr_fetching_exec_opcode, C::instr_fetching_instr_size_in_bytes, C::instr_fetching_sel_op_dc_0,
255258
C::instr_fetching_sel_op_dc_1, C::instr_fetching_sel_op_dc_2, C::instr_fetching_sel_op_dc_3,
256259
C::instr_fetching_sel_op_dc_4, C::instr_fetching_sel_op_dc_5, C::instr_fetching_sel_op_dc_6,
@@ -265,6 +268,11 @@ TEST(InstrFetchingConstrainingTest, NegativeWrongWireInstructionSpecInteractions
265268
auto mutated_trace = trace;
266269
const FF mutated_value = trace.get(col, 0) + 1; // Mutate to value + 1
267270
mutated_trace.set(col, 0, mutated_value);
271+
272+
// We do not need to re-run LookupIntoIndexedByClk<wire_instr_spec_lookup::Settings>().process(trace);
273+
// because we never mutate the indexing column for this lookup (clk) and for this lookup
274+
// find_in_dst only uses column C::instr_fetching_bd0 mapped to (clk). So, the counts are still valid.
275+
268276
EXPECT_THROW_WITH_MESSAGE(check_interaction<wire_instr_spec_lookup>(mutated_trace),
269277
"Relation.*WIRE_INSTRUCTION_INFO.* ACCUMULATION.* is non-zero");
270278
}
@@ -275,6 +283,7 @@ TEST(InstrFetchingConstrainingTest, NegativeWrongWireInstructionSpecInteractions
275283
TEST(InstrFetchingConstrainingTest, NegativeWrongBcDecompositionInteractions)
276284
{
277285
using bc_decomposition_lookup = lookup_instr_fetching_bytes_from_bc_dec_relation<FF>;
286+
using tracegen::LookupIntoDynamicTableSequential;
278287

279288
TestTraceContainer trace;
280289
BytecodeTraceBuilder bytecode_builder;
@@ -286,24 +295,25 @@ TEST(InstrFetchingConstrainingTest, NegativeWrongBcDecompositionInteractions)
286295
for (const auto& opcode : opcodes) {
287296
TestTraceContainer trace;
288297
const auto instr = testing::random_instruction(opcode);
289-
auto bytecode_ptr = std::make_shared<std::vector<uint8_t>>(instr.encode());
290-
bytecode_builder.process_instruction_fetching({ simulation::InstructionFetchingEvent{
298+
auto bytecode_ptr = std::make_shared<std::vector<uint8_t>>(instr.serialize());
299+
bytecode_builder.process_instruction_fetching({ {
291300
.bytecode_id = 1,
292301
.pc = 0,
293302
.instruction = instr,
294303
.bytecode = bytecode_ptr,
295304
} },
296305
trace);
297-
bytecode_builder.process_decomposition({ simulation::BytecodeDecompositionEvent{
306+
bytecode_builder.process_decomposition({ {
298307
.bytecode_id = 1,
299308
.bytecode = bytecode_ptr,
300309
} },
301310
trace);
302311

303-
tracegen::LookupIntoDynamicTableSequential<bc_decomposition_lookup::Settings>().process(trace);
304-
check_interaction<bc_decomposition_lookup>(trace);
312+
auto valid_trace = trace; // Keep original trace before lookup processing
313+
LookupIntoDynamicTableSequential<bc_decomposition_lookup::Settings>().process(valid_trace);
314+
check_interaction<bc_decomposition_lookup>(valid_trace);
305315

306-
const std::vector<C> mutated_cols = {
316+
constexpr std::array<C, 39> mutated_cols = {
307317
C::instr_fetching_pc, C::instr_fetching_bytecode_id, C::instr_fetching_bd0, C::instr_fetching_bd1,
308318
C::instr_fetching_bd2, C::instr_fetching_bd3, C::instr_fetching_bd4, C::instr_fetching_bd5,
309319
C::instr_fetching_bd6, C::instr_fetching_bd7, C::instr_fetching_bd8, C::instr_fetching_bd9,
@@ -321,6 +331,13 @@ TEST(InstrFetchingConstrainingTest, NegativeWrongBcDecompositionInteractions)
321331
auto mutated_trace = trace;
322332
const FF mutated_value = trace.get(col, 0) + 1; // Mutate to value + 1
323333
mutated_trace.set(col, 0, mutated_value);
334+
335+
// This sets the length of the inverse polynomial via SetDummyInverses, so we still need to call this even
336+
// though we know it will fail.
337+
EXPECT_THROW_WITH_MESSAGE(
338+
LookupIntoDynamicTableSequential<bc_decomposition_lookup::Settings>().process(mutated_trace),
339+
"Failed.*BYTES_FROM_BC_DEC. Could not find tuple in destination.");
340+
324341
EXPECT_THROW_WITH_MESSAGE(check_interaction<bc_decomposition_lookup>(mutated_trace),
325342
"Relation.*BYTES_FROM_BC_DEC.* ACCUMULATION.* is non-zero");
326343
}

barretenberg/cpp/src/barretenberg/vm2/simulation/bytecode_manager.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ Instruction TxBytecodeManager::read_instruction(BytecodeId bytecode_id, uint32_t
5757
auto bytecode_ptr = it->second;
5858
const auto& bytecode = *bytecode_ptr;
5959
// TODO: catch errors etc.
60-
Instruction instruction = decode_instruction(bytecode, pc);
60+
Instruction instruction = deserialize_instruction(bytecode, pc);
6161

6262
// The event will be deduplicated internally.
6363
fetching_events.emit(

barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ Operand& Operand::operator=(const Operand& other)
227227

228228
bool Operand::operator==(const Operand& other) const
229229
{
230+
if (this == &other) {
231+
return true;
232+
}
233+
230234
if (value.index() != other.value.index()) {
231235
return false;
232236
}
@@ -348,7 +352,7 @@ std::string Operand::to_string() const
348352
__builtin_unreachable();
349353
}
350354

351-
Instruction decode_instruction(std::span<const uint8_t> bytecode, size_t pos)
355+
Instruction deserialize_instruction(std::span<const uint8_t> bytecode, size_t pos)
352356
{
353357
const auto bytecode_length = bytecode.size();
354358

@@ -486,7 +490,7 @@ std::string Instruction::to_string() const
486490
return oss.str();
487491
}
488492

489-
std::vector<uint8_t> Instruction::encode() const
493+
std::vector<uint8_t> Instruction::serialize() const
490494
{
491495
std::vector<uint8_t> output;
492496
output.reserve(WIRE_INSTRUCTION_SPEC.at(opcode).size_in_bytes);

barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.hpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#pragma once
22

3-
#include "barretenberg/common/serialize.hpp"
43
#include "barretenberg/numeric/uint128/uint128.hpp"
54
#include "barretenberg/vm2/common/field.hpp"
65
#include "barretenberg/vm2/common/memory_types.hpp"
@@ -72,7 +71,8 @@ struct Instruction {
7271
std::vector<Operand> operands;
7372

7473
std::string to_string() const;
75-
std::vector<uint8_t> encode() const;
74+
// Serialize the instruction according to the specification from OPCODE_WIRE_FORMAT.
75+
std::vector<uint8_t> serialize() const;
7676

7777
bool operator==(const Instruction& other) const = default;
7878
};
@@ -87,6 +87,6 @@ struct Instruction {
8787
* @throws runtime_error exception when the bytecode is invalid or pos is out-of-range
8888
* @return The instruction
8989
*/
90-
Instruction decode_instruction(std::span<const uint8_t> bytecode, size_t pos);
90+
Instruction deserialize_instruction(std::span<const uint8_t> bytecode, size_t pos);
9191

9292
} // namespace bb::avm2::simulation

barretenberg/cpp/src/barretenberg/vm2/simulation/lib/serialization.test.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace bb::avm2 {
77
namespace {
8-
using simulation::decode_instruction;
8+
using simulation::deserialize_instruction;
99
using simulation::Instruction;
1010
using simulation::Operand;
1111

@@ -15,7 +15,7 @@ TEST(SerializationTest, Not8RoundTrip)
1515
const Instruction instr = { .opcode = WireOpCode::NOT_8,
1616
.indirect = 5,
1717
.operands = { Operand::u8(123), Operand::u8(45) } };
18-
const auto decoded = decode_instruction(instr.encode(), 0);
18+
const auto decoded = deserialize_instruction(instr.serialize(), 0);
1919
EXPECT_EQ(instr, decoded);
2020
}
2121

@@ -25,7 +25,7 @@ TEST(SerializationTest, Add16RoundTrip)
2525
const Instruction instr = { .opcode = WireOpCode::ADD_16,
2626
.indirect = 3,
2727
.operands = { Operand::u16(1000), Operand::u16(1001), Operand::u16(1002) } };
28-
const auto decoded = decode_instruction(instr.encode(), 0);
28+
const auto decoded = deserialize_instruction(instr.serialize(), 0);
2929
EXPECT_EQ(instr, decoded);
3030
}
3131

@@ -35,7 +35,7 @@ TEST(SerializationTest, Jumpi32RoundTrip)
3535
const Instruction instr = { .opcode = WireOpCode::JUMPI_32,
3636
.indirect = 7,
3737
.operands = { Operand::u16(12345), Operand::u32(678901234) } };
38-
const auto decoded = decode_instruction(instr.encode(), 0);
38+
const auto decoded = deserialize_instruction(instr.serialize(), 0);
3939
EXPECT_EQ(instr, decoded);
4040
}
4141

@@ -49,7 +49,7 @@ TEST(SerializationTest, Set64RoundTrip)
4949
.indirect = 2,
5050
.operands = { Operand::u16(1002), Operand::u8(static_cast<uint8_t>(MemoryTag::U64)), Operand::u64(value_64) }
5151
};
52-
const auto decoded = decode_instruction(instr.encode(), 0);
52+
const auto decoded = deserialize_instruction(instr.serialize(), 0);
5353
EXPECT_EQ(instr, decoded);
5454
}
5555

@@ -63,7 +63,7 @@ TEST(SerializationTest, Set128RoundTrip)
6363
.indirect = 2,
6464
.operands = { Operand::u16(1002), Operand::u8(static_cast<uint8_t>(MemoryTag::U128)), Operand::u128(value_128) }
6565
};
66-
const auto decoded = decode_instruction(instr.encode(), 0);
66+
const auto decoded = deserialize_instruction(instr.serialize(), 0);
6767
EXPECT_EQ(instr, decoded);
6868
}
6969

@@ -77,7 +77,7 @@ TEST(SerializationTest, SetFFRoundTrip)
7777
.indirect = 2,
7878
.operands = { Operand::u16(1002), Operand::u8(static_cast<uint8_t>(MemoryTag::FF)), Operand::ff(large_ff) }
7979
};
80-
const auto decoded = decode_instruction(instr.encode(), 0);
80+
const auto decoded = deserialize_instruction(instr.serialize(), 0);
8181
EXPECT_EQ(instr, decoded);
8282
}
8383

0 commit comments

Comments
 (0)