Line data Source code
1 : #include "fd_vm_syscall.h"
2 : #include "../../runtime/fd_bank.h"
3 : #include "../../../ballet/ed25519/fd_curve25519.h"
4 : #include "../../../ballet/ed25519/fd_ristretto255.h"
5 : #include "../../../ballet/bls/fd_bls12_381.h"
6 :
7 : int
8 : fd_vm_syscall_sol_curve_validate_point( /**/ void * _vm,
9 : /**/ ulong curve_id,
10 : /**/ ulong point_addr,
11 : FD_PARAM_UNUSED ulong r3,
12 : FD_PARAM_UNUSED ulong r4,
13 : FD_PARAM_UNUSED ulong r5,
14 91 : /**/ ulong * _ret ) {
15 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L871 */
16 91 : fd_vm_t * vm = (fd_vm_t *)_vm;
17 91 : ulong ret = 1UL; /* by default return Ok(1) == error */
18 :
19 : /* BLS12-381 syscalls are under feature gate enable_bls12_381_syscall.
20 : To clean up the feature gate after activation, just remove this block
21 : (the rest of the function will behave correctly). */
22 91 : {
23 91 : if( FD_UNLIKELY(
24 91 : !FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, enable_bls12_381_syscall )
25 91 : && ( curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE
26 91 : || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE
27 91 : || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE
28 91 : || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE )
29 91 : ) ) {
30 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
31 0 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
32 0 : }
33 91 : }
34 :
35 91 : uchar const * point = NULL;
36 91 : switch( curve_id ) {
37 :
38 44 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS:
39 :
40 44 : FD_VM_CU_UPDATE( vm, FD_VM_CURVE_EDWARDS_VALIDATE_POINT_COST );
41 43 : point = FD_VM_MEM_HADDR_LD( vm, point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
42 0 : ret = (ulong)!fd_ed25519_point_validate( point ); /* 0 if valid point, 1 if not */
43 42 : break;
44 :
45 45 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO:
46 :
47 45 : FD_VM_CU_UPDATE( vm, FD_VM_CURVE_RISTRETTO_VALIDATE_POINT_COST );
48 44 : point = FD_VM_MEM_HADDR_LD( vm, point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
49 0 : ret = (ulong)!fd_ristretto255_point_validate( point ); /* 0 if valid point, 1 if not */
50 43 : break;
51 :
52 0 : #if FD_HAS_BLST
53 0 : case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE:
54 0 : case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE: {
55 :
56 0 : int big_endian = ( curve_id & 0x80 ) ? 1 : 0;
57 0 : FD_VM_CU_UPDATE( vm, FD_VM_CURVE_BLS12_381_G1_VALIDATE_COST );
58 0 : point = FD_VM_MEM_HADDR_LD( vm, point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
59 0 : ret = (ulong)!fd_bls12_381_g1_validate_syscall( point, big_endian ); /* 0 if valid point, 1 if not */
60 0 : } break;
61 :
62 0 : case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE:
63 0 : case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE: {
64 :
65 0 : int big_endian = ( curve_id & 0x80 ) ? 1 : 0;
66 0 : FD_VM_CU_UPDATE( vm, FD_VM_CURVE_BLS12_381_G2_VALIDATE_COST );
67 0 : point = FD_VM_MEM_HADDR_LD( vm, point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
68 0 : ret = (ulong)!fd_bls12_381_g2_validate_syscall( point, big_endian ); /* 0 if valid point, 1 if not */
69 0 : } break;
70 0 : #endif
71 :
72 2 : default:
73 : /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L919-L928 */
74 2 : if( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, abort_on_invalid_curve ) ) {
75 1 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
76 1 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
77 1 : }
78 91 : }
79 :
80 86 : *_ret = ret;
81 86 : return FD_VM_SUCCESS;
82 91 : }
83 :
84 : int
85 : fd_vm_syscall_sol_curve_group_op( void * _vm,
86 : ulong curve_id,
87 : ulong group_op,
88 : ulong left_input_addr,
89 : ulong right_input_addr,
90 : ulong result_point_addr,
91 169 : ulong * _ret ) {
92 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L928 */
93 169 : fd_vm_t * vm = (fd_vm_t *)_vm;
94 169 : ulong ret = 1UL; /* by default return Ok(1) == error */
95 :
96 : /* BLS12-381 syscalls are under feature gate enable_bls12_381_syscall.
97 : To clean up the feature gate after activation, just remove this block
98 : (the rest of the function will behave correctly). */
99 169 : {
100 169 : if( FD_UNLIKELY(
101 169 : !FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, enable_bls12_381_syscall )
102 169 : && ( curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE
103 169 : || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE
104 169 : || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE
105 169 : || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE )
106 169 : ) ) {
107 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
108 0 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
109 0 : }
110 169 : }
111 :
112 : /* Note: we don't strictly follow the Rust implementation, but instead combine
113 : common code across switch cases. Similar to fd_vm_syscall_sol_alt_bn128_group_op. */
114 :
115 : /* MATCH_ID_OP allows us to unify 2 switch/case into 1.
116 : For better readability, we also temp define EDWARDS, RISTRETTO.
117 :
118 : The first time we check that both curve_id and group_op are valid
119 : with 2 nested switch/case. Using MATCH_ID_OP leads to undesidered
120 : edge cases. The second time, when we know that curve_id and group_op
121 : are correct, then we can use MATCH_ID_OP and a single switch/case. */
122 290 : #define MATCH_ID_OP(crv_id,grp_op) ((crv_id << 4) | grp_op)
123 169 : #define EDWARDS FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS
124 169 : #define RISTRETTO FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO
125 169 : #define BLS_G1_BE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE
126 169 : #define BLS_G1_LE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE
127 169 : #define BLS_G2_BE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE
128 169 : #define BLS_G2_LE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE
129 :
130 169 : ulong cost = 0UL;
131 169 : ulong inputL_sz = 32UL;
132 169 : ulong inputR_sz = 32UL;
133 169 : switch( curve_id ) {
134 :
135 83 : case EDWARDS:
136 83 : switch( group_op ) {
137 :
138 19 : case FD_VM_SYSCALL_SOL_CURVE_ADD:
139 19 : cost = FD_VM_CURVE_EDWARDS_ADD_COST;
140 19 : break;
141 :
142 18 : case FD_VM_SYSCALL_SOL_CURVE_SUB:
143 18 : cost = FD_VM_CURVE_EDWARDS_SUBTRACT_COST;
144 18 : break;
145 :
146 44 : case FD_VM_SYSCALL_SOL_CURVE_MUL:
147 44 : cost = FD_VM_CURVE_EDWARDS_MULTIPLY_COST;
148 44 : break;
149 :
150 2 : default:
151 2 : goto invalid_error;
152 83 : }
153 81 : break;
154 :
155 84 : case RISTRETTO:
156 84 : switch( group_op ) {
157 :
158 21 : case FD_VM_SYSCALL_SOL_CURVE_ADD:
159 21 : cost = FD_VM_CURVE_RISTRETTO_ADD_COST;
160 21 : break;
161 :
162 23 : case FD_VM_SYSCALL_SOL_CURVE_SUB:
163 23 : cost = FD_VM_CURVE_RISTRETTO_SUBTRACT_COST;
164 23 : break;
165 :
166 38 : case FD_VM_SYSCALL_SOL_CURVE_MUL:
167 38 : cost = FD_VM_CURVE_RISTRETTO_MULTIPLY_COST;
168 38 : break;
169 :
170 2 : default:
171 2 : goto invalid_error;
172 84 : }
173 82 : break;
174 :
175 82 : #if FD_HAS_BLST
176 : /* BLS12-381 G1 */
177 82 : case BLS_G1_BE:
178 0 : case BLS_G1_LE:
179 0 : switch( group_op ) {
180 :
181 0 : case FD_VM_SYSCALL_SOL_CURVE_ADD:
182 0 : cost = FD_VM_CURVE_BLS12_381_G1_ADD_COST;
183 0 : inputL_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ;
184 0 : inputR_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ;
185 0 : break;
186 :
187 0 : case FD_VM_SYSCALL_SOL_CURVE_SUB:
188 0 : cost = FD_VM_CURVE_BLS12_381_G1_SUB_COST;
189 0 : inputL_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ;
190 0 : inputR_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ;
191 0 : break;
192 :
193 0 : case FD_VM_SYSCALL_SOL_CURVE_MUL:
194 0 : cost = FD_VM_CURVE_BLS12_381_G1_MUL_COST;
195 : /* inputL_sz = 32UL // scalar */
196 0 : inputR_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ;
197 0 : break;
198 :
199 0 : default:
200 0 : goto invalid_error;
201 0 : }
202 0 : break;
203 :
204 : /* BLS12-381 G2 */
205 0 : case BLS_G2_BE:
206 0 : case BLS_G2_LE:
207 0 : switch( group_op ) {
208 :
209 0 : case FD_VM_SYSCALL_SOL_CURVE_ADD:
210 0 : cost = FD_VM_CURVE_BLS12_381_G2_ADD_COST;
211 0 : inputL_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ;
212 0 : inputR_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ;
213 0 : break;
214 :
215 0 : case FD_VM_SYSCALL_SOL_CURVE_SUB:
216 0 : cost = FD_VM_CURVE_BLS12_381_G2_SUB_COST;
217 0 : inputL_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ;
218 0 : inputR_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ;
219 0 : break;
220 :
221 0 : case FD_VM_SYSCALL_SOL_CURVE_MUL:
222 0 : cost = FD_VM_CURVE_BLS12_381_G2_MUL_COST;
223 : /* inputL_sz = 32UL // scalar */
224 0 : inputR_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ;
225 0 : break;
226 :
227 0 : default:
228 0 : goto invalid_error;
229 0 : }
230 0 : break;
231 0 : #endif
232 :
233 2 : default:
234 2 : goto invalid_error;
235 169 : }
236 :
237 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L944-L947 */
238 320 : FD_VM_CU_UPDATE( vm, cost );
239 :
240 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L949-L958 */
241 :
242 : /* Note: left_input_addr is a point for add, sub, BUT it's a scalar for mul. */
243 459 : uchar const * inputL = FD_VM_MEM_HADDR_LD( vm, left_input_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, inputL_sz );
244 441 : uchar const * inputR = FD_VM_MEM_HADDR_LD( vm, right_input_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, inputR_sz );
245 :
246 0 : #if FD_HAS_BLST
247 145 : int big_endian = ( curve_id & 0x80 ) ? 1 : 0;
248 441 : #endif
249 :
250 441 : switch( MATCH_ID_OP( curve_id, group_op ) ) {
251 :
252 16 : case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
253 16 : fd_ed25519_point_t p0[1], p1[1], r[1];
254 16 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p0, inputL ) ) ) {
255 1 : goto soft_error;
256 1 : }
257 15 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p1, inputR ) ) ) {
258 1 : goto soft_error;
259 1 : }
260 :
261 14 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
262 13 : fd_ed25519_point_add( r, p0, p1 );
263 13 : fd_ed25519_point_tobytes( result, r );
264 13 : ret = 0UL;
265 13 : break;
266 14 : }
267 :
268 15 : case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_SUB ): {
269 15 : fd_ed25519_point_t p0[1], p1[1], r[1];
270 15 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p0, inputL ) ) ) {
271 1 : goto soft_error;
272 1 : }
273 14 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p1, inputR ) ) ) {
274 1 : goto soft_error;
275 1 : }
276 :
277 13 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
278 12 : fd_ed25519_point_sub( r, p0, p1 );
279 12 : fd_ed25519_point_tobytes( result, r );
280 12 : ret = 0UL;
281 12 : break;
282 13 : }
283 :
284 41 : case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_MUL ): {
285 41 : fd_ed25519_point_t p[1], r[1];
286 41 : if( FD_UNLIKELY( !fd_curve25519_scalar_validate( inputL ) ) ) {
287 4 : goto soft_error;
288 4 : }
289 37 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p, inputR ) ) ) {
290 2 : goto soft_error;
291 2 : }
292 :
293 35 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
294 34 : fd_ed25519_scalar_mul( r, inputL, p );
295 34 : fd_ed25519_point_tobytes( result, r );
296 34 : ret = 0UL;
297 34 : break;
298 35 : }
299 :
300 18 : case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
301 18 : fd_ristretto255_point_t p0[1], p1[1], r[1];
302 18 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p0, inputL ) ) ) {
303 1 : goto soft_error;
304 1 : }
305 17 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p1, inputR ) ) ) {
306 1 : goto soft_error;
307 1 : }
308 :
309 16 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
310 15 : fd_ristretto255_point_add( r, p0, p1 );
311 15 : fd_ristretto255_point_tobytes( result, r );
312 15 : ret = 0UL;
313 15 : break;
314 16 : }
315 :
316 20 : case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_SUB ): {
317 20 : fd_ristretto255_point_t p0[1], p1[1], r[1];
318 20 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p0, inputL ) ) ) {
319 1 : goto soft_error;
320 1 : }
321 19 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p1, inputR ) ) ) {
322 1 : goto soft_error;
323 1 : }
324 :
325 18 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
326 17 : fd_ristretto255_point_sub( r, p0, p1 );
327 17 : fd_ristretto255_point_tobytes( result, r );
328 17 : ret = 0UL;
329 17 : break;
330 18 : }
331 :
332 35 : case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_MUL ): {
333 35 : fd_ristretto255_point_t p[1], r[1];
334 35 : if( FD_UNLIKELY( !fd_curve25519_scalar_validate( inputL ) ) ) {
335 5 : goto soft_error;
336 5 : }
337 30 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p, inputR ) ) ) {
338 10 : goto soft_error;
339 10 : }
340 :
341 20 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
342 19 : fd_ristretto255_scalar_mul( r, inputL, p );
343 19 : fd_ristretto255_point_tobytes( result, r );
344 19 : ret = 0UL;
345 19 : break;
346 20 : }
347 :
348 0 : #if FD_HAS_BLST
349 : /* BLS12-381 G1 */
350 :
351 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1453 */
352 0 : case MATCH_ID_OP( BLS_G1_BE, FD_VM_SYSCALL_SOL_CURVE_ADD ):
353 0 : case MATCH_ID_OP( BLS_G1_LE, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
354 0 : uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ ];
355 : /* Compute add */
356 0 : if( FD_LIKELY( fd_bls12_381_g1_add_syscall( _result, inputL, inputR, big_endian )==0 ) ) {
357 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1474 */
358 0 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
359 0 : memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
360 0 : ret = 0UL; /* success */
361 0 : }
362 0 : break;
363 0 : }
364 :
365 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1485 */
366 0 : case MATCH_ID_OP( BLS_G1_BE, FD_VM_SYSCALL_SOL_CURVE_SUB ):
367 0 : case MATCH_ID_OP( BLS_G1_LE, FD_VM_SYSCALL_SOL_CURVE_SUB ): {
368 0 : uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ ];
369 : /* Compute sub */
370 0 : if( FD_LIKELY( fd_bls12_381_g1_sub_syscall( _result, inputL, inputR, big_endian )==0 ) ) {
371 0 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
372 0 : memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
373 0 : ret = 0UL; /* success */
374 0 : }
375 0 : break;
376 0 : }
377 :
378 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1519 */
379 0 : case MATCH_ID_OP( BLS_G1_BE, FD_VM_SYSCALL_SOL_CURVE_MUL ):
380 0 : case MATCH_ID_OP( BLS_G1_LE, FD_VM_SYSCALL_SOL_CURVE_MUL ): {
381 0 : uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ ];
382 : /* Compute mul */
383 0 : if( FD_LIKELY( fd_bls12_381_g1_mul_syscall( _result, inputL, inputR, big_endian )==0 ) ) {
384 0 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
385 0 : memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
386 0 : ret = 0UL; /* success */
387 0 : }
388 0 : break;
389 0 : }
390 :
391 : /* BLS12-381 G2 */
392 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1566 */
393 0 : case MATCH_ID_OP( BLS_G2_BE, FD_VM_SYSCALL_SOL_CURVE_ADD ):
394 0 : case MATCH_ID_OP( BLS_G2_LE, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
395 0 : uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ ];
396 : /* Compute add */
397 0 : if( FD_LIKELY( fd_bls12_381_g2_add_syscall( _result, inputL, inputR, big_endian )==0 ) ) {
398 0 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
399 0 : memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
400 0 : ret = 0UL; /* success */
401 0 : }
402 0 : break;
403 0 : }
404 :
405 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1598 */
406 0 : case MATCH_ID_OP( BLS_G2_BE, FD_VM_SYSCALL_SOL_CURVE_SUB ):
407 0 : case MATCH_ID_OP( BLS_G2_LE, FD_VM_SYSCALL_SOL_CURVE_SUB ): {
408 0 : uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ ];
409 : /* Compute sub */
410 0 : if( FD_LIKELY( fd_bls12_381_g2_sub_syscall( _result, inputL, inputR, big_endian )==0 ) ) {
411 0 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
412 0 : memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
413 0 : ret = 0UL; /* success */
414 0 : }
415 0 : break;
416 0 : }
417 :
418 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1632 */
419 0 : case MATCH_ID_OP( BLS_G2_BE, FD_VM_SYSCALL_SOL_CURVE_MUL ):
420 0 : case MATCH_ID_OP( BLS_G2_LE, FD_VM_SYSCALL_SOL_CURVE_MUL ): {
421 0 : uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ ];
422 : /* Compute mul */
423 0 : if( FD_LIKELY( fd_bls12_381_g2_mul_syscall( _result, inputL, inputR, big_endian )==0 ) ) {
424 0 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
425 0 : memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
426 0 : ret = 0UL; /* success */
427 0 : }
428 0 : break;
429 0 : }
430 0 : #endif
431 :
432 0 : default:
433 : /* COV: this can never happen because of the previous switch */
434 0 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
435 441 : }
436 :
437 139 : soft_error:
438 139 : *_ret = ret;
439 139 : return FD_VM_SUCCESS;
440 0 : #undef MATCH_ID_OP
441 0 : #undef EDWARDS
442 0 : #undef RISTRETTO
443 0 : #undef BLS_G1_BE
444 0 : #undef BLS_G1_LE
445 0 : #undef BLS_G2_BE
446 0 : #undef BLS_G2_LE
447 :
448 6 : invalid_error:
449 : /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L1135-L1156 */
450 6 : if( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, abort_on_invalid_curve ) ) {
451 3 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
452 3 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
453 3 : }
454 3 : *_ret = 1UL;
455 3 : return FD_VM_SUCCESS;
456 6 : }
457 :
458 : /* multi_scalar_mul_edwards computes a MSM on curve25519.
459 :
460 : This function is equivalent to
461 : zk-token-sdk::edwards::multi_scalar_mul_edwards
462 :
463 : https://github.com/solana-labs/solana/blob/v1.17.7/zk-token-sdk/src/curve25519/edwards.rs#L116
464 :
465 : Specifically it takes as input byte arrays and takes care of scalars
466 : validation and points decompression. It then invokes ballet MSM
467 : function fd_ed25519_multi_scalar_mul. To avoid dynamic allocation,
468 : the full MSM is done in batches of FD_BALLET_CURVE25519_MSM_BATCH_SZ. */
469 :
470 : static fd_ed25519_point_t *
471 : multi_scalar_mul_edwards( fd_ed25519_point_t * r,
472 : uchar const * scalars,
473 : uchar const * points,
474 68 : ulong cnt ) {
475 : /* Validate all scalars first (fast) */
476 203 : for( ulong i=0UL; i<cnt; i++ ) {
477 136 : if( FD_UNLIKELY( !fd_curve25519_scalar_validate ( scalars + i*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ ) ) ) {
478 1 : return NULL;
479 1 : }
480 136 : }
481 :
482 : /* Static allocation of a batch of decompressed points */
483 67 : fd_ed25519_point_t tmp[1];
484 67 : fd_ed25519_point_t A[ FD_BALLET_CURVE25519_MSM_BATCH_SZ ];
485 :
486 67 : fd_ed25519_point_set_zero( r );
487 133 : for( ulong i=0UL; i<cnt; i+=FD_BALLET_CURVE25519_MSM_BATCH_SZ ) {
488 67 : ulong batch_cnt = fd_ulong_min( cnt-i, FD_BALLET_CURVE25519_MSM_BATCH_SZ );
489 :
490 : /* Decompress (and validate) points */
491 199 : for( ulong j=0UL; j<batch_cnt; j++ ) {
492 : //TODO: use fd_ed25519_point_frombytes_2x
493 133 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( &A[j], points + j*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ ) ) ) {
494 1 : return NULL;
495 1 : }
496 133 : }
497 :
498 66 : fd_ed25519_multi_scalar_mul( tmp, scalars, A, batch_cnt );
499 66 : fd_ed25519_point_add( r, r, tmp );
500 66 : points += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ *batch_cnt;
501 66 : scalars += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ*batch_cnt;
502 66 : }
503 :
504 66 : return r;
505 67 : }
506 :
507 : /* multi_scalar_mul_ristretto computes a MSM on ristretto255.
508 : See multi_scalar_mul_edwards for details. */
509 :
510 : static fd_ristretto255_point_t *
511 : multi_scalar_mul_ristretto( fd_ristretto255_point_t * r,
512 : uchar const * scalars,
513 : uchar const * points,
514 37 : ulong cnt ) {
515 : /* Validate all scalars first (fast) */
516 110 : for( ulong i=0UL; i<cnt; i++ ) {
517 74 : if( FD_UNLIKELY( !fd_curve25519_scalar_validate ( scalars + i*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ ) ) ) {
518 1 : return NULL;
519 1 : }
520 74 : }
521 :
522 : /* Static allocation of a batch of decompressed points */
523 36 : fd_ristretto255_point_t tmp[1];
524 36 : fd_ristretto255_point_t A[ FD_BALLET_CURVE25519_MSM_BATCH_SZ ];
525 :
526 36 : fd_ristretto255_point_set_zero( r );
527 68 : for( ulong i=0UL; i<cnt; i+=FD_BALLET_CURVE25519_MSM_BATCH_SZ ) {
528 36 : ulong batch_cnt = fd_ulong_min( cnt-i, FD_BALLET_CURVE25519_MSM_BATCH_SZ );
529 :
530 : /* Decompress (and validate) points */
531 100 : for( ulong j=0UL; j<batch_cnt; j++ ) {
532 : //TODO: use fd_ristretto255_point_frombytes_2x
533 68 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( &A[j], points + j*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ ) ) ) {
534 4 : return NULL;
535 4 : }
536 68 : }
537 :
538 32 : fd_ristretto255_multi_scalar_mul( tmp, scalars, A, batch_cnt );
539 32 : fd_ristretto255_point_add( r, r, tmp );
540 32 : points += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ *batch_cnt;
541 32 : scalars += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ*batch_cnt;
542 32 : }
543 :
544 32 : return r;
545 36 : }
546 :
547 : #undef BATCH_MAX
548 :
549 : int
550 : fd_vm_syscall_sol_curve_multiscalar_mul( void * _vm,
551 : ulong curve_id,
552 : ulong scalars_addr,
553 : ulong points_addr,
554 : ulong points_len,
555 : ulong result_point_addr,
556 115 : ulong * _ret ) {
557 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1129 */
558 115 : fd_vm_t * vm = (fd_vm_t *)_vm;
559 115 : ulong ret = 1UL; /* by default return Ok(1) == error */
560 :
561 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1143-L1151 */
562 115 : if( FD_UNLIKELY( points_len > 512 ) ) {
563 2 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_LENGTH );
564 2 : return FD_VM_SYSCALL_ERR_INVALID_LENGTH; /* SyscallError::InvalidLength */
565 2 : }
566 :
567 : /* Note: we don't strictly follow the Rust implementation, but instead combine
568 : common code across switch cases. Similar to fd_vm_syscall_sol_alt_bn128_group_op. */
569 :
570 113 : ulong base_cost = 0UL;
571 113 : ulong incremental_cost = 0UL;
572 113 : switch( curve_id ) {
573 71 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS:
574 71 : base_cost = FD_VM_CURVE_EDWARDS_MSM_BASE_COST;
575 71 : incremental_cost = FD_VM_CURVE_EDWARDS_MSM_INCREMENTAL_COST;
576 71 : break;
577 :
578 40 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO:
579 40 : base_cost = FD_VM_CURVE_RISTRETTO_MSM_BASE_COST;
580 40 : incremental_cost = FD_VM_CURVE_RISTRETTO_MSM_INCREMENTAL_COST;
581 40 : break;
582 :
583 2 : default:
584 : /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L1262-L1271 */
585 2 : if( FD_UNLIKELY( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, abort_on_invalid_curve ) ) ) {
586 1 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
587 1 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
588 1 : }
589 1 : goto soft_error;
590 113 : }
591 :
592 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1155-L1164 */
593 111 : ulong cost = fd_ulong_sat_add(
594 111 : base_cost,
595 111 : fd_ulong_sat_mul(
596 111 : incremental_cost,
597 111 : fd_ulong_sat_sub( points_len, 1 )
598 111 : )
599 111 : );
600 111 : FD_VM_CU_UPDATE( vm, cost );
601 :
602 : /* Edge case points_len==0.
603 : Agave computes the MSM, that returns the point at infinity, and stores the result.
604 : This means that we have to mem map result, and then set the point at infinity,
605 : that is 0x0100..00 for Edwards and 0x00..00 for Ristretto. */
606 109 : if ( FD_UNLIKELY( points_len==0 ) ) {
607 0 : uchar * result = FD_VM_MEM_HADDR_ST( vm, result_point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
608 0 : memset( result, 0, 32 );
609 0 : result[0] = curve_id==FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS ? 1 : 0;
610 0 : *_ret = 0;
611 0 : return FD_VM_SUCCESS;
612 0 : }
613 :
614 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1166-L1178 */
615 323 : uchar const * scalars = FD_VM_MEM_HADDR_LD( vm, scalars_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, points_len*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ );
616 317 : uchar const * points = FD_VM_MEM_HADDR_LD( vm, points_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, points_len*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
617 :
618 0 : switch( curve_id ) {
619 :
620 68 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS: {
621 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1180-L1189 */
622 68 : fd_ed25519_point_t _r[1];
623 68 : fd_ed25519_point_t * r = multi_scalar_mul_edwards( _r, scalars, points, points_len );
624 :
625 68 : if( FD_LIKELY( r ) ) {
626 66 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
627 66 : fd_ed25519_point_tobytes( result, r );
628 66 : ret = 0UL;
629 66 : }
630 68 : break;
631 68 : }
632 :
633 68 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO: {
634 37 : fd_ristretto255_point_t _r[1];
635 37 : fd_ristretto255_point_t * r = multi_scalar_mul_ristretto( _r, scalars, points, points_len );
636 :
637 37 : if( FD_LIKELY( r ) ) {
638 32 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
639 32 : fd_ristretto255_point_tobytes( result, r );
640 32 : ret = 0UL;
641 32 : }
642 37 : break;
643 37 : }
644 :
645 37 : default:
646 : /* COV: this can never happen because of the previous switch */
647 0 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
648 317 : }
649 :
650 106 : soft_error:
651 106 : *_ret = ret;
652 106 : return FD_VM_SUCCESS;
653 317 : }
654 :
655 : #if FD_HAS_BLST
656 :
657 : int
658 : fd_vm_syscall_sol_curve_decompress( /**/ void * _vm,
659 : /**/ ulong curve_id,
660 : /**/ ulong point_addr,
661 : /**/ ulong result_addr,
662 : FD_PARAM_UNUSED ulong r4,
663 : FD_PARAM_UNUSED ulong r5,
664 0 : /**/ ulong * _ret ) {
665 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1118 */
666 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
667 0 : ulong ret = 1UL; /* by default return Ok(1) == error */
668 :
669 0 : int big_endian = ( curve_id & 0x80 ) ? 1 : 0;
670 :
671 0 : uchar const * point = NULL;
672 0 : switch( curve_id ) {
673 :
674 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1137 */
675 0 : case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE:
676 0 : case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE: {
677 0 : FD_VM_CU_UPDATE( vm, FD_VM_CURVE_BLS12_381_G1_DECOMPRESS_COST );
678 0 : point = FD_VM_MEM_HADDR_LD( vm, point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_COMPRESSED_SZ );
679 0 : uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ ];
680 0 : if( FD_LIKELY( fd_bls12_381_g1_decompress_syscall( _result, point, big_endian )==0 ) ) {
681 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1160 */
682 0 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
683 0 : memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
684 0 : ret = 0UL; /* success */
685 0 : }
686 0 : } break;
687 :
688 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1171 */
689 0 : case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE:
690 0 : case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE: {
691 0 : FD_VM_CU_UPDATE( vm, FD_VM_CURVE_BLS12_381_G2_DECOMPRESS_COST );
692 0 : point = FD_VM_MEM_HADDR_LD( vm, point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_COMPRESSED_SZ );
693 0 : uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ ];
694 0 : if( FD_LIKELY( fd_bls12_381_g2_decompress_syscall( _result, point, big_endian )==0 ) ) {
695 0 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
696 0 : memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ );
697 0 : ret = 0UL; /* success */
698 0 : }
699 0 : } break;
700 :
701 0 : default:
702 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
703 0 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
704 0 : }
705 :
706 0 : *_ret = ret;
707 0 : return FD_VM_SUCCESS;
708 0 : }
709 :
710 : int
711 : fd_vm_syscall_sol_curve_pairing_map( /**/ void * _vm,
712 : /**/ ulong curve_id,
713 : /**/ ulong num_pairs,
714 : FD_PARAM_UNUSED ulong g1_points_addr,
715 : FD_PARAM_UNUSED ulong g2_points_addr,
716 : FD_PARAM_UNUSED ulong result_addr,
717 0 : /**/ ulong * _ret ) {
718 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1804 */
719 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
720 0 : ulong ret = 1UL; /* by default return Ok(1) == error */
721 :
722 0 : int big_endian = ( curve_id & 0x80 ) ? 1 : 0;
723 :
724 0 : switch( curve_id ) {
725 :
726 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1823 */
727 0 : case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_BE:
728 0 : case FD_VM_SYSCALL_SOL_CURVE_BLS12_381_LE: {
729 :
730 0 : ulong cost = fd_ulong_sat_add( FD_VM_CURVE_BLS12_381_PAIRING_BASE_COST,
731 0 : fd_ulong_sat_mul( FD_VM_CURVE_BLS12_381_PAIRING_INCR_COST,
732 0 : fd_ulong_sat_sub( num_pairs, 1 ) ) );
733 0 : FD_VM_CU_UPDATE( vm, cost );
734 :
735 0 : ulong total_g1_sz = fd_ulong_sat_mul( FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ, num_pairs );
736 0 : uchar const * g1_points = FD_VM_MEM_HADDR_LD( vm, g1_points_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, total_g1_sz );
737 :
738 0 : ulong total_g2_sz = fd_ulong_sat_mul( FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_POINT_SZ, num_pairs );
739 0 : uchar const * g2_points = FD_VM_MEM_HADDR_LD( vm, g2_points_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, total_g2_sz );
740 :
741 0 : uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_GT_ELE_SZ ];
742 0 : if( FD_LIKELY( fd_bls12_381_pairing_syscall( _result, g1_points, g2_points, num_pairs, big_endian )==0 ) ) {
743 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1860 */
744 0 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_GT_ELE_SZ );
745 0 : memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_GT_ELE_SZ );
746 0 : ret = 0UL; /* success */
747 0 : }
748 0 : } break;
749 :
750 0 : default:
751 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
752 0 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
753 0 : }
754 :
755 0 : *_ret = ret;
756 0 : return FD_VM_SUCCESS;
757 0 : }
758 :
759 : #endif
|