Skip to content

Commit 2c70ef8

Browse files
committed
chore(avm): align some errors between C++ and TS simulators
1 parent 26f55a8 commit 2c70ef8

File tree

18 files changed

+161
-74
lines changed

18 files changed

+161
-74
lines changed

barretenberg/cpp/src/barretenberg/vm2/common/tagged_value.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,9 @@ TaggedValue TaggedValue::from_tag_truncating(ValueTag tag, FF value)
277277
case ValueTag::FF:
278278
return TaggedValue(value);
279279
default:
280-
throw std::runtime_error("Invalid tag");
280+
const auto msg =
281+
format("Tag check failed: Tag value: " + std::to_string(static_cast<uint8_t>(tag)), " is invalid.");
282+
throw std::runtime_error(msg);
281283
}
282284
}
283285

@@ -414,7 +416,7 @@ std::string std::to_string(bb::avm2::ValueTag tag)
414416
case ValueTag::U128:
415417
return "U128";
416418
case ValueTag::FF:
417-
return "FF";
419+
return "FIELD";
418420
default:
419421
return "Unknown";
420422
}

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

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ using C = Column;
3333
using instr_fetching = instr_fetching<FF>;
3434

3535
using simulation::BytecodeDecompositionEvent;
36-
using simulation::InstrDeserializationError;
36+
using simulation::InstrDeserializationEventError;
3737
using simulation::Instruction;
3838
using simulation::InstructionFetchingEvent;
3939
using simulation::Operand;
@@ -223,9 +223,10 @@ std::vector<RangeCheckEvent> gen_range_check_events(const std::vector<Instructio
223223

224224
for (const auto& instr_event : instr_events) {
225225
range_check_events.emplace_back(RangeCheckEvent{
226-
.value = instr_event.error == InstrDeserializationError::PC_OUT_OF_RANGE
227-
? instr_event.pc - instr_event.bytecode->size()
228-
: instr_event.bytecode->size() - instr_event.pc - 1,
226+
.value =
227+
(instr_event.error.has_value() && instr_event.error == InstrDeserializationEventError::PC_OUT_OF_RANGE)
228+
? instr_event.pc - instr_event.bytecode->size()
229+
: instr_event.bytecode->size() - instr_event.pc - 1,
229230
.num_bits = AVM_PC_SIZE_IN_BITS,
230231
});
231232
}
@@ -376,7 +377,7 @@ TEST(InstrFetchingConstrainingTest, SingleInstructionOutOfRange)
376377
.bytecode_id = 1,
377378
.pc = 0,
378379
.bytecode = bytecode_ptr,
379-
.error = InstrDeserializationError::INSTRUCTION_OUT_OF_RANGE,
380+
.error = InstrDeserializationEventError::INSTRUCTION_OUT_OF_RANGE,
380381
},
381382
};
382383

@@ -413,7 +414,7 @@ TEST(InstrFetchingConstrainingTest, SingleInstructionOutOfRangeSplitOperand)
413414
.bytecode_id = 1,
414415
.pc = 0,
415416
.bytecode = bytecode_ptr,
416-
.error = InstrDeserializationError::INSTRUCTION_OUT_OF_RANGE,
417+
.error = InstrDeserializationEventError::INSTRUCTION_OUT_OF_RANGE,
417418
},
418419
};
419420

@@ -451,7 +452,7 @@ TEST(InstrFetchingConstrainingTest, SingleInstructionPcOutOfRange)
451452
.bytecode_id = 1,
452453
.pc = static_cast<uint32_t>(bytecode_ptr->size() + 1),
453454
.bytecode = bytecode_ptr,
454-
.error = InstrDeserializationError::PC_OUT_OF_RANGE,
455+
.error = InstrDeserializationEventError::PC_OUT_OF_RANGE,
455456
},
456457
};
457458

