Skip to content

Commit

Permalink
implement Blake2s opcode in runner
Browse files Browse the repository at this point in the history
  • Loading branch information
ohad-nir-starkware committed Jan 31, 2025
1 parent a0f8806 commit d25cef1
Show file tree
Hide file tree
Showing 11 changed files with 439 additions and 67 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ jobs:
cairo_bench_programs,
cairo_proof_programs,
cairo_test_programs,
cairo_stwo_exclusive_programs,
cairo_1_test_contracts,
cairo_2_test_contracts,
]
Expand Down Expand Up @@ -124,6 +125,12 @@ jobs:
path: ${{ env.CAIRO_PROGRAMS_PATH }}
key: cairo_test_programs-cache-${{ hashFiles('cairo_programs/**/*.cairo', 'examples/wasm-demo/src/array_sum.cairo') }}
fail-on-cache-miss: true
- name: Fetch cairo stwo exclusive programs
uses: actions/cache/restore@v3
with:
path: ${{ env.CAIRO_PROGRAMS_PATH }}
key: cairo_stwo_exclusive_programs-cache-${{ hashFiles('cairo_programs/**/*.cairo', 'examples/wasm-demo/src/array_sum.cairo') }}
fail-on-cache-miss: true
- name: Fetch proof programs
uses: actions/cache/restore@v3
with:
Expand Down Expand Up @@ -486,6 +493,9 @@ jobs:
- program-target: cairo_test_programs
programs-dir: cairo_programs
extra-args: '--cairo_pie_output {program}.rs.pie.zip'
- program-target: cairo_stwo_exclusive_programs
programs-dir: cairo_programs
extra-args: '--cairo_pie_output {program}.rs.pie.zip'
name: Compute memory and execution traces with cairo-vm
needs: [ build-programs, build-release ]
runs-on: ubuntu-22.04
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#### Upcoming Changes

