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 0 : /**/ ulong * _ret ) {
15 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L871 */
16 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
17 0 : 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 0 : {
23 0 : if( FD_UNLIKELY(
24 0 : !FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, enable_bls12_381_syscall )
25 0 : && ( curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE
26 0 : || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE
27 0 : || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE
28 0 : || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE )
29 0 : ) ) {
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 0 : }
34 :
35 0 : uchar const * point = NULL;
36 0 : switch( curve_id ) {
37 :
38 0 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS:
39 :
40 0 : FD_VM_CU_UPDATE( vm, FD_VM_CURVE_EDWARDS_VALIDATE_POINT_COST );
41 0 : 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 0 : break;
44 :
45 0 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO:
46 :
47 0 : FD_VM_CU_UPDATE( vm, FD_VM_CURVE_RISTRETTO_VALIDATE_POINT_COST );
48 0 : 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 0 : 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 0 : default:
73 : /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L919-L928 */
74 0 : if( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, abort_on_invalid_curve ) ) {
75 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
76 0 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
77 0 : }
78 0 : }
79 :
80 0 : *_ret = ret;
81 0 : return FD_VM_SUCCESS;
82 0 : }
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 15 : ulong * _ret ) {
92 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L928 */
93 15 : fd_vm_t * vm = (fd_vm_t *)_vm;
94 15 : 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 15 : {
100 15 : if( FD_UNLIKELY(
101 15 : !FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, enable_bls12_381_syscall )
102 15 : && ( curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE
103 15 : || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE
104 15 : || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE
105 15 : || curve_id==FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE )
106 15 : ) ) {
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 15 : }
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 30 : #define MATCH_ID_OP(crv_id,grp_op) ((crv_id << 4) | grp_op)
123 15 : #define EDWARDS FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS
124 15 : #define RISTRETTO FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO
125 15 : #define BLS_G1_BE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_BE
126 15 : #define BLS_G1_LE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_LE
127 15 : #define BLS_G2_BE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_BE
128 15 : #define BLS_G2_LE FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G2_LE
129 :
130 15 : ulong cost = 0UL;
131 15 : ulong inputL_sz = 32UL;
132 15 : ulong inputR_sz = 32UL;
133 15 : switch( curve_id ) {
134 :
135 0 : case EDWARDS:
136 0 : switch( group_op ) {
137 :
138 0 : case FD_VM_SYSCALL_SOL_CURVE_ADD:
139 0 : cost = FD_VM_CURVE_EDWARDS_ADD_COST;
140 0 : break;
141 :
142 0 : case FD_VM_SYSCALL_SOL_CURVE_SUB:
143 0 : cost = FD_VM_CURVE_EDWARDS_SUBTRACT_COST;
144 0 : break;
145 :
146 0 : case FD_VM_SYSCALL_SOL_CURVE_MUL:
147 0 : cost = FD_VM_CURVE_EDWARDS_MULTIPLY_COST;
148 0 : break;
149 :
150 0 : default:
151 0 : goto invalid_error;
152 0 : }
153 0 : break;
154 :
155 12 : case RISTRETTO:
156 12 : switch( group_op ) {
157 :
158 6 : case FD_VM_SYSCALL_SOL_CURVE_ADD:
159 6 : cost = FD_VM_CURVE_RISTRETTO_ADD_COST;
160 6 : break;
161 :
162 3 : case FD_VM_SYSCALL_SOL_CURVE_SUB:
163 3 : cost = FD_VM_CURVE_RISTRETTO_SUBTRACT_COST;
164 3 : break;
165 :
166 3 : case FD_VM_SYSCALL_SOL_CURVE_MUL:
167 3 : cost = FD_VM_CURVE_RISTRETTO_MULTIPLY_COST;
168 3 : break;
169 :
170 0 : default:
171 0 : goto invalid_error;
172 12 : }
173 12 : break;
174 :
175 12 : #if FD_HAS_BLST
176 : /* BLS12-381 G1 */
177 12 : case BLS_G1_BE:
178 3 : case BLS_G1_LE:
179 3 : switch( group_op ) {
180 :
181 3 : case FD_VM_SYSCALL_SOL_CURVE_ADD:
182 3 : cost = FD_VM_CURVE_BLS12_381_G1_ADD_COST;
183 3 : inputL_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ;
184 3 : inputR_sz = FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ;
185 3 : 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 3 : }
202 3 : break;
203 :
204 : /* BLS12-381 G2 */
205 3 : 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 0 : default:
234 0 : goto invalid_error;
235 15 : }
236 :
237 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L944-L947 */
238 30 : 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 45 : uchar const * inputL = FD_VM_MEM_HADDR_LD( vm, left_input_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, inputL_sz );
244 45 : 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 15 : int big_endian = ( curve_id & 0x80 ) ? 1 : 0;
248 45 : #endif
249 :
250 45 : switch( MATCH_ID_OP( curve_id, group_op ) ) {
251 :
252 0 : case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
253 0 : fd_ed25519_point_t p0[1], p1[1], r[1];
254 0 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p0, inputL ) ) ) {
255 0 : goto soft_error;
256 0 : }
257 0 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p1, inputR ) ) ) {
258 0 : goto soft_error;
259 0 : }
260 :
261 0 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
262 0 : fd_ed25519_point_add( r, p0, p1 );
263 0 : fd_ed25519_point_tobytes( result, r );
264 0 : ret = 0UL;
265 0 : break;
266 0 : }
267 :
268 0 : case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_SUB ): {
269 0 : fd_ed25519_point_t p0[1], p1[1], r[1];
270 0 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p0, inputL ) ) ) {
271 0 : goto soft_error;
272 0 : }
273 0 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p1, inputR ) ) ) {
274 0 : goto soft_error;
275 0 : }
276 :
277 0 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
278 0 : fd_ed25519_point_sub( r, p0, p1 );
279 0 : fd_ed25519_point_tobytes( result, r );
280 0 : ret = 0UL;
281 0 : break;
282 0 : }
283 :
284 0 : case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_MUL ): {
285 0 : fd_ed25519_point_t p[1], r[1];
286 0 : if( FD_UNLIKELY( !fd_curve25519_scalar_validate( inputL ) ) ) {
287 0 : goto soft_error;
288 0 : }
289 0 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p, inputR ) ) ) {
290 0 : goto soft_error;
291 0 : }
292 :
293 0 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
294 0 : fd_ed25519_scalar_mul( r, inputL, p );
295 0 : fd_ed25519_point_tobytes( result, r );
296 0 : ret = 0UL;
297 0 : break;
298 0 : }
299 :
300 6 : case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
301 6 : fd_ristretto255_point_t p0[1], p1[1], r[1];
302 6 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p0, inputL ) ) ) {
303 0 : goto soft_error;
304 0 : }
305 6 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p1, inputR ) ) ) {
306 0 : goto soft_error;
307 0 : }
308 :
309 6 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
310 6 : fd_ristretto255_point_add( r, p0, p1 );
311 6 : fd_ristretto255_point_tobytes( result, r );
312 6 : ret = 0UL;
313 6 : break;
314 6 : }
315 :
316 3 : case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_SUB ): {
317 3 : fd_ristretto255_point_t p0[1], p1[1], r[1];
318 3 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p0, inputL ) ) ) {
319 0 : goto soft_error;
320 0 : }
321 3 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p1, inputR ) ) ) {
322 0 : goto soft_error;
323 0 : }
324 :
325 3 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
326 3 : fd_ristretto255_point_sub( r, p0, p1 );
327 3 : fd_ristretto255_point_tobytes( result, r );
328 3 : ret = 0UL;
329 3 : break;
330 3 : }
331 :
332 3 : case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_MUL ): {
333 3 : fd_ristretto255_point_t p[1], r[1];
334 3 : if( FD_UNLIKELY( !fd_curve25519_scalar_validate( inputL ) ) ) {
335 0 : goto soft_error;
336 0 : }
337 3 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p, inputR ) ) ) {
338 0 : goto soft_error;
339 0 : }
340 :
341 3 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
342 3 : fd_ristretto255_scalar_mul( r, inputL, p );
343 3 : fd_ristretto255_point_tobytes( result, r );
344 3 : ret = 0UL;
345 3 : break;
346 3 : }
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 3 : case MATCH_ID_OP( BLS_G1_LE, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
354 3 : uchar _result[ FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ ];
355 : /* Compute add */
356 3 : 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 3 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
359 3 : memcpy( result, _result, FD_VM_SYSCALL_SOL_CURVE_BLS12_381_G1_POINT_SZ );
360 3 : ret = 0UL; /* success */
361 3 : }
362 3 : break;
363 3 : }
364 :
365 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/syscalls/src/lib.rs#L1485 */
366 3 : 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 45 : }
436 :
437 15 : soft_error:
438 15 : *_ret = ret;
439 15 : 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 0 : invalid_error:
449 : /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L1135-L1156 */
450 0 : if( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, abort_on_invalid_curve ) ) {
451 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
452 0 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
453 0 : }
454 0 : *_ret = 1UL;
455 0 : return FD_VM_SUCCESS;
456 0 : }
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 3 : ulong cnt ) {
475 : /* Validate all scalars first (fast) */
476 9 : for( ulong i=0UL; i<cnt; i++ ) {
477 6 : if( FD_UNLIKELY( !fd_curve25519_scalar_validate ( scalars + i*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ ) ) ) {
478 0 : return NULL;
479 0 : }
480 6 : }
481 :
482 : /* Static allocation of a batch of decompressed points */
483 3 : fd_ed25519_point_t tmp[1];
484 3 : fd_ed25519_point_t A[ FD_BALLET_CURVE25519_MSM_BATCH_SZ ];
485 :
486 3 : fd_ed25519_point_set_zero( r );
487 6 : for( ulong i=0UL; i<cnt; i+=FD_BALLET_CURVE25519_MSM_BATCH_SZ ) {
488 3 : ulong batch_cnt = fd_ulong_min( cnt-i, FD_BALLET_CURVE25519_MSM_BATCH_SZ );
489 :
490 : /* Decompress (and validate) points */
491 9 : for( ulong j=0UL; j<batch_cnt; j++ ) {
492 : //TODO: use fd_ed25519_point_frombytes_2x
493 6 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( &A[j], points + j*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ ) ) ) {
494 0 : return NULL;
495 0 : }
496 6 : }
497 :
498 3 : fd_ed25519_multi_scalar_mul( tmp, scalars, A, batch_cnt );
499 3 : fd_ed25519_point_add( r, r, tmp );
500 3 : points += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ *batch_cnt;
501 3 : scalars += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ*batch_cnt;
502 3 : }
503 :
504 3 : return r;
505 3 : }
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 3 : ulong cnt ) {
515 : /* Validate all scalars first (fast) */
516 9 : for( ulong i=0UL; i<cnt; i++ ) {
517 6 : if( FD_UNLIKELY( !fd_curve25519_scalar_validate ( scalars + i*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ ) ) ) {
518 0 : return NULL;
519 0 : }
520 6 : }
521 :
522 : /* Static allocation of a batch of decompressed points */
523 3 : fd_ristretto255_point_t tmp[1];
524 3 : fd_ristretto255_point_t A[ FD_BALLET_CURVE25519_MSM_BATCH_SZ ];
525 :
526 3 : fd_ristretto255_point_set_zero( r );
527 6 : for( ulong i=0UL; i<cnt; i+=FD_BALLET_CURVE25519_MSM_BATCH_SZ ) {
528 3 : ulong batch_cnt = fd_ulong_min( cnt-i, FD_BALLET_CURVE25519_MSM_BATCH_SZ );
529 :
530 : /* Decompress (and validate) points */
531 9 : for( ulong j=0UL; j<batch_cnt; j++ ) {
532 : //TODO: use fd_ristretto255_point_frombytes_2x
533 6 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( &A[j], points + j*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ ) ) ) {
534 0 : return NULL;
535 0 : }
536 6 : }
537 :
538 3 : fd_ristretto255_multi_scalar_mul( tmp, scalars, A, batch_cnt );
539 3 : fd_ristretto255_point_add( r, r, tmp );
540 3 : points += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ *batch_cnt;
541 3 : scalars += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ*batch_cnt;
542 3 : }
543 :
544 3 : return r;
545 3 : }
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 15 : ulong * _ret ) {
557 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1129 */
558 15 : fd_vm_t * vm = (fd_vm_t *)_vm;
559 15 : 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 15 : if( FD_UNLIKELY( points_len > 512 ) ) {
563 3 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_LENGTH );
564 3 : return FD_VM_SYSCALL_ERR_INVALID_LENGTH; /* SyscallError::InvalidLength */
565 3 : }
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 12 : ulong base_cost = 0UL;
571 12 : ulong incremental_cost = 0UL;
572 12 : switch( curve_id ) {
573 6 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS:
574 6 : base_cost = FD_VM_CURVE_EDWARDS_MSM_BASE_COST;
575 6 : incremental_cost = FD_VM_CURVE_EDWARDS_MSM_INCREMENTAL_COST;
576 6 : break;
577 :
578 3 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO:
579 3 : base_cost = FD_VM_CURVE_RISTRETTO_MSM_BASE_COST;
580 3 : incremental_cost = FD_VM_CURVE_RISTRETTO_MSM_INCREMENTAL_COST;
581 3 : break;
582 :
583 3 : default:
584 : /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L1262-L1271 */
585 3 : if( FD_UNLIKELY( FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, abort_on_invalid_curve ) ) ) {
586 3 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
587 3 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
588 3 : }
589 0 : goto soft_error;
590 12 : }
591 :
592 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1155-L1164 */
593 9 : ulong cost = fd_ulong_sat_add(
594 9 : base_cost,
595 9 : fd_ulong_sat_mul(
596 9 : incremental_cost,
597 9 : fd_ulong_sat_sub( points_len, 1 )
598 9 : )
599 9 : );
600 9 : 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 9 : if ( FD_UNLIKELY( points_len==0 ) ) {
607 3 : 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 3 : }
613 :
614 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1166-L1178 */
615 18 : 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 18 : 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 3 : 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 3 : fd_ed25519_point_t _r[1];
623 3 : fd_ed25519_point_t * r = multi_scalar_mul_edwards( _r, scalars, points, points_len );
624 :
625 3 : if( FD_LIKELY( r ) ) {
626 3 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
627 3 : fd_ed25519_point_tobytes( result, r );
628 3 : ret = 0UL;
629 3 : }
630 3 : break;
631 3 : }
632 :
633 3 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO: {
634 3 : fd_ristretto255_point_t _r[1];
635 3 : fd_ristretto255_point_t * r = multi_scalar_mul_ristretto( _r, scalars, points, points_len );
636 :
637 3 : if( FD_LIKELY( r ) ) {
638 3 : uchar * result = FD_VM_HADDR_QUERY_U8_ARRAY( vm, result_point_addr, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
639 3 : fd_ristretto255_point_tobytes( result, r );
640 3 : ret = 0UL;
641 3 : }
642 3 : break;
643 3 : }
644 :
645 3 : default:
646 : /* COV: this can never happen because of the previous switch */
647 0 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
648 18 : }
649 :
650 6 : soft_error:
651 6 : *_ret = ret;
652 6 : return FD_VM_SUCCESS;
653 18 : }
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_POINT_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_POINT_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
|