@@ -492,7 +493,7 @@ TEST(InstrFetchingConstrainingTest, SingleInstructionOpcodeOutOfRange)
492493
.bytecode_id = 1,
493494
.pc = 5, // We move pc to the beginning of the 128-bit immediate value.
494495
.bytecode = bytecode_ptr,
495-
.error = InstrDeserializationError::OPCODE_OUT_OF_RANGE,
496+
.error = InstrDeserializationEventError::OPCODE_OUT_OF_RANGE,
496497
},
497498
};
498499

@@ -526,7 +527,7 @@ TEST(InstrFetchingConstrainingTest, SingleInstructionTagOutOfRange)
526527
.pc = 0,
527528
.instruction = set_16_instruction,
528529
.bytecode = bytecode_ptr,
529-
.error = InstrDeserializationError::TAG_OUT_OF_RANGE,
530+
.error = InstrDeserializationEventError::TAG_OUT_OF_RANGE,
530531
},
531532
};
532533

barretenberg/cpp/src/barretenberg/vm2/simulation/events/addressing_event.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ inline std::string to_string(AddressingEventError e)
3636
}
3737

3838
struct AddressingException : public std::runtime_error {
39-
explicit AddressingException()
40-
: std::runtime_error("Error resolving operands.")
39+
explicit AddressingException(const std::string& message = "Error resolving operands.")
40+
: std::runtime_error(message)
4141
{}
4242
};
4343

barretenberg/cpp/src/barretenberg/vm2/simulation/events/bytecode_events.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ struct InstructionFetchingEvent {
4747
// TODO: Do we want to have a dep on Instruction here or do we redefine what we need?
4848
Instruction instruction;
4949
std::shared_ptr<std::vector<uint8_t>> bytecode;
50-
std::optional<InstrDeserializationError> error;
50+
std::optional<InstrDeserializationEventError> error;
5151

5252
// To be used with deduplicating event emitters.
5353
using Key = std::tuple<BytecodeId, uint32_t>;

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,18 @@ Instruction TxBytecodeManager::read_instruction(const BytecodeId& bytecode_id,
121121
const auto& bytecode = *bytecode_ptr;
122122
instr_fetching_event.bytecode = std::move(bytecode_ptr);
123123

124+
// Keep full error for exception message, but only store enum in event
125+
std::optional<InstrDeserializationError> deserialization_error;
126+
124127
try {
125128
instr_fetching_event.instruction = deserialize_instruction(bytecode, pc);
126129

127130
// If the following code is executed, no error was thrown in deserialize_instruction().
128131
if (!check_tag(instr_fetching_event.instruction)) {
129-
instr_fetching_event.error = InstrDeserializationError::TAG_OUT_OF_RANGE;
132+
instr_fetching_event.error = InstrDeserializationEventError::TAG_OUT_OF_RANGE;
130133
};
131134
} catch (const InstrDeserializationError& error) {
132-
instr_fetching_event.error = error;
135+
instr_fetching_event.error = error.type;
133136
}
134137

135138
// We are showing whether bytecode_size > pc or not. If there is no fetching error,

barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/execution.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ void Execution::add(ContextInterface& context, MemoryAddress a_addr, MemoryAddre
7575
memory.set(dst_addr, c);
7676
set_output(opcode, c);
7777
} catch (AluException& e) {
78-
throw OpcodeExecutionException("Alu add operation failed");
78+
throw OpcodeExecutionException("Alu add operation failed: " + std::string(e.what()));
7979
}
8080
}
8181

@@ -115,7 +115,7 @@ void Execution::mul(ContextInterface& context, MemoryAddress a_addr, MemoryAddre
115115
memory.set(dst_addr, c);
116116
set_output(opcode, c);
117117
} catch (AluException& e) {
118-
throw OpcodeExecutionException("Alu mul operation failed");
118+
throw OpcodeExecutionException("Alu mul operation failed: " + std::string(e.what()));
119119
}
120120
}
121121

