Skip to content

Commit 40154d5

Browse files
authored
bytecode: reorg implementation (#7)
* bytecode: reorg implementation * fix conflicts
1 parent 51c2811 commit 40154d5

File tree

10 files changed

+198
-190
lines changed

10 files changed

+198
-190
lines changed

crates/leanVm/src/bytecode/hint.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use super::operand::MemOrConstant;
2+
3+
/// Hints are special instructions for the prover to resolve non-determinism.
4+
///
5+
/// They are not part of the verified computation trace.
6+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7+
pub enum Hint<F> {
8+
/// A hint for the prover to allocate a new memory segment for a function's stack frame.
9+
///
10+
/// This is the core mechanism for memory management in a VM without an `ap` (allocation pointer)
11+
/// register. The compiler pre-calculates the required memory size for each function.
12+
RequestMemory {
13+
/// The offset from `fp` where the pointer to the newly allocated segment will be stored.
14+
offset: usize,
15+
/// The requested size of the memory segment in scalar field elements.
16+
size: MemOrConstant<F>,
17+
/// If true, the start of the allocated memory is aligned to an 8-element boundary
18+
/// to facilitate vectorized memory access for extension field operations.
19+
/// The value stored at `m[fp + offset]` will be the aligned address divided by 8.
20+
vectorized: bool,
21+
},
22+
/// A hint for the prover to compute the bit decomposition of a base field element.
23+
///
24+
/// This is a non-deterministic operation used for operations like range checks
25+
/// or other logic required by the XMSS signature scheme.
26+
DecomposeBits {
27+
/// The starting offset from `fp` where the resulting bits will be stored.
28+
res_offset: usize,
29+
/// The field element that needs to be decomposed into its bits.
30+
to_decompose: MemOrConstant<F>,
31+
},
32+
/// A hint used for debugging to print values from memory during execution.
33+
Print {
34+
/// A string containing line information (e.g., file and line number) for context.
35+
line_info: String,
36+
/// A list of memory locations or constants whose values should be printed.
37+
content: Vec<MemOrConstant<F>>,
38+
},
39+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use super::{
2+
operand::{MemOrConstant, MemOrFp, MemOrFpOrConstant},
3+
operation::Operation,
4+
};
5+
6+
/// Defines the instruction set for this zkVM, specialized for the `AggregateMerge` logic.
7+
///
8+
/// The ISA is minimal and includes basic arithmetic, memory operations, control flow,
9+
/// and powerful precompiles for hashing and extension field arithmetic.
10+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
11+
pub enum Instruction<F> {
12+
/// Performs a basic arithmetic computation: `res = arg_a op arg_b`.
13+
///
14+
/// This corresponds to the `ADD` and `MUL` opcodes in the design document.
15+
Computation {
16+
/// The arithmetic operation to perform (`Add` or `Mul`).
17+
operation: Operation,
18+
/// The first operand of the computation.
19+
arg_a: MemOrConstant<F>,
20+
/// The second operand of the computation.
21+
arg_b: MemOrFp,
22+
/// The memory location or constant that the result must be equal to.
23+
res: MemOrConstant<F>,
24+
},
25+
/// Performs a memory dereference: `res = m[m[fp + shift_0] + shift_1]`.
26+
///
27+
/// This corresponds to the `DEREF` opcode.
28+
Deref {
29+
/// The offset from `fp` for the first memory access, which yields a pointer.
30+
shift_0: usize,
31+
/// The offset added to the pointer from the first access to get the final address.
32+
shift_1: usize,
33+
/// The value that the result of the double dereference must be equal to.
34+
res: MemOrFpOrConstant<F>,
35+
},
36+
/// A conditional jump, called `JUZ` (Jump Unless Zero).
37+
///
38+
/// Changes the `pc` if `condition` is non-zero.
39+
JumpIfNotZero {
40+
/// The value to check. The jump is taken if this value is not zero.
41+
condition: MemOrConstant<F>,
42+
/// The destination `pc` for the jump.
43+
dest: MemOrConstant<F>,
44+
/// The new value for the frame pointer (`fp`) after the instruction.
45+
updated_fp: MemOrFp,
46+
},
47+
/// **Precompile** for a Poseidon2 permutation over 16 base field elements.
48+
///
49+
/// This is used for hashing operations within the `AggregateMerge` algorithm.
50+
/// The precompile performs: `Poseidon2(m'[m[fp+s]], m'[m[fp+s+1]]) = (m'[m[fp+s+2]], m'[m[fp+s+3]])`,
51+
/// where:
52+
/// - `s` is the shift,
53+
/// - `m` is scalar memory,
54+
/// - `m'` is vectorized memory access (a chunk of 8 base field elements, representing a degree-8 extension field element).
55+
Poseidon2_16 {
56+
/// The starting offset `s` from `fp`. The instruction reads 4 pointers from `m[fp+s]` to `m[fp+s+3]`.
57+
shift: usize,
58+
},
59+
/// **Precompile** for a Poseidon2 permutation over 24 base field elements.
60+
///
61+
/// This operates similarly to `Poseidon2_16` but on 3 concatenated input vectors and 3 output vectors.
62+
///
63+
/// It reads 6 pointers from memory, starting at `m[fp+shift]`.
64+
Poseidon2_24 {
65+
/// The starting offset from `fp`. The instruction reads 6 pointers from `m[fp+shift]` to `m[fp+shift+5]`.
66+
shift: usize,
67+
},
68+
/// **Precompile** for multiplication in the degree-8 extension field.
69+
///
70+
/// This is important for speeding up recursive proof verification (`snark_verify`).
71+
ExtensionMul {
72+
/// An array of three offsets from `fp`. These point to the start of the 8-cell memory blocks
73+
/// for the two input extension field elements and the resulting output element.
74+
args: [usize; 3],
75+
},
76+
}

crates/leanVm/src/bytecode/mod.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use std::collections::BTreeMap;
2+
3+
use hint::Hint;
4+
use instruction::Instruction;
5+
6+
pub mod hint;
7+
pub mod instruction;
8+
pub mod operand;
9+
pub mod operation;
10+
11+
/// Represents the compiled bytecode of a program for the zkVM.
12+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
13+
pub struct Bytecode<F> {
14+
/// A vector of instructions that form the executable part of the program.
15+
///
16+
/// The Program Counter (pc) iterates over this vector.
17+
pub instructions: Vec<Instruction<F>>,
18+
19+
/// A map from a program counter (pc) value to a list of `Hint`s.
20+
///
21+
/// Hints are auxiliary, non-deterministic instructions executed only by the prover.
22+
///
23+
/// In this zkVM, they are crucial for managing memory allocations in the absence
24+
/// of an `ap` register.
25+
pub hints: BTreeMap<usize, Vec<Hint<F>>>,
26+
27+
/// The memory offset from the frame pointer (fp) where the public input for the program begins.
28+
pub public_input_start: usize,
29+
30+
/// The program counter (pc) value at which the program execution is considered complete.
31+
pub ending_pc: usize,
32+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/// Represents a value that can either be a constant or a value from memory.
2+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
3+
pub enum MemOrConstant<F> {
4+
/// A constant value (a field element).
5+
Constant(F),
6+
/// A memory location specified by a positive offset from the frame pointer (`fp`).
7+
///
8+
/// Represents the scalar value at `m[fp + shift]`.
9+
MemoryAfterFp {
10+
/// The offset from `fp` where the memory location is located.
11+
shift: usize,
12+
},
13+
}
14+
15+
/// Represents a value that can be a memory location, the `fp` register itself, or a constant.
16+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
17+
pub enum MemOrFpOrConstant<F> {
18+
/// A memory location specified by a positive offset from `fp`. Represents `m[fp + shift]`.
19+
MemoryAfterFp {
20+
/// The offset from `fp` where the memory location is located.
21+
shift: usize,
22+
},
23+
/// The value of the frame pointer (`fp`) register itself.
24+
Fp,
25+
/// A constant value (a field element).
26+
Constant(F),
27+
}
28+
29+
/// Represents a value that is either a memory location or the `fp` register itself.
30+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
31+
pub enum MemOrFp {
32+
/// A memory location specified by a positive offset from `fp`. Represents `m[fp + shift]`.
33+
MemoryAfterFp {
34+
/// The offset from `fp` where the memory location is located.
35+
shift: usize,
36+
},
37+
/// The value of the frame pointer (`fp`) register itself.
38+
Fp,
39+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/// The basic arithmetic operations supported by the VM's `Computation` instruction.
2+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
3+
pub enum Operation {
4+
/// Field addition in the base field.
5+
Add,
6+
/// Field multiplication in the base field.
7+
Mul,
8+
}

crates/leanVm/src/context/run_context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use p3_field::PrimeField64;
22

33
use crate::{
4+
bytecode::operand::{MemOrConstant, MemOrFp, MemOrFpOrConstant},
45
errors::{memory::MemoryError, vm::VirtualMachineError},
56
memory::{address::MemoryAddress, manager::MemoryManager, val::MemoryValue},
6-
types::instruction::{MemOrConstant, MemOrFp, MemOrFpOrConstant},
77
};
88

99
#[derive(Debug, Default)]

crates/leanVm/src/core.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use p3_field::PrimeField64;
22

33
use crate::{
4+
bytecode::{instruction::Instruction, operand::MemOrFp},
45
context::run_context::RunContext,
56
errors::{memory::MemoryError, vm::VirtualMachineError},
67
memory::manager::MemoryManager,
7-
types::instruction::{Instruction, MemOrFp},
88
};
99

1010
#[derive(Debug, Default)]
@@ -130,8 +130,8 @@ mod tests {
130130

131131
use super::*;
132132
use crate::{
133+
bytecode::{operand::MemOrConstant, operation::Operation},
133134
memory::{address::MemoryAddress, val::MemoryValue},
134-
types::instruction::{MemOrConstant, Operation},
135135
};
136136

137137
type F = BabyBear;

crates/leanVm/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
pub mod bytecode;
12
pub mod context;
23
pub mod core;
34
pub mod errors;
45
pub mod memory;
5-
pub mod types;

0 commit comments

Comments
 (0)