1
+ %builtins range_check
2
+
3
+ from starkware.cairo.common.alloc import alloc
4
+ from starkware.cairo.common.cairo_blake2s.blake2s import blake2s_inner, INPUT_BLOCK_BYTES, STATE_SIZE_FELTS, INPUT_BLOCK_FELTS
5
+
6
+ const COUNTER = 128 ;
7
+
8
+ // Tests the Blake2s opcode runner using a preexisting implementation within the repo as reference.
9
+ // The initial state, a random message of 68 bytes and counter are used as input.
10
+ // Both the opcode and the reference implementation are run on the same inputs and then their outputs are compared.
11
+ // Before comparing the outputs, it is verified that the opcode runner has written the output to the correct location.
12
+ func main {range_check_ptr } () {
13
+ alloc_locals ;
14
+
15
+ let (local random_message) = alloc();
16
+ assert random_message[0 ] = 930933030 ;
17
+ assert random_message[1 ] = 1766240503 ;
18
+ assert random_message[2 ] = 3660871006 ;
19
+ assert random_message[3 ] = 388409270 ;
20
+ assert random_message[4 ] = 1948594622 ;
21
+ assert random_message[5 ] = 3119396969 ;
22
+ assert random_message[6 ] = 3924579183 ;
23
+ assert random_message[7 ] = 2089920034 ;
24
+ assert random_message[8 ] = 3857888532 ;
25
+ assert random_message[9 ] = 929304360 ;
26
+ assert random_message[10 ] = 1810891574 ;
27
+ assert random_message[11 ] = 860971754 ;
28
+ assert random_message[12 ] = 1822893775 ;
29
+ assert random_message[13 ] = 2008495810 ;
30
+ assert random_message[14 ] = 2958962335 ;
31
+ assert random_message[15 ] = 2340515744 ;
32
+ assert random_message[16 ] = 1111307871 ;
33
+
34
+ let (local blake2s_ptr_start) = alloc();
35
+ let blake2s_ptr = blake2s_ptr_start;
36
+ // Set the initial state to IV (IV[0] is modified).
37
+ assert blake2s_ptr[0 ] = 0x6B08E647 ; // IV[0] ^ 0x01010020 (config: no key, 32 bytes output).
38
+ assert blake2s_ptr[1 ] = 0xBB67AE85 ;
39
+ assert blake2s_ptr[2 ] = 0x3C6EF372 ;
40
+ assert blake2s_ptr[3 ] = 0xA54FF53A ;
41
+ assert blake2s_ptr[4 ] = 0x510E527F ;
42
+ assert blake2s_ptr[5 ] = 0x9B05688C ;
43
+ assert blake2s_ptr[6 ] = 0x1F83D9AB ;
44
+ assert blake2s_ptr[7 ] = 0x5BE0CD19 ;
45
+ static_assert STATE_SIZE_FELTS == 8 ;
46
+ let blake2s_ptr = blake2s_ptr + STATE_SIZE_FELTS;
47
+
48
+ 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);
49
+
50
+ let relevant_output_start = blake2s_ptr_start+INPUT_BLOCK_FELTS+2 +STATE_SIZE_FELTS;
51
+
52
+ let vm_output_start = run_blake2s(
53
+ dst=COUNTER+INPUT_BLOCK_BYTES,
54
+ op0=blake2s_ptr_start,
55
+ op1=random_message,
56
+ );
57
+
58
+ tempvar check_nonempty = vm_output_start[0 ];
59
+ tempvar check_nonempty = vm_output_start[1 ];
60
+ tempvar check_nonempty = vm_output_start[2 ];
61
+ tempvar check_nonempty = vm_output_start[3 ];
62
+ tempvar check_nonempty = vm_output_start[4 ];
63
+ tempvar check_nonempty = vm_output_start[5 ];
64
+ tempvar check_nonempty = vm_output_start[6 ];
65
+ tempvar check_nonempty = vm_output_start[7 ];
66
+
67
+ assert vm_output_start[0 ] = relevant_output_start[0 ];
68
+ assert vm_output_start[1 ] = relevant_output_start[1 ];
69
+ assert vm_output_start[2 ] = relevant_output_start[2 ];
70
+ assert vm_output_start[3 ] = relevant_output_start[3 ];
71
+ assert vm_output_start[4 ] = relevant_output_start[4 ];
72
+ assert vm_output_start[5 ] = relevant_output_start[5 ];
73
+ assert vm_output_start[6 ] = relevant_output_start[6 ];
74
+ assert vm_output_start[7 ] = relevant_output_start[7 ];
75
+
76
+ return ();
77
+ }
78
+
79
+ // Forces the runner to execute the Blake2s with the given operands.
80
+ // op0 is a pointer to an array of 8 felts as u32 integers of the state.
81
+ // op1 is a pointer to an array of 16 felts as u32 integers of the messsage.
82
+ // dst is a felt representing a u32 of the counter.
83
+ // ap contains a pointer to an array of 8 felts as u32 integers of the output state.
84
+ // Those values are stored within addresses fp-5, fp-4 and fp-3 respectively.
85
+ // An instruction encoding is built from offsets -5, -4, -3 and flags which are all 0 except for
86
+ // those denoting uses of fp as the base for operand addresses and flag_opcode_blake (16th flag).
87
+ // The instruction is then written to [pc] and the runner is forced to execute Blake2s.
88
+ func run_blake2s (
89
+ dst: felt ,
90
+ op0: felt *,
91
+ op1: felt *,
92
+ ) -> felt * {
93
+ alloc_locals ;
94
+ let offset0 = (2 **15 )-5 ;
95
+ let offset1 = (2 **15 )-4 ;
96
+ let offset2 = (2 **15 )-3 ;
97
+
98
+ static_assert dst == [fp -5 ];
99
+ static_assert op0 == [fp -4 ];
100
+ static_assert op1 == [fp -3 ];
101
+
102
+ let flag_dst_base_fp = 1 ;
103
+ let flag_op0_base_fp = 1 ;
104
+ let flag_op1_imm = 0 ;
105
+ let flag_op1_base_fp = 1 ;
106
+ let flag_op1_base_ap = 0 ;
107
+ let flag_res_add = 0 ;
108
+ let flag_res_mul = 0 ;
109
+ let flag_PC_update_jump = 0 ;
110
+ let flag_PC_update_jump_rel = 0 ;
111
+ let flag_PC_update_jnz = 0 ;
112
+ let flag_ap_update_add = 0 ;
113
+ let flag_ap_update_add_1 = 0 ;
114
+ let flag_opcode_call = 0 ;
115
+ let flag_opcode_ret = 0 ;
116
+ let flag_opcode_assert_eq = 0 ;
117
+ let flag_opcode_blake2s = 1 ;
118
+
119
+ 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 );
120
+ let instruction_num = offset0 + offset1*(2 **16 ) + offset2*(2 **32 ) + flag_num*(2 **48 );
121
+ static_assert instruction_num==9226608988349300731 ;
122
+ let (local vm_output_start) = alloc();
123
+ assert [ap ] = cast (vm_output_start, felt );
124
+ dw 9226608988349300731 ;
125
+
126
+ let vm_output_start = cast ([ap ], felt *);
127
+ return vm_output_start;
128
+ }
0 commit comments