Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
addressing.test.cpp
Go to the documentation of this file.
2
3#include <gmock/gmock.h>
4#include <gtest/gtest.h>
5
15
16namespace bb::avm2::simulation {
17namespace {
18
19using ::bb::avm2::testing::InstructionBuilder;
20using enum ::bb::avm2::WireOpCode;
21using ::testing::ElementsAre;
22using ::testing::ReturnRef;
23using ::testing::StrictMock;
24
25template <typename T> auto from = ::bb::avm2::simulation::Operand::from<T>;
26
27TEST(AvmSimulationAddressingTest, AllDirectAndNonRelative)
28{
29 InstructionInfoDB instruction_info_db;
30 NoopEventEmitter<AddressingEvent> event_emitter;
31
32 // No calls to range checks.
33 StrictMock<MockRangeCheck> range_check;
34
35 Addressing addressing(instruction_info_db, range_check, event_emitter);
36
37 {
38 const auto instr = InstructionBuilder(SET_8)
39 // dstOffset
40 .operand<uint8_t>(1)
41 // tag
42 .operand(MemoryTag::FF)
43 // value
44 .operand<uint8_t>(1)
45 .build();
46
47 // No calls to get the base address.
48 StrictMock<MockMemory> memory;
49
50 const auto operands = addressing.resolve(instr, memory);
51 EXPECT_THAT(operands,
52 ElementsAre(
53 // dstOffset has been resolved and is now a MemoryAddress.
54 from<MemoryAddress>(1),
55 // tag is unchanged.
56 instr.operands.at(1),
57 // value is unchanged.
58 instr.operands.at(2)));
59 }
60 {
61 const auto instr = InstructionBuilder(ADD_16)
62 // aOffset
63 .operand<uint16_t>(1)
64 // bOffset
65 .operand<uint16_t>(2)
66 // dstOffset
67 .operand<uint16_t>(3)
68 .build();
69
70 // No calls to get the base address.
71 StrictMock<MockMemory> memory;
72
73 const auto operands = addressing.resolve(instr, memory);
74 EXPECT_THAT(operands, ElementsAre(from<MemoryAddress>(1), from<MemoryAddress>(2), from<MemoryAddress>(3)));
75 }
76}
77
78TEST(AvmSimulationAddressingTest, RelativeAddressing)
79{
80 InstructionInfoDB instruction_info_db;
81 NoopEventEmitter<AddressingEvent> event_emitter;
82 StrictMock<MockRangeCheck> range_check;
83 Addressing addressing(instruction_info_db, range_check, event_emitter);
84
85 // For relative addressing, we need a base address other than 0
86 // Base pointer at address 100
87 MemoryValue base_addr = MemoryValue::from<uint32_t>(100);
88
89 // Set up the ADD_8 instruction with relative addressing
90 const auto instr = InstructionBuilder(ADD_8)
91 // aOffset
92 .operand<uint8_t>(10)
93 .relative()
94 // bOffset
95 .operand<uint8_t>(20)
96 // dstOffset
97 .operand<uint8_t>(30)
98 .relative()
99 .build();
100
101 StrictMock<MockMemory> memory;
102 EXPECT_CALL(memory, get(0)).WillOnce(ReturnRef(base_addr));
103 // Range check calls. This leaks information from the circuit.
104 EXPECT_CALL(range_check, assert_range((1ULL << 32) - 110 - 1, /*num_bits=*/32));
105 EXPECT_CALL(range_check, assert_range((1ULL << 32) - 130 - 1, /*num_bits=*/32));
106
107 const auto operands = addressing.resolve(instr, memory);
108
109 EXPECT_THAT(operands,
110 ElementsAre(
111 // aOffset resolved as base + 10 = 110
112 from<MemoryAddress>(110),
113 // bOffset stays the same
114 from<MemoryAddress>(20),
115 // dstOffset resolved as base + 30 = 130
116 from<MemoryAddress>(130)));
117}
118
119TEST(AvmSimulationAddressingTest, IndirectAddressing)
120{
121 InstructionInfoDB instruction_info_db;
122 NoopEventEmitter<AddressingEvent> event_emitter;
123 // No calls to range checks.
124 StrictMock<MockRangeCheck> range_check;
125 Addressing addressing(instruction_info_db, range_check, event_emitter);
126
127 // Set up the ADD_8 instruction with indirect addressing
128 const auto instr = InstructionBuilder(ADD_8)
129 // aOffset - address 5 contains the actual address
130 .operand<uint8_t>(5)
131 .indirect()
132 // bOffset
133 .operand<uint8_t>(10)
134 // dstOffset - address 15 contains the actual address
135 .operand<uint8_t>(15)
136 .indirect()
137 .build();
138
139 StrictMock<MockMemory> memory;
140 MemoryValue addr_5_value = MemoryValue::from<uint32_t>(50);
141 EXPECT_CALL(memory, get(5)).WillOnce(ReturnRef(addr_5_value));
142 MemoryValue addr_15_value = MemoryValue::from<uint32_t>(60);
143 EXPECT_CALL(memory, get(15)).WillOnce(ReturnRef(addr_15_value));
144
145 const auto operands = addressing.resolve(instr, memory);
146
147 // Expect indirect offsets to be resolved by looking up their values in memory
148 EXPECT_THAT(operands,
149 ElementsAre(
150 // aOffset resolved indirectly: memory[5] = 50
151 from<MemoryAddress>(50),
152 // bOffset stays the same
153 from<MemoryAddress>(10),
154 // dstOffset resolved indirectly: memory[15] = 60
155 from<MemoryAddress>(60)));
156}
157
158TEST(AvmSimulationAddressingTest, IndirectAndRelativeAddressing)
159{
160 InstructionInfoDB instruction_info_db;
161 NoopEventEmitter<AddressingEvent> event_emitter;
162 StrictMock<MockRangeCheck> range_check;
163 Addressing addressing(instruction_info_db, range_check, event_emitter);
164
165 // Base address is 100
166 MemoryValue base_addr = MemoryValue::from<uint32_t>(100);
167
168 // Set up the ADD_8 instruction with both indirect and relative addressing
169 const auto instr = InstructionBuilder(ADD_8)
170 // aOffset (indirect and relative): address base+5 contains value
171 .operand<uint8_t>(5)
172 .indirect()
173 .relative()
174 // bOffset (indirect only): address 10 contains value
175 .operand<uint8_t>(10)
176 .indirect()
177 // dstOffset (relative only)
178 .operand<uint8_t>(15)
179 .relative()
180 .build();
181
182 StrictMock<MockMemory> memory;
183 EXPECT_CALL(memory, get(0)).WillOnce(ReturnRef(base_addr)); // Base address (100)
184 // Address 105 (base+5) contains value 200
185 MemoryValue addr_105_value = MemoryValue::from<uint32_t>(200);
186 EXPECT_CALL(memory, get(105)).WillOnce(ReturnRef(addr_105_value));
187 // Address 10 contains value 60
188 MemoryValue addr_10_value = MemoryValue::from<uint32_t>(60);
189 EXPECT_CALL(memory, get(10)).WillOnce(ReturnRef(addr_10_value));
190 // Range check calls. This leaks information from the circuit.
191 EXPECT_CALL(range_check, assert_range((1ULL << 32) - 105 - 1, /*num_bits=*/32));
192 EXPECT_CALL(range_check, assert_range((1ULL << 32) - 115 - 1, /*num_bits=*/32));
193
194 const auto operands = addressing.resolve(instr, memory);
195
196 // Expect combined indirect and relative addressing
197 EXPECT_THAT(operands,
198 ElementsAre(
199 // aOffset: relative (base+5=105) and indirect (memory[105]=200)
200 from<MemoryAddress>(200),
201 // bOffset: indirect only (memory[10]=60)
202 from<MemoryAddress>(60),
203 // dstOffset: relative only (base+15=115)
204 from<MemoryAddress>(115)));
205}
206
207} // namespace
208} // namespace bb::avm2::simulation
EventEmitter< DataCopyEvent > event_emitter
RangeCheck range_check
InstructionInfoDB instruction_info_db
TEST(EmitUnencryptedLogTest, Basic)
TaggedValue MemoryValue
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
MemoryStore memory