Skip to content

Commit b1b2e7c

Browse files
authored
feat(avm): add standalone jump opcode (AztecProtocol#3781)
- Add missing check that program counter advanced in call opcode ( oops ) - Moved return storing to intermediate register b - jump dest goes on register a - Implement trivial jump opcode ( subset of call )
1 parent e534204 commit b1b2e7c

File tree

11 files changed

+289
-231
lines changed

11 files changed

+289
-231
lines changed

barretenberg/cpp/pil/avm/avm_mini.pil

+24-15
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace avmMini(256);
1616

1717
pol commit sel_internal_call;
1818
pol commit sel_internal_return;
19+
pol commit sel_jump;
1920

2021
// Halt program execution
2122
pol commit sel_halt;
@@ -80,6 +81,7 @@ namespace avmMini(256);
8081

8182
sel_internal_call * (1 - sel_internal_call) = 0;
8283
sel_internal_return * (1 - sel_internal_return) = 0;
84+
sel_jump * (1 - sel_jump) = 0;
8385
sel_halt * (1 - sel_halt) = 0;
8486

8587
op_err * (1 - op_err) = 0;
@@ -147,33 +149,40 @@ namespace avmMini(256);
147149
// This works in combination with op_div_err * (sel_op_div - 1) = 0;
148150
// Drawback is the need to paralllelize the latter.
149151

152+
//===== CONTROL FLOW =======================================================
153+
//===== JUMP ===============================================================
154+
sel_jump * (pc' - ia) = 0;
150155

151-
//===== CALL_RETURN ========================================================
152-
// The program counter in the next row should be equal to the value loaded from the ia register
153-
// This implies that a load from memory must occur at the same time
154-
// Imply that we must load the return location into mem_idx_a
156+
//===== INTERNAL_CALL ======================================================
157+
// - The program counter in the next row should be equal to the value loaded from the ia register
158+
// - We then write the return location (pc + 1) into the call stack (in memory)
155159

156160
#[RETURN_POINTER_INCREMENT]
157-
sel_internal_call * ( internal_return_ptr' - ( internal_return_ptr + 1)) = 0;
158-
sel_internal_call * ( internal_return_ptr - mem_idx_a) = 0;
159-
sel_internal_call * ((pc + 1) - ia) = 0;
160-
161+
sel_internal_call * (internal_return_ptr' - (internal_return_ptr + 1)) = 0;
162+
sel_internal_call * (internal_return_ptr - mem_idx_b) = 0;
163+
sel_internal_call * (pc' - ia) = 0;
164+
sel_internal_call * ((pc + 1) - ib) = 0;
165+
161166
// TODO(md): Below relations may be removed through sub-op table lookup
162-
sel_internal_call * (rwa - 1) = 0;
163-
sel_internal_call * (mem_op_a - 1) = 0;
167+
sel_internal_call * (rwb - 1) = 0;
168+
sel_internal_call * (mem_op_b - 1) = 0;
164169

165-
// We must load the memory pointer to be the internal_return_ptr
170+
//===== INTERNAL_RETURN ===================================================
171+
// - We load the memory pointer to be the internal_return_ptr
172+
// - Constrain then next program counter to be the loaded value
173+
// - decrement the internal_return_ptr
174+
166175
#[RETURN_POINTER_DECREMENT]
167-
sel_internal_return * ( internal_return_ptr' - ( internal_return_ptr - 1)) = 0;
168-
sel_internal_return * ( (internal_return_ptr - 1) - mem_idx_a) = 0;
176+
sel_internal_return * (internal_return_ptr' - (internal_return_ptr - 1)) = 0;
177+
sel_internal_return * ((internal_return_ptr - 1) - mem_idx_a) = 0;
169178
sel_internal_return * (pc' - ia) = 0;
170179

171180
// TODO(md): Below relations may be removed through sub-op table lookup
172181
sel_internal_return * rwa = 0;
173182
sel_internal_return * (mem_op_a - 1) = 0;
174183

175184
//===== CONTROL_FLOW_CONSISTENCY ============================================
176-
pol CONTROL_FLOW_SELECTORS = (first + sel_internal_call + sel_internal_return + sel_halt);
185+
pol INTERNAL_CALL_STACK_SELECTORS = (first + sel_internal_call + sel_internal_return + sel_halt);
177186
pol OPCODE_SELECTORS = (sel_op_add + sel_op_sub + sel_op_div + sel_op_mul);
178187

179188
// Program counter must increment if not jumping or returning
@@ -182,7 +191,7 @@ namespace avmMini(256);
182191

183192
// first == 0 && sel_internal_call == 0 && sel_internal_return == 0 && sel_halt == 0 ==> internal_return_ptr == internal_return_ptr'
184193
#[INTERNAL_RETURN_POINTER_CONSISTENCY]
185-
(1 - CONTROL_FLOW_SELECTORS) * (internal_return_ptr' - internal_return_ptr) = 0;
194+
(1 - INTERNAL_CALL_STACK_SELECTORS) * (internal_return_ptr' - internal_return_ptr) = 0;
186195

187196
// TODO: we want to set an initial number for the reserved memory of the jump pointer
188197

barretenberg/cpp/pil/avm/avm_mini_opt.pil

-68
This file was deleted.

barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp

+28-21
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ class AvmMiniFlavor {
3636
using VerifierCommitmentKey = pcs::VerifierCommitmentKey<Curve>;
3737

3838
static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2;
39-
static constexpr size_t NUM_WITNESS_ENTITIES = 37;
39+
static constexpr size_t NUM_WITNESS_ENTITIES = 38;
4040
static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES;
4141
// We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for
4242
// the unshifted and one for the shifted
43-
static constexpr size_t NUM_ALL_ENTITIES = 45;
43+
static constexpr size_t NUM_ALL_ENTITIES = 46;
4444

45-
using Relations = std::tuple<AvmMini_vm::avm_mini<FF>, AvmMini_vm::mem_trace<FF>>;
45+
using Relations = std::tuple<AvmMini_vm::mem_trace<FF>, AvmMini_vm::avm_mini<FF>>;
4646

4747
static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length<Relations>();
4848

@@ -91,6 +91,7 @@ class AvmMiniFlavor {
9191
avmMini_internal_return_ptr,
9292
avmMini_sel_internal_call,
9393
avmMini_sel_internal_return,
94+
avmMini_sel_jump,
9495
avmMini_sel_halt,
9596
avmMini_sel_op_add,
9697
avmMini_sel_op_sub,
@@ -131,6 +132,7 @@ class AvmMiniFlavor {
131132
avmMini_internal_return_ptr,
132133
avmMini_sel_internal_call,
133134
avmMini_sel_internal_return,
135+
avmMini_sel_jump,
134136
avmMini_sel_halt,
135137
avmMini_sel_op_add,
136138
avmMini_sel_op_sub,
@@ -177,6 +179,7 @@ class AvmMiniFlavor {
177179
avmMini_internal_return_ptr,
178180
avmMini_sel_internal_call,
179181
avmMini_sel_internal_return,
182+
avmMini_sel_jump,
180183
avmMini_sel_halt,
181184
avmMini_sel_op_add,
182185
avmMini_sel_op_sub,
@@ -199,12 +202,12 @@ class AvmMiniFlavor {
199202
avmMini_mem_idx_b,
200203
avmMini_mem_idx_c,
201204
avmMini_last,
202-
avmMini_internal_return_ptr_shift,
203-
avmMini_pc_shift,
204-
memTrace_m_tag_shift,
205205
memTrace_m_val_shift,
206+
memTrace_m_addr_shift,
207+
memTrace_m_tag_shift,
206208
memTrace_m_rw_shift,
207-
memTrace_m_addr_shift)
209+
avmMini_internal_return_ptr_shift,
210+
avmMini_pc_shift)
208211

209212
RefVector<DataType> get_wires()
210213
{
@@ -225,6 +228,7 @@ class AvmMiniFlavor {
225228
avmMini_internal_return_ptr,
226229
avmMini_sel_internal_call,
227230
avmMini_sel_internal_return,
231+
avmMini_sel_jump,
228232
avmMini_sel_halt,
229233
avmMini_sel_op_add,
230234
avmMini_sel_op_sub,
@@ -247,12 +251,12 @@ class AvmMiniFlavor {
247251
avmMini_mem_idx_b,
248252
avmMini_mem_idx_c,
249253
avmMini_last,
250-
avmMini_internal_return_ptr_shift,
251-
avmMini_pc_shift,
252-
memTrace_m_tag_shift,
253254
memTrace_m_val_shift,
255+
memTrace_m_addr_shift,
256+
memTrace_m_tag_shift,
254257
memTrace_m_rw_shift,
255-
memTrace_m_addr_shift };
258+
avmMini_internal_return_ptr_shift,
259+
avmMini_pc_shift };
256260
};
257261
RefVector<DataType> get_unshifted()
258262
{
@@ -273,6 +277,7 @@ class AvmMiniFlavor {
273277
avmMini_internal_return_ptr,
274278
avmMini_sel_internal_call,
275279
avmMini_sel_internal_return,
280+
avmMini_sel_jump,
276281
avmMini_sel_halt,
277282
avmMini_sel_op_add,
278283
avmMini_sel_op_sub,
@@ -298,18 +303,17 @@ class AvmMiniFlavor {
298303
};
299304
RefVector<DataType> get_to_be_shifted()
300305
{
301-
return {
302-
avmMini_internal_return_ptr, avmMini_pc, memTrace_m_tag, memTrace_m_val, memTrace_m_rw, memTrace_m_addr
303-
};
306+
return { memTrace_m_val, memTrace_m_addr, memTrace_m_tag, memTrace_m_rw, avmMini_internal_return_ptr,
307+
avmMini_pc };
304308
};
305309
RefVector<DataType> get_shifted()
306310
{
307-
return { avmMini_internal_return_ptr_shift,
308-
avmMini_pc_shift,
311+
return { memTrace_m_val_shift,
312+
memTrace_m_addr_shift,
309313
memTrace_m_tag_shift,
310-
memTrace_m_val_shift,
311314
memTrace_m_rw_shift,
312-
memTrace_m_addr_shift };
315+
avmMini_internal_return_ptr_shift,
316+
avmMini_pc_shift };
313317
};
314318
};
315319

@@ -322,9 +326,8 @@ class AvmMiniFlavor {
322326

323327
RefVector<DataType> get_to_be_shifted()
324328
{
325-
return {
326-
avmMini_internal_return_ptr, avmMini_pc, memTrace_m_tag, memTrace_m_val, memTrace_m_rw, memTrace_m_addr
327-
};
329+
return { memTrace_m_val, memTrace_m_addr, memTrace_m_tag, memTrace_m_rw, avmMini_internal_return_ptr,
330+
avmMini_pc };
328331
};
329332

330333
// The plookup wires that store plookup read data.
@@ -418,6 +421,7 @@ class AvmMiniFlavor {
418421
Base::avmMini_internal_return_ptr = "AVMMINI_INTERNAL_RETURN_PTR";
419422
Base::avmMini_sel_internal_call = "AVMMINI_SEL_INTERNAL_CALL";
420423
Base::avmMini_sel_internal_return = "AVMMINI_SEL_INTERNAL_RETURN";
424+
Base::avmMini_sel_jump = "AVMMINI_SEL_JUMP";
421425
Base::avmMini_sel_halt = "AVMMINI_SEL_HALT";
422426
Base::avmMini_sel_op_add = "AVMMINI_SEL_OP_ADD";
423427
Base::avmMini_sel_op_sub = "AVMMINI_SEL_OP_SUB";
@@ -474,6 +478,7 @@ class AvmMiniFlavor {
474478
Commitment avmMini_internal_return_ptr;
475479
Commitment avmMini_sel_internal_call;
476480
Commitment avmMini_sel_internal_return;
481+
Commitment avmMini_sel_jump;
477482
Commitment avmMini_sel_halt;
478483
Commitment avmMini_sel_op_add;
479484
Commitment avmMini_sel_op_sub;
@@ -530,6 +535,7 @@ class AvmMiniFlavor {
530535
avmMini_internal_return_ptr = deserialize_from_buffer<Commitment>(Transcript::proof_data, num_bytes_read);
531536
avmMini_sel_internal_call = deserialize_from_buffer<Commitment>(Transcript::proof_data, num_bytes_read);
532537
avmMini_sel_internal_return = deserialize_from_buffer<Commitment>(Transcript::proof_data, num_bytes_read);
538+
avmMini_sel_jump = deserialize_from_buffer<Commitment>(Transcript::proof_data, num_bytes_read);
533539
avmMini_sel_halt = deserialize_from_buffer<Commitment>(Transcript::proof_data, num_bytes_read);
534540
avmMini_sel_op_add = deserialize_from_buffer<Commitment>(Transcript::proof_data, num_bytes_read);
535541
avmMini_sel_op_sub = deserialize_from_buffer<Commitment>(Transcript::proof_data, num_bytes_read);
@@ -590,6 +596,7 @@ class AvmMiniFlavor {
590596
serialize_to_buffer<Commitment>(avmMini_internal_return_ptr, Transcript::proof_data);
591597
serialize_to_buffer<Commitment>(avmMini_sel_internal_call, Transcript::proof_data);
592598
serialize_to_buffer<Commitment>(avmMini_sel_internal_return, Transcript::proof_data);
599+
serialize_to_buffer<Commitment>(avmMini_sel_jump, Transcript::proof_data);
593600
serialize_to_buffer<Commitment>(avmMini_sel_halt, Transcript::proof_data);
594601
serialize_to_buffer<Commitment>(avmMini_sel_op_add, Transcript::proof_data);
595602
serialize_to_buffer<Commitment>(avmMini_sel_op_sub, Transcript::proof_data);

barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.cpp

+30-5
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,30 @@ void AvmMiniTraceBuilder::halt()
566566
});
567567
}
568568

569+
/**
570+
* @brief JUMP OPCODE
571+
* Jumps to a new `jmpDest`
572+
* This function must:
573+
* - Set the next program counter to the provided `jmpDest`.
574+
*
575+
* @param jmpDest - The destination to jump to
576+
*/
577+
void AvmMiniTraceBuilder::jump(uint32_t jmpDest)
578+
{
579+
auto clk = mainTrace.size();
580+
581+
mainTrace.push_back(Row{
582+
.avmMini_clk = clk,
583+
.avmMini_pc = FF(pc),
584+
.avmMini_internal_return_ptr = FF(internal_return_ptr),
585+
.avmMini_sel_jump = FF(1),
586+
.avmMini_ia = FF(jmpDest),
587+
});
588+
589+
// Adjust parameters for the next row
590+
pc = jmpDest;
591+
}
592+
569593
/**
570594
* @brief INTERNAL_CALL OPCODE
571595
* This opcode effectively jumps to a new `jmpDest` and stores the return program counter
@@ -588,18 +612,19 @@ void AvmMiniTraceBuilder::internal_call(uint32_t jmpDest)
588612
internal_call_stack.push(stored_pc);
589613

590614
// Add the return location to the memory trace
591-
storeInMemTrace(IntermRegister::ia, internal_return_ptr, FF(stored_pc), AvmMemoryTag::ff);
615+
storeInMemTrace(IntermRegister::ib, internal_return_ptr, FF(stored_pc), AvmMemoryTag::ff);
592616
memory.at(internal_return_ptr) = stored_pc;
593617

594618
mainTrace.push_back(Row{
595619
.avmMini_clk = clk,
596620
.avmMini_pc = FF(pc),
597621
.avmMini_internal_return_ptr = FF(internal_return_ptr),
598622
.avmMini_sel_internal_call = FF(1),
599-
.avmMini_ia = stored_pc,
600-
.avmMini_mem_op_a = FF(1),
601-
.avmMini_rwa = FF(1),
602-
.avmMini_mem_idx_a = FF(internal_return_ptr),
623+
.avmMini_ia = FF(jmpDest),
624+
.avmMini_ib = stored_pc,
625+
.avmMini_mem_op_b = FF(1),
626+
.avmMini_rwb = FF(1),
627+
.avmMini_mem_idx_b = FF(internal_return_ptr),
603628
});
604629

605630
// Adjust parameters for the next row

barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ class AvmMiniTraceBuilder {
6060
void div(uint32_t aOffset, uint32_t bOffset, uint32_t dstOffset, AvmMemoryTag inTag);
6161

6262
// Jump to a given program counter.
63+
void jump(uint32_t jmpDest);
64+
65+
// Jump to a given program counter; storing the return location on a call stack.
6366
// TODO(md): this program counter MUST be an operand to the OPCODE.
6467
void internal_call(uint32_t jmpDest);
6568

0 commit comments

Comments
 (0)