@@ -135,7 +135,7 @@ void Execution::div(ContextInterface& context, MemoryAddress a_addr, MemoryAddre
135135
memory.set(dst_addr, c);
136136
set_output(opcode, c);
137137
} catch (AluException& e) {
138-
throw OpcodeExecutionException("Alu div operation failed");
138+
throw OpcodeExecutionException("Alu div operation failed: " + std::string(e.what()));
139139
}
140140
}
141141

@@ -155,7 +155,7 @@ void Execution::fdiv(ContextInterface& context, MemoryAddress a_addr, MemoryAddr
155155
memory.set(dst_addr, c);
156156
set_output(opcode, c);
157157
} catch (AluException& e) {
158-
throw OpcodeExecutionException("Alu fdiv operation failed");
158+
throw OpcodeExecutionException("Alu fdiv operation failed: " + std::string(e.what()));
159159
}
160160
}
161161

@@ -175,7 +175,7 @@ void Execution::eq(ContextInterface& context, MemoryAddress a_addr, MemoryAddres
175175
memory.set(dst_addr, c);
176176
set_output(opcode, c);
177177
} catch (AluException& e) {
178-
throw OpcodeExecutionException("Alu eq operation failed");
178+
throw OpcodeExecutionException("Alu eq operation failed: " + std::string(e.what()));
179179
}
180180
}
181181

@@ -195,7 +195,7 @@ void Execution::lt(ContextInterface& context, MemoryAddress a_addr, MemoryAddres
195195
memory.set(dst_addr, c);
196196
set_output(opcode, c);
197197
} catch (AluException& e) {
198-
throw OpcodeExecutionException("Alu lt operation failed");
198+
throw OpcodeExecutionException("Alu lt operation failed: " + std::string(e.what()));
199199
}
200200
}
201201

@@ -215,7 +215,7 @@ void Execution::lte(ContextInterface& context, MemoryAddress a_addr, MemoryAddre
215215
memory.set(dst_addr, c);
216216
set_output(opcode, c);
217217
} catch (AluException& e) {
218-
throw OpcodeExecutionException("Alu lte operation failed");
218+
throw OpcodeExecutionException("Alu lte operation failed: " + std::string(e.what()));
219219
}
220220
}
221221

@@ -234,7 +234,7 @@ void Execution::op_not(ContextInterface& context, MemoryAddress src_addr, Memory
234234
memory.set(dst_addr, b);
235235
set_output(opcode, b);
236236
} catch (AluException& e) {
237-
throw OpcodeExecutionException("Alu not operation failed");
237+
throw OpcodeExecutionException("Alu not operation failed: " + std::string(e.what()));
238238
}
239239
}
240240

@@ -660,7 +660,7 @@ void Execution::and_op(ContextInterface& context, MemoryAddress a_addr, MemoryAd
660660
memory.set(dst_addr, c);
661661
set_output(opcode, c);
662662
} catch (const BitwiseException& e) {
663-
throw OpcodeExecutionException("Bitwise AND Exeception");
663+
throw OpcodeExecutionException("Bitwise AND Exeception: " + std::string(e.what()));
664664
}
665665
}
666666

@@ -682,7 +682,7 @@ void Execution::or_op(ContextInterface& context, MemoryAddress a_addr, MemoryAdd
682682
memory.set(dst_addr, c);
683683
set_output(opcode, c);
684684
} catch (const BitwiseException& e) {
685-
throw OpcodeExecutionException("Bitwise OR Exception");
685+
throw OpcodeExecutionException("Bitwise OR Exception: " + std::string(e.what()));
686686
}
687687
}
688688

@@ -704,7 +704,7 @@ void Execution::xor_op(ContextInterface& context, MemoryAddress a_addr, MemoryAd
704704
memory.set(dst_addr, c);
705705
set_output(opcode, c);
706706
} catch (const BitwiseException& e) {
707-
throw OpcodeExecutionException("Bitwise XOR Exception");
707+
throw OpcodeExecutionException("Bitwise XOR Exception: " + std::string(e.what()));
708708
}
709709
}
710710