* feat: implement `Blake2s` opcode in VM [#1927](https://github.com/lambdaclass/cairo-vm/pull/1927)

* refactor: Limit ret opcode decodeing to Cairo0's standards. [#1925](https://github.com/lambdaclass/cairo-vm/pull/1925)

#### [2.0.0-rc4] - 2025-01-23
Expand Down
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ CAIRO_RS_MEM:=$(patsubst $(TEST_DIR)/%.json, $(TEST_DIR)/%.rs.memory, $(COMPILED
CAIRO_RS_TRACE:=$(patsubst $(TEST_DIR)/%.json, $(TEST_DIR)/%.rs.trace, $(COMPILED_TESTS))
CAIRO_RS_PIE:=$(patsubst $(TEST_DIR)/%.json, $(TEST_DIR)/%.rs.pie.zip, $(COMPILED_TESTS))

STWO_EXCLUSIVE_DIR=cairo_programs/stwo_exclusive_programs
STWO_EXCLUSIVE_FILES:=$(wildcard $(STWO_EXCLUSIVE_DIR)/*.cairo)
COMPILED_STWO_EXCLUSIVE_TESTS:=$(patsubst $(STWO_EXCLUSIVE_DIR)/%.cairo, $(STWO_EXCLUSIVE_DIR)/%.json, $(STWO_EXCLUSIVE_FILES))

BENCH_DIR=cairo_programs/benchmarks
BENCH_FILES:=$(wildcard $(BENCH_DIR)/*.cairo)
COMPILED_BENCHES:=$(patsubst $(BENCH_DIR)/%.cairo, $(BENCH_DIR)/%.json, $(BENCH_FILES))
Expand Down Expand Up @@ -249,6 +253,7 @@ check:

cairo_test_programs: $(COMPILED_TESTS) $(COMPILED_BAD_TESTS) $(COMPILED_NORETROCOMPAT_TESTS) $(COMPILED_PRINT_TESTS) $(COMPILED_MOD_BUILTIN_TESTS) $(COMPILED_SECP_CAIRO0_HINTS) $(COMPILED_KZG_DA_CAIRO0_HINTS)
cairo_proof_programs: $(COMPILED_PROOF_TESTS) $(COMPILED_MOD_BUILTIN_PROOF_TESTS)
cairo_stwo_exclusive_programs: $(COMPILED_STWO_EXCLUSIVE_TESTS)
cairo_bench_programs: $(COMPILED_BENCHES)
cairo_1_test_contracts: $(CAIRO_1_COMPILED_CASM_CONTRACTS)
cairo_2_test_contracts: $(CAIRO_2_COMPILED_CASM_CONTRACTS)
Expand Down
137 changes: 137 additions & 0 deletions cairo_programs/stwo_exclusive_programs/blake2s_opcode_test.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
%builtins range_check

from starkware.cairo.common.alloc import alloc
from starkware.cairo.common.cairo_blake2s.blake2s import blake2s_inner, INPUT_BLOCK_BYTES, STATE_SIZE_FELTS, INPUT_BLOCK_FELTS

const COUNTER = 128;

// Tests the Blake2s opcode runner using a preexisting implementation within the repo as reference.
// The initial state, a random message of 68 bytes and counter are used as input.
// Both the opcode and the reference implementation are run on the same inputs and then their outputs are compared.
// Before comparing the outputs, it is verified that the opcode runner has written the output to the correct location.
func main{range_check_ptr}() {
alloc_locals;

let (local random_message) = alloc();
assert random_message[0] = 930933030;
assert random_message[1] = 1766240503;
assert random_message[2] = 3660871006;
assert random_message[3] = 388409270;
assert random_message[4] = 1948594622;
assert random_message[5] = 3119396969;
assert random_message[6] = 3924579183;
assert random_message[7] = 2089920034;
assert random_message[8] = 3857888532;
assert random_message[9] = 929304360;
assert random_message[10] = 1810891574;
assert random_message[11] = 860971754;
assert random_message[12] = 1822893775;
assert random_message[13] = 2008495810;
assert random_message[14] = 2958962335;
assert random_message[15] = 2340515744;
assert random_message[16] = 1111307871;

let (local blake2s_ptr_start) = alloc();
let blake2s_ptr = blake2s_ptr_start;
// Set the initial state to IV (IV[0] is modified).
assert blake2s_ptr[0] = 0x6B08E647; // IV[0] ^ 0x01010020 (config: no key, 32 bytes output).
assert blake2s_ptr[1] = 0xBB67AE85;
assert blake2s_ptr[2] = 0x3C6EF372;
assert blake2s_ptr[3] = 0xA54FF53A;
assert blake2s_ptr[4] = 0x510E527F;
assert blake2s_ptr[5] = 0x9B05688C;
assert blake2s_ptr[6] = 0x1F83D9AB;
assert blake2s_ptr[7] = 0x5BE0CD19;
static_assert STATE_SIZE_FELTS == 8;
let blake2s_ptr = blake2s_ptr + STATE_SIZE_FELTS;

let (cairo_output) = blake2s_inner{range_check_ptr=range_check_ptr, blake2s_ptr=blake2s_ptr}(data=random_message, n_bytes=INPUT_BLOCK_BYTES+4, counter=COUNTER);

let (local initial_state) = alloc();
assert initial_state[0] = 0x6B08E647;
assert initial_state[1] = 0xBB67AE85;
assert initial_state[2] = 0x3C6EF372;
assert initial_state[3] = 0xA54FF53A;
assert initial_state[4] = 0x510E527F;
assert initial_state[5] = 0x9B05688C;
assert initial_state[6] = 0x1F83D9AB;
assert initial_state[7] = 0x5BE0CD19;
assert initial_state[8] = COUNTER;

let (local vm_output_start) = alloc();

run_blake2s(
dst=vm_output_start,
op0=initial_state,
op1=random_message,
);

tempvar check_nonempty = vm_output_start[0];
tempvar check_nonempty = vm_output_start[1];
tempvar check_nonempty = vm_output_start[2];
tempvar check_nonempty = vm_output_start[3];
tempvar check_nonempty = vm_output_start[4];
tempvar check_nonempty = vm_output_start[5];
tempvar check_nonempty = vm_output_start[6];
tempvar check_nonempty = vm_output_start[7];
tempvar check_nonempty = vm_output_start[8];

let relevant_output_start = blake2s_ptr_start+INPUT_BLOCK_FELTS+2+STATE_SIZE_FELTS;

assert vm_output_start[0] = relevant_output_start[0];
assert vm_output_start[1] = relevant_output_start[1];
assert vm_output_start[2] = relevant_output_start[2];
assert vm_output_start[3] = relevant_output_start[3];
assert vm_output_start[4] = relevant_output_start[4];
assert vm_output_start[5] = relevant_output_start[5];
assert vm_output_start[6] = relevant_output_start[6];
assert vm_output_start[7] = relevant_output_start[7];
assert vm_output_start[8] = [relevant_output_start-2];

return ();
}

// Forces the runner to execute the Blake2s with the given operands.
// op0 is a pointer to an array of 9 felts, 8 as u32 integers of the state and 1 as a u32 of the counter.
// op1 is a pointer to an array of 16 felts as u32 integers of the messsage.
// dst is a pointer to an array of 9 felts, 8 as u32 integers of the output state and 1 as a u32 of the updated counter.
// The values of said pointers are stored within addresses fp-5, fp-4 and fp-3 respectively.
// An instruction encoding is built from offsets -5, -4, -3 and flags which are all 0 except for
// those denoting uses of fp as the base for operand addresses and flag_opcode_blake (16th flag).
// The instruction is then written to [pc] and the runner is forced to execute Blake2s.
func run_blake2s(
dst: felt*,
op0: felt*,
op1: felt*,
) {
let offset0 = (2**15)-5;
let offset1 = (2**15)-4;
let offset2 = (2**15)-3;
static_assert dst == [fp -5];
static_assert op0 == [fp -4];
static_assert op1 == [fp -3];
let flag_dst_base_fp = 1;
let flag_op0_base_fp = 1;
let flag_op1_imm = 0;
let flag_op1_base_fp = 1;
let flag_op1_base_ap = 0;
let flag_res_add = 0;
let flag_res_mul = 0;
let flag_PC_update_jump = 0;
let flag_PC_update_jump_rel = 0;
let flag_PC_update_jnz = 0;
let flag_ap_update_add = 0;
let flag_ap_update_add_1 = 0;
let flag_opcode_call = 0;
let flag_opcode_ret = 0;
let flag_opcode_assert_eq = 0;
let flag_opcode_blake2s = 1;
let flag_num = flag_dst_base_fp+flag_op0_base_fp*(2**1)+flag_op1_imm*(2**2)+flag_op1_base_fp*(2**3)+flag_opcode_blake2s*(2**15);
let instruction_num = offset0 + offset1*(2**16) + offset2*(2**32) + flag_num*(2**48);
static_assert instruction_num==9226608988349300731;
dw 9226608988349300731;
return ();
}
8 changes: 8 additions & 0 deletions vm/src/tests/cairo_run_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,14 @@ fn blake2s_integration_tests() {
run_program_simple(program_data.as_slice());
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn blake2s_opcode_test() {
let program_data =
include_bytes!("../../../cairo_programs/stwo_exclusive_programs/blake2s_opcode_test.json");
run_program_simple(program_data.as_slice());
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn relocate_segments() {
Expand Down
7 changes: 7 additions & 0 deletions vm/src/types/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub struct Instruction {
pub ap_update: ApUpdate,
pub fp_update: FpUpdate,
pub opcode: Opcode,
pub opcode_extension: OpcodeExtension,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -76,6 +77,12 @@ pub enum Opcode {
Ret,
}

#[derive(Clone, Debug, Copy, PartialEq, Eq)]
pub enum OpcodeExtension {
Stone,
Blake,
}

impl Instruction {
pub fn size(&self) -> usize {
match self.op1_addr {
Expand Down
13 changes: 12 additions & 1 deletion vm/src/vm/context/run_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ mod tests {
use super::*;
use crate::relocatable;
use crate::stdlib::string::ToString;
use crate::types::instruction::{ApUpdate, FpUpdate, Opcode, PcUpdate, Res};
use crate::types::instruction::{ApUpdate, FpUpdate, Opcode, OpcodeExtension, PcUpdate, Res};
use crate::utils::test_utils::mayberelocatable;
use crate::vm::errors::memory_errors::MemoryError;
use crate::Felt252;
Expand All @@ -130,6 +130,7 @@ mod tests {
ap_update: ApUpdate::Regular,
fp_update: FpUpdate::Regular,
opcode: Opcode::NOp,
opcode_extension: OpcodeExtension::Stone,
};

let run_context = RunContext {
Expand Down Expand Up @@ -158,6 +159,7 @@ mod tests {
ap_update: ApUpdate::Regular,
fp_update: FpUpdate::Regular,
opcode: Opcode::NOp,
opcode_extension: OpcodeExtension::Stone,
};

let run_context = RunContext {
Expand Down Expand Up @@ -187,6 +189,7 @@ mod tests {
ap_update: ApUpdate::Regular,
fp_update: FpUpdate::Regular,
opcode: Opcode::NOp,
opcode_extension: OpcodeExtension::Stone,
};

let run_context = RunContext {
Expand Down Expand Up @@ -215,6 +218,7 @@ mod tests {
ap_update: ApUpdate::Regular,
fp_update: FpUpdate::Regular,
opcode: Opcode::NOp,
opcode_extension: OpcodeExtension::Stone,
};

let run_context = RunContext {
Expand Down Expand Up @@ -243,6 +247,7 @@ mod tests {
ap_update: ApUpdate::Regular,
fp_update: FpUpdate::Regular,
opcode: Opcode::NOp,
opcode_extension: OpcodeExtension::Stone,
};

let run_context = RunContext {
Expand Down Expand Up @@ -271,6 +276,7 @@ mod tests {
ap_update: ApUpdate::Regular,
fp_update: FpUpdate::Regular,
opcode: Opcode::NOp,
opcode_extension: OpcodeExtension::Stone,
};

let run_context = RunContext {
Expand Down Expand Up @@ -299,6 +305,7 @@ mod tests {
ap_update: ApUpdate::Regular,
fp_update: FpUpdate::Regular,
opcode: Opcode::NOp,
opcode_extension: OpcodeExtension::Stone,
};

let run_context = RunContext {
Expand Down Expand Up @@ -327,6 +334,7 @@ mod tests {
ap_update: ApUpdate::Regular,
fp_update: FpUpdate::Regular,
opcode: Opcode::NOp,
opcode_extension: OpcodeExtension::Stone,
};

let run_context = RunContext {
Expand Down Expand Up @@ -358,6 +366,7 @@ mod tests {
ap_update: ApUpdate::Regular,
fp_update: FpUpdate::Regular,
opcode: Opcode::NOp,
opcode_extension: OpcodeExtension::Stone,
};

let run_context = RunContext {
Expand Down Expand Up @@ -388,6 +397,7 @@ mod tests {
ap_update: ApUpdate::Regular,
fp_update: FpUpdate::Regular,
opcode: Opcode::NOp,
opcode_extension: OpcodeExtension::Stone,
};

let run_context = RunContext {
Expand Down Expand Up @@ -420,6 +430,7 @@ mod tests {
ap_update: ApUpdate::Regular,
fp_update: FpUpdate::Regular,
opcode: Opcode::NOp,
opcode_extension: OpcodeExtension::Stone,
};

let run_context = RunContext {
Expand Down
Loading

0 comments on commit d25cef1

Please sign in to comment.