Line data Source code
1 : #include "fd_vm_syscall.h"
2 :
3 : #include "../../../ballet/keccak256/fd_keccak256.h"
4 : #include "../../../ballet/sha512/fd_sha512.h"
5 :
6 : /* Syscalls for sha256, keccak256, blake3, sha512. */
7 :
8 : /* Agave has a single generic hash syscall:
9 : https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1895-L1959
10 : With trait impl for sha256, keccak256 and blake3:
11 : https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L130-L225
12 :
13 : Notes:
14 : 1. Max slices, base cost and byte cost are the same for all 3 hash functions:
15 : - https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L189-L197
16 : - https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L216-L224
17 : 2. Poseidon doesn't follow this generic hash implementation (so we left it in fd_vm_syscall_crypto.c):
18 : - https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1678
19 :
20 : Implementation notes.
21 : Because of the notes above, we implemented fd_vm_syscall_sol_sha256() following the generic hash
22 : syscall step by step.
23 : The other implementations are just a copy & paste, replacing the hash function.
24 : Resisted the temptation to do a macro, because it would complicate future changes, for example if
25 : we were to modify CU costs. */
26 :
27 : int
28 : fd_vm_syscall_sol_sha256( /**/ void * _vm,
29 : /**/ ulong vals_addr,
30 : /**/ ulong vals_len,
31 : /**/ ulong result_addr,
32 : FD_PARAM_UNUSED ulong r4,
33 : FD_PARAM_UNUSED ulong r5,
34 15 : /**/ ulong * _ret ) {
35 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1897 */
36 15 : fd_vm_t * vm = (fd_vm_t *)_vm;
37 :
38 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1911-L1920 */
39 15 : if( FD_UNLIKELY( FD_VM_SHA256_MAX_SLICES < vals_len ) ) {
40 : /* Max msg_sz = 61 - 8 + 6 + 20 + 20 = 99 < 127 => we can use printf */
41 3 : fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
42 3 : "%s Hashing %lu sequences in one syscall is over the limit %lu",
43 3 : "Sha256", vals_len, FD_VM_SHA256_MAX_SLICES );
44 3 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_TOO_MANY_SLICES );
45 3 : return FD_VM_SYSCALL_ERR_TOO_MANY_SLICES; /* SyscallError::TooManySlices */
46 3 : }
47 :
48 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1922 */
49 24 : FD_VM_CU_UPDATE( vm, FD_VM_SHA256_BASE_COST );
50 24 : uchar * hash_result = FD_VM_HADDR_QUERY_U8_SLICE( vm, result_addr, 32UL );
51 :
52 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1930 */
53 12 : fd_sha256_t sha[1];
54 12 : fd_sha256_init( sha );
55 :
56 12 : if( vals_len > 0 ) {
57 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1932-L1937 */
58 27 : fd_vm_vec_t const * input_vec_haddr = (fd_vm_vec_t const *)FD_VM_MEM_HADDR_LD( vm, vals_addr, FD_VM_VEC_ALIGN, vals_len*sizeof(fd_vm_vec_t) );
59 27 : for( ulong i=0UL; i<vals_len; i++ ) {
60 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1939-L1944 */
61 12 : ulong val_len = input_vec_haddr[i].len;
62 24 : void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, val_len );
63 :
64 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1945-L1951 */
65 24 : ulong cost = fd_ulong_max( FD_VM_MEM_OP_BASE_COST,
66 24 : fd_ulong_sat_mul( FD_VM_SHA256_BYTE_COST, (val_len / 2) ) );
67 :
68 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1952 */
69 24 : FD_VM_CU_UPDATE( vm, cost );
70 :
71 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1953 */
72 12 : fd_sha256_append( sha, bytes, val_len );
73 12 : }
74 27 : }
75 :
76 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1956-L1957 */
77 12 : fd_sha256_fini( sha, hash_result );
78 12 : *_ret = 0UL;
79 12 : return FD_VM_SUCCESS;
80 12 : }
81 :
82 : int
83 : fd_vm_syscall_sol_blake3( /**/ void * _vm,
84 : /**/ ulong vals_addr,
85 : /**/ ulong vals_len,
86 : /**/ ulong result_addr,
87 : FD_PARAM_UNUSED ulong r4,
88 : FD_PARAM_UNUSED ulong r5,
89 15 : /**/ ulong * _ret ) {
90 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1897 */
91 15 : fd_vm_t * vm = (fd_vm_t *)_vm;
92 :
93 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1911-L1920 */
94 15 : if( FD_UNLIKELY( FD_VM_SHA256_MAX_SLICES < vals_len ) ) {
95 : /* Max msg_sz = 61 - 8 + 6 + 20 + 20 = 99 < 127 => we can use printf */
96 3 : fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
97 3 : "%s Hashing %lu sequences in one syscall is over the limit %lu",
98 3 : "Blake3", vals_len, FD_VM_SHA256_MAX_SLICES );
99 3 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_TOO_MANY_SLICES );
100 3 : return FD_VM_SYSCALL_ERR_TOO_MANY_SLICES; /* SyscallError::TooManySlices */
101 3 : }
102 :
103 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1922 */
104 24 : FD_VM_CU_UPDATE( vm, FD_VM_SHA256_BASE_COST );
105 24 : uchar * hash_result = FD_VM_HADDR_QUERY_U8_SLICE( vm, result_addr, 32UL );
106 :
107 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1930 */
108 12 : fd_blake3_t sha[1];
109 12 : fd_blake3_init( sha );
110 :
111 12 : if( vals_len > 0 ) {
112 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1932-L1937 */
113 27 : fd_vm_vec_t const * input_vec_haddr = (fd_vm_vec_t const *)FD_VM_MEM_HADDR_LD( vm, vals_addr, FD_VM_VEC_ALIGN, vals_len*sizeof(fd_vm_vec_t) );
114 27 : for( ulong i=0UL; i<vals_len; i++ ) {
115 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1939-L1944 */
116 12 : ulong val_len = input_vec_haddr[i].len;
117 24 : void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, val_len );
118 :
119 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1945-L1951 */
120 24 : ulong cost = fd_ulong_max( FD_VM_MEM_OP_BASE_COST,
121 24 : fd_ulong_sat_mul( FD_VM_SHA256_BYTE_COST, (val_len / 2) ) );
122 :
123 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1952 */
124 24 : FD_VM_CU_UPDATE( vm, cost );
125 :
126 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1953 */
127 12 : fd_blake3_append( sha, bytes, val_len );
128 12 : }
129 27 : }
130 :
131 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1956-L1957 */
132 12 : fd_blake3_fini( sha, hash_result );
133 12 : *_ret = 0UL;
134 12 : return FD_VM_SUCCESS;
135 12 : }
136 :
137 : int
138 : fd_vm_syscall_sol_keccak256( /**/ void * _vm,
139 : /**/ ulong vals_addr,
140 : /**/ ulong vals_len,
141 : /**/ ulong result_addr,
142 : FD_PARAM_UNUSED ulong r4,
143 : FD_PARAM_UNUSED ulong r5,
144 15 : /**/ ulong * _ret ) {
145 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1897 */
146 15 : fd_vm_t * vm = (fd_vm_t *)_vm;
147 :
148 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1911-L1920 */
149 15 : if( FD_UNLIKELY( FD_VM_SHA256_MAX_SLICES < vals_len ) ) {
150 : /* Max msg_sz = 61 - 8 + 9 + 20 + 20 = 102 < 127 => we can use printf */
151 3 : fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
152 3 : "%s Hashing %lu sequences in one syscall is over the limit %lu",
153 3 : "Keccak256", vals_len, FD_VM_SHA256_MAX_SLICES );
154 3 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_TOO_MANY_SLICES );
155 3 : return FD_VM_SYSCALL_ERR_TOO_MANY_SLICES; /* SyscallError::TooManySlices */
156 3 : }
157 :
158 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1922 */
159 24 : FD_VM_CU_UPDATE( vm, FD_VM_SHA256_BASE_COST );
160 24 : uchar * hash_result = FD_VM_HADDR_QUERY_U8_SLICE( vm, result_addr, 32UL );
161 :
162 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1930 */
163 12 : fd_keccak256_t sha[1];
164 12 : fd_keccak256_init( sha );
165 :
166 12 : if( vals_len > 0 ) {
167 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1932-L1937 */
168 27 : fd_vm_vec_t const * input_vec_haddr = (fd_vm_vec_t const *)FD_VM_MEM_HADDR_LD( vm, vals_addr, FD_VM_VEC_ALIGN, vals_len*sizeof(fd_vm_vec_t) );
169 27 : for( ulong i=0UL; i<vals_len; i++ ) {
170 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1939-L1944 */
171 12 : ulong val_len = input_vec_haddr[i].len;
172 24 : void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, val_len );
173 :
174 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1945-L1951 */
175 24 : ulong cost = fd_ulong_max( FD_VM_MEM_OP_BASE_COST,
176 24 : fd_ulong_sat_mul( FD_VM_SHA256_BYTE_COST, (val_len / 2) ) );
177 :
178 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1952 */
179 24 : FD_VM_CU_UPDATE( vm, cost );
180 :
181 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1953 */
182 12 : fd_keccak256_append( sha, bytes, val_len );
183 12 : }
184 27 : }
185 :
186 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1956-L1957 */
187 12 : fd_keccak256_fini( sha, hash_result );
188 12 : *_ret = 0UL;
189 12 : return FD_VM_SUCCESS;
190 12 : }
191 :
192 : int
193 : fd_vm_syscall_sol_sha512( /**/ void * _vm,
194 : /**/ ulong vals_addr,
195 : /**/ ulong vals_len,
196 : /**/ ulong result_addr,
197 : FD_PARAM_UNUSED ulong r4,
198 : FD_PARAM_UNUSED ulong r5,
199 15 : /**/ ulong * _ret ) {
200 15 : fd_vm_t * vm = (fd_vm_t *)_vm;
201 :
202 15 : if( FD_UNLIKELY( FD_VM_SHA256_MAX_SLICES < vals_len ) ) {
203 3 : fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
204 3 : "%s Hashing %lu sequences in one syscall is over the limit %lu",
205 3 : "Sha512", vals_len, FD_VM_SHA256_MAX_SLICES );
206 3 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_TOO_MANY_SLICES );
207 3 : return FD_VM_SYSCALL_ERR_TOO_MANY_SLICES;
208 3 : }
209 :
210 24 : FD_VM_CU_UPDATE( vm, FD_VM_SHA256_BASE_COST );
211 24 : uchar * hash_result = FD_VM_HADDR_QUERY_U8_SLICE( vm, result_addr, FD_SHA512_HASH_SZ );
212 :
213 12 : fd_sha512_t sha[1];
214 12 : fd_sha512_init( sha );
215 :
216 12 : if( vals_len > 0 ) {
217 27 : fd_vm_vec_t const * input_vec_haddr = (fd_vm_vec_t const *)FD_VM_MEM_HADDR_LD( vm, vals_addr, FD_VM_VEC_ALIGN, vals_len*sizeof(fd_vm_vec_t) );
218 27 : for( ulong i=0UL; i<vals_len; i++ ) {
219 12 : ulong val_len = input_vec_haddr[i].len;
220 24 : void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, val_len );
221 :
222 24 : ulong cost = fd_ulong_max( FD_VM_MEM_OP_BASE_COST,
223 24 : fd_ulong_sat_mul( FD_VM_SHA256_BYTE_COST, (val_len / 2) ) );
224 :
225 24 : FD_VM_CU_UPDATE( vm, cost );
226 :
227 12 : fd_sha512_append( sha, bytes, val_len );
228 12 : }
229 27 : }
230 :
231 12 : fd_sha512_fini( sha, hash_result );
232 12 : *_ret = 0UL;
233 12 : return FD_VM_SUCCESS;
234 12 : }
|