@@ -858,7 +858,7 @@ void Execution::get_contract_instance(ContextInterface& context,
858858
try {
859859
get_contract_instance_component.get_contract_instance(memory, contract_address, dst_offset, member_enum);
860860
} catch (const GetContractInstanceException& e) {
861-
throw OpcodeExecutionException("GetContractInstance Exception");
861+
throw OpcodeExecutionException("GetContractInstance Exception: " + std::string(e.what()));
862862
}
863863

864864
// No `set_output` here since the dedicated component handles memory writes.
@@ -1041,7 +1041,7 @@ void Execution::emit_unencrypted_log(ContextInterface& context, MemoryAddress lo
10411041
emit_unencrypted_log_component.emit_unencrypted_log(
10421042
memory, context, context.get_address(), log_offset, log_size_int);
10431043
} catch (const EmitUnencryptedLogException& e) {
1044-
throw OpcodeExecutionException("EmitUnencryptedLog Exception");
1044+
throw OpcodeExecutionException("EmitUnencryptedLog Exception: " + std::string(e.what()));
10451045
}
10461046
}
10471047

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

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <variant>
1111
#include <vector>
1212

13+
#include "barretenberg/common/log.hpp"
1314
#include "barretenberg/common/serialize.hpp"
1415
#include "barretenberg/numeric/uint256/uint256.hpp"
1516
#include "barretenberg/vm2/common/addressing.hpp"
@@ -233,15 +234,23 @@ Instruction deserialize_instruction(std::span<const uint8_t> bytecode, size_t po
233234
const auto bytecode_length = bytecode.size();
234235

235236
if (pos >= bytecode_length) {
236-
vinfo("PC is out of range. Position: ", pos, " Bytecode length: ", bytecode_length);
237-
throw InstrDeserializationError::PC_OUT_OF_RANGE;
237+
std::string error_msg = format("Invalid program counter ", pos, ", max is ", bytecode_length - 1);
238+
vinfo(error_msg);
239+
throw InstrDeserializationError(InstrDeserializationEventError::PC_OUT_OF_RANGE, error_msg);
238240
}
239241

240242
const uint8_t opcode_byte = bytecode[pos];
241243

242244
if (!is_wire_opcode_valid(opcode_byte)) {
243-
vinfo("Invalid wire opcode byte: 0x", to_hex(opcode_byte), " at position: ", pos);
244-
throw InstrDeserializationError::OPCODE_OUT_OF_RANGE;
245+
std::string error_msg = format("Opcode ",
246+
static_cast<uint32_t>(opcode_byte),
247+
" (0x",
248+
to_hex(opcode_byte),
249+
") value is not in the range of valid opcodes (at PC ",
250+
pos,
251+
").");
252+
vinfo(error_msg);
253+
throw InstrDeserializationError(InstrDeserializationEventError::OPCODE_OUT_OF_RANGE, error_msg);
245254
}
246255

247256
const auto opcode = static_cast<WireOpCode>(opcode_byte);
@@ -254,15 +263,15 @@ Instruction deserialize_instruction(std::span<const uint8_t> bytecode, size_t po
254263
// We know we will encounter a parsing error, but continue processing because
255264
// we need the partial instruction to be parsed for witness generation.
256265
if (pos + instruction_size > bytecode_length) {
257-
vinfo("Instruction does not fit in remaining bytecode. Wire opcode: ",
258-
opcode,
259-
" pos: ",
260-
pos,
261-
" instruction size: ",
262-
instruction_size,
263-
" bytecode length: ",
264-
bytecode_length);
265-
throw InstrDeserializationError::INSTRUCTION_OUT_OF_RANGE;
266+
std::string error_msg = format("Instruction at PC ",
267+
pos,
268+
" does not fit in bytecode (instruction size: ",
269+
instruction_size,
270+
", remaining: ",
271+
bytecode_length - pos,
272+
")");
273+
vinfo(error_msg);
274+
throw InstrDeserializationError(InstrDeserializationEventError::INSTRUCTION_OUT_OF_RANGE, error_msg);
266275
}
267276

268277
pos++; // move after opcode byte

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

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include <cstdint>
1010
#include <memory>
11+
#include <optional>
12+
#include <string>
1113
#include <variant>
1214
#include <vector>
1315

@@ -47,7 +49,7 @@ struct Instruction {
4749
bool operator==(const Instruction& other) const = default;
4850
};
4951

50-
enum class InstrDeserializationError : uint8_t {
52+
enum class InstrDeserializationEventError : uint8_t {
5153
PC_OUT_OF_RANGE,
5254
OPCODE_OUT_OF_RANGE,
5355
INSTRUCTION_OUT_OF_RANGE,
@@ -57,6 +59,25 @@ enum class InstrDeserializationError : uint8_t {
5759
INVALID_EXECUTION_OPCODE,
5860
};
5961

62+
struct InstrDeserializationError {
63+
InstrDeserializationEventError type;
64+
std::optional<std::string> message;
65+
66+
// Constructor from error type only
67+
InstrDeserializationError(InstrDeserializationEventError t)
68+
: type(t)
69+
, message(std::nullopt)
70+
{}
71+
72+
// Constructor with error type and message
73+
InstrDeserializationError(InstrDeserializationEventError t, const std::string& msg)
74+
: type(t)
75+
, message(msg)
76+
{}
77+
78+
bool operator==(const InstrDeserializationError& other) const = default;
79+
};
80+
6081
/**
6182
* @brief Parsing of an instruction in the supplied bytecode at byte position pos. This
6283
* checks that the WireOpCode value is in the defined range and extracts the operands

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace {
1010
using simulation::check_tag;
1111
using simulation::deserialize_instruction;
1212
using simulation::InstrDeserializationError;
13+
using simulation::InstrDeserializationEventError;
1314
using simulation::Instruction;
1415
using simulation::Operand;
1516

@@ -119,7 +120,8 @@ TEST(SerializationTest, PCOutOfRange)
119120
try {
120121
deserialize_instruction(bytecode, bytecode.size() + 1);
121122
} catch (const InstrDeserializationError& error) {
122-
EXPECT_EQ(error, InstrDeserializationError::PC_OUT_OF_RANGE);
123+
EXPECT_EQ(error.type, InstrDeserializationEventError::PC_OUT_OF_RANGE);
124+
EXPECT_TRUE(error.message.has_value());
123125
}
124126
}
125127

@@ -132,7 +134,8 @@ TEST(SerializationTest, OpcodeOutOfRange)
132134
try {
133135
deserialize_instruction(bytecode, 0);
134136
} catch (const InstrDeserializationError& error) {
135-
EXPECT_EQ(error, InstrDeserializationError::OPCODE_OUT_OF_RANGE);
137+
EXPECT_EQ(error.type, InstrDeserializationEventError::OPCODE_OUT_OF_RANGE);
138+
EXPECT_TRUE(error.message.has_value());
136139
}
137140
}
138141

@@ -154,7 +157,8 @@ TEST(SerializationTest, InstructionOutOfRange)
154157
try {
155158
deserialize_instruction(bytecode, 0);
156159
} catch (const InstrDeserializationError& error) {
157-
EXPECT_EQ(error, InstrDeserializationError::INSTRUCTION_OUT_OF_RANGE);
160+
EXPECT_EQ(error.type, InstrDeserializationEventError::INSTRUCTION_OUT_OF_RANGE);
161+
EXPECT_TRUE(error.message.has_value());
158162
}
159163
}
160164

0 commit comments

Comments
 (0)