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, 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 and keccak256:
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 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 296 : FD_PARAM_UNUSED ulong r5 ) {
34 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1897 */
35 296 : fd_vm_t * vm = (fd_vm_t *)_vm;
36 :
37 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1911-L1920 */
38 296 : if( FD_UNLIKELY( FD_VM_SHA256_MAX_SLICES < vals_len ) ) {
39 : /* Max msg_sz = 61 - 8 + 6 + 20 + 20 = 99 < 127 => we can use printf */
40 1 : fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
41 1 : "%s Hashing %lu sequences in one syscall is over the limit %lu",
42 1 : "Sha256", vals_len, FD_VM_SHA256_MAX_SLICES );
43 1 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_TOO_MANY_SLICES );
44 1 : return FD_VM_SYSCALL_ERR_TOO_MANY_SLICES; /* SyscallError::TooManySlices */
45 1 : }
46 :
47 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1922 */
48 589 : FD_VM_CU_UPDATE( vm, FD_VM_SHA256_BASE_COST );
49 279 : uchar * hash_result = FD_VM_HADDR_QUERY_U8_SLICE( vm, result_addr, 32UL );
50 :
51 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1930 */
52 279 : fd_sha256_t sha[1];
53 279 : fd_sha256_init( sha );
54 :
55 279 : if( vals_len > 0 ) {
56 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1932-L1937 */
57 788 : 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) );
58 3713 : for( ulong i=0UL; i<vals_len; i++ ) {
59 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1939-L1944 */
60 3456 : ulong val_len = input_vec_haddr[i].len;
61 6910 : void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, val_len );
62 :
63 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1945-L1951 */
64 3454 : ulong cost = fd_ulong_max( FD_VM_MEM_OP_BASE_COST,
65 6910 : fd_ulong_sat_mul( FD_VM_SHA256_BYTE_COST, (val_len / 2) ) );
66 :
67 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1952 */
68 6910 : FD_VM_CU_UPDATE( vm, cost );
69 :
70 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1953 */
71 0 : fd_sha256_append( sha, bytes, val_len );
72 3451 : }
73 788 : }
74 :
75 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1956-L1957 */
76 272 : fd_sha256_fini( sha, hash_result );
77 272 : vm->reg[0] = 0UL;
78 272 : return FD_VM_SUCCESS;
79 279 : }
80 :
81 : int
82 : fd_vm_syscall_sol_keccak256( /**/ void * _vm,
83 : /**/ ulong vals_addr,
84 : /**/ ulong vals_len,
85 : /**/ ulong result_addr,
86 : FD_PARAM_UNUSED ulong r4,
87 250 : FD_PARAM_UNUSED ulong r5 ) {
88 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1897 */
89 250 : fd_vm_t * vm = (fd_vm_t *)_vm;
90 :
91 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1911-L1920 */
92 250 : if( FD_UNLIKELY( FD_VM_SHA256_MAX_SLICES < vals_len ) ) {
93 : /* Max msg_sz = 61 - 8 + 9 + 20 + 20 = 102 < 127 => we can use printf */
94 1 : fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
95 1 : "%s Hashing %lu sequences in one syscall is over the limit %lu",
96 1 : "Keccak256", vals_len, FD_VM_SHA256_MAX_SLICES );
97 1 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_TOO_MANY_SLICES );
98 1 : return FD_VM_SYSCALL_ERR_TOO_MANY_SLICES; /* SyscallError::TooManySlices */
99 1 : }
100 :
101 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1922 */
102 497 : FD_VM_CU_UPDATE( vm, FD_VM_SHA256_BASE_COST );
103 236 : uchar * hash_result = FD_VM_HADDR_QUERY_U8_SLICE( vm, result_addr, 32UL );
104 :
105 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1930 */
106 236 : fd_keccak256_t sha[1];
107 236 : fd_keccak256_init( sha );
108 :
109 236 : if( vals_len > 0 ) {
110 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1932-L1937 */
111 680 : 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) );
112 3390 : for( ulong i=0UL; i<vals_len; i++ ) {
113 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1939-L1944 */
114 3169 : ulong val_len = input_vec_haddr[i].len;
115 6336 : void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, val_len );
116 :
117 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1945-L1951 */
118 3167 : ulong cost = fd_ulong_max( FD_VM_MEM_OP_BASE_COST,
119 6336 : fd_ulong_sat_mul( FD_VM_SHA256_BYTE_COST, (val_len / 2) ) );
120 :
121 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1952 */
122 6336 : FD_VM_CU_UPDATE( vm, cost );
123 :
124 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1953 */
125 0 : fd_keccak256_append( sha, bytes, val_len );
126 3164 : }
127 680 : }
128 :
129 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1956-L1957 */
130 229 : fd_keccak256_fini( sha, hash_result );
131 229 : vm->reg[0] = 0UL;
132 229 : return FD_VM_SUCCESS;
133 236 : }
134 :
135 : int
136 : fd_vm_syscall_sol_sha512( /**/ void * _vm,
137 : /**/ ulong vals_addr,
138 : /**/ ulong vals_len,
139 : /**/ ulong result_addr,
140 : FD_PARAM_UNUSED ulong r4,
141 0 : FD_PARAM_UNUSED ulong r5 ) {
142 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
143 :
144 0 : if( FD_UNLIKELY( FD_VM_SHA256_MAX_SLICES < vals_len ) ) {
145 0 : fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
146 0 : "%s Hashing %lu sequences in one syscall is over the limit %lu",
147 0 : "Sha512", vals_len, FD_VM_SHA256_MAX_SLICES );
148 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_TOO_MANY_SLICES );
149 0 : return FD_VM_SYSCALL_ERR_TOO_MANY_SLICES;
150 0 : }
151 :
152 0 : FD_VM_CU_UPDATE( vm, FD_VM_SHA256_BASE_COST );
153 0 : uchar * hash_result = FD_VM_HADDR_QUERY_U8_SLICE( vm, result_addr, FD_SHA512_HASH_SZ );
154 :
155 0 : fd_sha512_t sha[1];
156 0 : fd_sha512_init( sha );
157 :
158 0 : if( vals_len > 0 ) {
159 0 : 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) );
160 0 : for( ulong i=0UL; i<vals_len; i++ ) {
161 0 : ulong val_len = input_vec_haddr[i].len;
162 0 : void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, val_len );
163 :
164 0 : ulong cost = fd_ulong_max( FD_VM_MEM_OP_BASE_COST,
165 0 : fd_ulong_sat_mul( FD_VM_SHA256_BYTE_COST, (val_len / 2) ) );
166 :
167 0 : FD_VM_CU_UPDATE( vm, cost );
168 :
169 0 : fd_sha512_append( sha, bytes, val_len );
170 0 : }
171 0 : }
172 :
173 0 : fd_sha512_fini( sha, hash_result );
174 0 : vm->reg[0] = 0UL;
175 0 : return FD_VM_SUCCESS;
176 0 : }
|