Line data Source code
1 : #include "fd_vm_syscall.h"
2 :
3 : #include "../../../ballet/ed25519/fd_curve25519.h"
4 : #include "../../../ballet/ed25519/fd_ristretto255.h"
5 :
6 : int
7 : fd_vm_syscall_sol_curve_validate_point( /**/ void * _vm,
8 : /**/ ulong curve_id,
9 : /**/ ulong point_addr,
10 : FD_PARAM_UNUSED ulong r3,
11 : FD_PARAM_UNUSED ulong r4,
12 : FD_PARAM_UNUSED ulong r5,
13 30 : /**/ ulong * _ret ) {
14 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L871 */
15 30 : fd_vm_t * vm = (fd_vm_t *)_vm;
16 30 : ulong ret = 1UL; /* by default return Ok(1) == error */
17 :
18 30 : uchar const * point = NULL;
19 30 : switch( curve_id ) {
20 :
21 12 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS:
22 :
23 12 : FD_VM_CU_UPDATE( vm, FD_VM_CURVE25519_EDWARDS_VALIDATE_POINT_COST );
24 9 : point = FD_VM_MEM_HADDR_LD( vm, point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
25 0 : ret = (ulong)!fd_ed25519_point_validate( point ); /* 0 if valid point, 1 if not */
26 6 : break;
27 :
28 12 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO:
29 :
30 12 : FD_VM_CU_UPDATE( vm, FD_VM_CURVE25519_RISTRETTO_VALIDATE_POINT_COST );
31 9 : point = FD_VM_MEM_HADDR_LD( vm, point_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
32 0 : ret = (ulong)!fd_ristretto255_point_validate( point ); /* 0 if valid point, 1 if not */
33 6 : break;
34 :
35 6 : default:
36 : /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L919-L928 */
37 6 : if( FD_FEATURE_ACTIVE( (vm->instr_ctx->slot_ctx), abort_on_invalid_curve ) ) {
38 3 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_ERR_SYSCALL_INVALID_ATTRIBUTE );
39 3 : return FD_VM_ERR_INVAL; /* SyscallError::InvalidAttribute */
40 3 : }
41 30 : }
42 :
43 15 : *_ret = ret;
44 15 : return FD_VM_SUCCESS;
45 30 : }
46 :
47 : int
48 : fd_vm_syscall_sol_curve_group_op( void * _vm,
49 : ulong curve_id,
50 : ulong group_op,
51 : ulong left_input_addr,
52 : ulong right_input_addr,
53 : ulong result_point_addr,
54 252 : ulong * _ret ) {
55 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L928 */
56 252 : fd_vm_t * vm = (fd_vm_t *)_vm;
57 252 : ulong ret = 1UL; /* by default return Ok(1) == error */
58 :
59 : /* Note: we don't strictly follow the Rust implementation, but instead combine
60 : common code across switch cases. Similar to fd_vm_syscall_sol_alt_bn128_group_op. */
61 :
62 : /* MATCH_ID_OP allows us to unify 2 switch/case into 1.
63 : For better readability, we also temp define EDWARDS, RISTRETTO.
64 :
65 : The first time we check that both curve_id and group_op are valid
66 : with 2 nested switch/case. Using MATCH_ID_OP leads to undesidered
67 : edge cases. The second time, when we know that curve_id and group_op
68 : are correct, then we can use MATCH_ID_OP and a single switch/case. */
69 360 : #define MATCH_ID_OP(crv_id,grp_op) ((crv_id << 4) | grp_op)
70 252 : #define EDWARDS FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS
71 252 : #define RISTRETTO FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO
72 :
73 252 : ulong cost = 0UL;
74 252 : switch( curve_id ) {
75 :
76 117 : case EDWARDS:
77 117 : switch( group_op ) {
78 :
79 21 : case FD_VM_SYSCALL_SOL_CURVE_ADD:
80 21 : cost = FD_VM_CURVE25519_EDWARDS_ADD_COST;
81 21 : break;
82 :
83 21 : case FD_VM_SYSCALL_SOL_CURVE_SUB:
84 21 : cost = FD_VM_CURVE25519_EDWARDS_SUBTRACT_COST;
85 21 : break;
86 :
87 69 : case FD_VM_SYSCALL_SOL_CURVE_MUL:
88 69 : cost = FD_VM_CURVE25519_EDWARDS_MULTIPLY_COST;
89 69 : break;
90 :
91 6 : default:
92 6 : goto invalid_error;
93 117 : }
94 111 : break;
95 :
96 129 : case RISTRETTO:
97 129 : switch( group_op ) {
98 :
99 27 : case FD_VM_SYSCALL_SOL_CURVE_ADD:
100 27 : cost = FD_VM_CURVE25519_RISTRETTO_ADD_COST;
101 27 : break;
102 :
103 24 : case FD_VM_SYSCALL_SOL_CURVE_SUB:
104 24 : cost = FD_VM_CURVE25519_RISTRETTO_SUBTRACT_COST;
105 24 : break;
106 :
107 72 : case FD_VM_SYSCALL_SOL_CURVE_MUL:
108 72 : cost = FD_VM_CURVE25519_RISTRETTO_MULTIPLY_COST;
109 72 : break;
110 :
111 6 : default:
112 6 : goto invalid_error;
113 129 : }
114 123 : break;
115 :
116 123 : default:
117 6 : goto invalid_error;
118 252 : }
119 :
120 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L944-L947 */
121 450 : FD_VM_CU_UPDATE( vm, cost );
122 :
123 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L949-L958 */
124 :
125 : /* Note: left_input_addr is a point for add, sub, BUT it's a scalar for mul.
126 : However, from a memory mapping perspective it's always 32 bytes, so we unify the code. */
127 612 : uchar const * inputL = FD_VM_MEM_HADDR_LD( vm, left_input_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, 32UL );
128 558 : uchar const * inputR = FD_VM_MEM_HADDR_LD( vm, right_input_addr, FD_VM_ALIGN_RUST_POD_U8_ARRAY, FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ );
129 :
130 180 : switch( MATCH_ID_OP( curve_id, group_op ) ) {
131 :
132 12 : case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
133 12 : fd_ed25519_point_t p0[1], p1[1], r[1];
134 12 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p0, inputL ) ) ) {
135 3 : goto soft_error;
136 3 : }
137 9 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p1, inputR ) ) ) {
138 3 : goto soft_error;
139 3 : }
140 :
141 6 : 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 );
142 0 : fd_ed25519_point_add( r, p0, p1 );
143 3 : fd_ed25519_point_tobytes( result, r );
144 3 : ret = 0UL;
145 3 : break;
146 9 : }
147 :
148 12 : case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_SUB ): {
149 12 : fd_ed25519_point_t p0[1], p1[1], r[1];
150 12 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p0, inputL ) ) ) {
151 3 : goto soft_error;
152 3 : }
153 9 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p1, inputR ) ) ) {
154 3 : goto soft_error;
155 3 : }
156 :
157 6 : 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 );
158 0 : fd_ed25519_point_sub( r, p0, p1 );
159 3 : fd_ed25519_point_tobytes( result, r );
160 3 : ret = 0UL;
161 3 : break;
162 9 : }
163 :
164 60 : case MATCH_ID_OP( EDWARDS, FD_VM_SYSCALL_SOL_CURVE_MUL ): {
165 60 : fd_ed25519_point_t p[1], r[1];
166 60 : if( FD_UNLIKELY( !fd_curve25519_scalar_validate( inputL ) ) ) {
167 12 : goto soft_error;
168 12 : }
169 48 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( p, inputR ) ) ) {
170 6 : goto soft_error;
171 6 : }
172 :
173 42 : 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 );
174 0 : fd_ed25519_scalar_mul( r, inputL, p );
175 39 : fd_ed25519_point_tobytes( result, r );
176 39 : ret = 0UL;
177 39 : break;
178 81 : }
179 :
180 18 : case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_ADD ): {
181 18 : fd_ristretto255_point_t p0[1], p1[1], r[1];
182 18 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p0, inputL ) ) ) {
183 3 : goto soft_error;
184 3 : }
185 15 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p1, inputR ) ) ) {
186 3 : goto soft_error;
187 3 : }
188 :
189 12 : 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 );
190 9 : fd_ristretto255_point_add( r, p0, p1 );
191 9 : fd_ristretto255_point_tobytes( result, r );
192 9 : ret = 0UL;
193 9 : break;
194 21 : }
195 :
196 15 : case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_SUB ): {
197 15 : fd_ristretto255_point_t p0[1], p1[1], r[1];
198 15 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p0, inputL ) ) ) {
199 3 : goto soft_error;
200 3 : }
201 12 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p1, inputR ) ) ) {
202 3 : goto soft_error;
203 3 : }
204 :
205 9 : 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 );
206 6 : fd_ristretto255_point_sub( r, p0, p1 );
207 6 : fd_ristretto255_point_tobytes( result, r );
208 6 : ret = 0UL;
209 6 : break;
210 15 : }
211 :
212 63 : case MATCH_ID_OP( RISTRETTO, FD_VM_SYSCALL_SOL_CURVE_MUL ): {
213 63 : fd_ristretto255_point_t p[1], r[1];
214 63 : if( FD_UNLIKELY( !fd_curve25519_scalar_validate( inputL ) ) ) {
215 15 : goto soft_error;
216 15 : }
217 48 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( p, inputR ) ) ) {
218 30 : goto soft_error;
219 30 : }
220 :
221 18 : 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 );
222 15 : fd_ristretto255_scalar_mul( r, inputL, p );
223 15 : fd_ristretto255_point_tobytes( result, r );
224 15 : ret = 0UL;
225 15 : break;
226 33 : }
227 :
228 0 : default:
229 : /* COV: this can never happen because of the previous switch */
230 0 : return FD_VM_ERR_INVAL; /* SyscallError::InvalidAttribute */
231 558 : }
232 :
233 162 : soft_error:
234 162 : *_ret = ret;
235 162 : return FD_VM_SUCCESS;
236 0 : #undef MATCH_ID_OP
237 0 : #undef EDWARDS
238 0 : #undef RISTRETTO
239 :
240 18 : invalid_error:
241 : /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L1135-L1156 */
242 18 : if( FD_FEATURE_ACTIVE( (vm->instr_ctx->slot_ctx), abort_on_invalid_curve ) ) {
243 9 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_ERR_SYSCALL_INVALID_ATTRIBUTE );
244 9 : return FD_VM_ERR_INVAL; /* SyscallError::InvalidAttribute */
245 9 : }
246 9 : *_ret = 1UL;
247 9 : return FD_VM_SUCCESS;
248 18 : }
249 :
250 : /* multi_scalar_mul_edwards computes a MSM on curve25519.
251 :
252 : This function is equivalent to
253 : zk-token-sdk::edwards::multi_scalar_mul_edwards
254 :
255 : https://github.com/solana-labs/solana/blob/v1.17.7/zk-token-sdk/src/curve25519/edwards.rs#L116
256 :
257 : Specifically it takes as input byte arrays and takes care of scalars
258 : validation and points decompression. It then invokes ballet MSM
259 : function fd_ed25519_multi_scalar_mul. To avoid dynamic allocation,
260 : the full MSM is done in batches of FD_BALLET_CURVE25519_MSM_BATCH_SZ. */
261 :
262 : static fd_ed25519_point_t *
263 : multi_scalar_mul_edwards( fd_ed25519_point_t * r,
264 : uchar const * scalars,
265 : uchar const * points,
266 12 : ulong cnt ) {
267 : /* Validate all scalars first (fast) */
268 33 : for( ulong i=0UL; i<cnt; i++ ) {
269 24 : if( FD_UNLIKELY( !fd_curve25519_scalar_validate ( scalars + i*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ ) ) ) {
270 3 : return NULL;
271 3 : }
272 24 : }
273 :
274 : /* Static allocation of a batch of decompressed points */
275 9 : fd_ed25519_point_t tmp[1];
276 9 : fd_ed25519_point_t A[ FD_BALLET_CURVE25519_MSM_BATCH_SZ ];
277 :
278 9 : fd_ed25519_point_set_zero( r );
279 15 : for( ulong i=0UL; i<cnt; i+=FD_BALLET_CURVE25519_MSM_BATCH_SZ ) {
280 9 : ulong batch_cnt = fd_ulong_min( cnt-i, FD_BALLET_CURVE25519_MSM_BATCH_SZ );
281 :
282 : /* Decompress (and validate) points */
283 21 : for( ulong j=0UL; j<batch_cnt; j++ ) {
284 : //TODO: use fd_ed25519_point_frombytes_2x
285 15 : if( FD_UNLIKELY( !fd_ed25519_point_frombytes( &A[j], points + j*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ ) ) ) {
286 3 : return NULL;
287 3 : }
288 15 : }
289 :
290 6 : fd_ed25519_multi_scalar_mul( tmp, scalars, A, batch_cnt );
291 6 : fd_ed25519_point_add( r, r, tmp );
292 6 : points += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ *batch_cnt;
293 6 : scalars += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ*batch_cnt;
294 6 : }
295 :
296 6 : return r;
297 9 : }
298 :
299 : /* multi_scalar_mul_ristretto computes a MSM on ristretto255.
300 : See multi_scalar_mul_edwards for details. */
301 :
302 : static fd_ed25519_point_t *
303 : multi_scalar_mul_ristretto( fd_ristretto255_point_t * r,
304 : uchar const * scalars,
305 : uchar const * points,
306 12 : ulong cnt ) {
307 : /* Validate all scalars first (fast) */
308 33 : for( ulong i=0UL; i<cnt; i++ ) {
309 24 : if( FD_UNLIKELY( !fd_curve25519_scalar_validate ( scalars + i*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ ) ) ) {
310 3 : return NULL;
311 3 : }
312 24 : }
313 :
314 : /* Static allocation of a batch of decompressed points */
315 9 : fd_ristretto255_point_t tmp[1];
316 9 : fd_ristretto255_point_t A[ FD_BALLET_CURVE25519_MSM_BATCH_SZ ];
317 :
318 9 : fd_ristretto255_point_set_zero( r );
319 15 : for( ulong i=0UL; i<cnt; i+=FD_BALLET_CURVE25519_MSM_BATCH_SZ ) {
320 9 : ulong batch_cnt = fd_ulong_min( cnt-i, FD_BALLET_CURVE25519_MSM_BATCH_SZ );
321 :
322 : /* Decompress (and validate) points */
323 21 : for( ulong j=0UL; j<batch_cnt; j++ ) {
324 : //TODO: use fd_ristretto255_point_frombytes_2x
325 15 : if( FD_UNLIKELY( !fd_ristretto255_point_frombytes( &A[j], points + j*FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ ) ) ) {
326 3 : return NULL;
327 3 : }
328 15 : }
329 :
330 6 : fd_ristretto255_multi_scalar_mul( tmp, scalars, A, batch_cnt );
331 6 : fd_ristretto255_point_add( r, r, tmp );
332 6 : points += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_POINT_SZ *batch_cnt;
333 6 : scalars += FD_VM_SYSCALL_SOL_CURVE_CURVE25519_SCALAR_SZ*batch_cnt;
334 6 : }
335 :
336 6 : return r;
337 9 : }
338 :
339 : #undef BATCH_MAX
340 :
341 : int
342 : fd_vm_syscall_sol_curve_multiscalar_mul( void * _vm,
343 : ulong curve_id,
344 : ulong scalars_addr,
345 : ulong points_addr,
346 : ulong points_len,
347 : ulong result_point_addr,
348 63 : ulong * _ret ) {
349 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1129 */
350 63 : fd_vm_t * vm = (fd_vm_t *)_vm;
351 63 : ulong ret = 1UL; /* by default return Ok(1) == error */
352 :
353 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1143-L1151 */
354 63 : if( FD_UNLIKELY( points_len > 512 ) ) {
355 9 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_ERR_SYSCALL_INVALID_LENGTH );
356 9 : return FD_VM_ERR_INVAL; /* SyscallError::InvalidLength */
357 9 : }
358 :
359 : /* Note: we don't strictly follow the Rust implementation, but instead combine
360 : common code across switch cases. Similar to fd_vm_syscall_sol_alt_bn128_group_op. */
361 :
362 54 : ulong base_cost = 0UL;
363 54 : ulong incremental_cost = 0UL;
364 54 : switch( curve_id ) {
365 24 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS:
366 24 : base_cost = FD_VM_CURVE25519_EDWARDS_MSM_BASE_COST;
367 24 : incremental_cost = FD_VM_CURVE25519_EDWARDS_MSM_INCREMENTAL_COST;
368 24 : break;
369 :
370 21 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO:
371 21 : base_cost = FD_VM_CURVE25519_RISTRETTO_MSM_BASE_COST;
372 21 : incremental_cost = FD_VM_CURVE25519_RISTRETTO_MSM_INCREMENTAL_COST;
373 21 : break;
374 :
375 9 : default:
376 : /* https://github.com/anza-xyz/agave/blob/5b3390b99a6e7665439c623062c1a1dda2803524/programs/bpf_loader/src/syscalls/mod.rs#L1262-L1271 */
377 9 : if( FD_FEATURE_ACTIVE( (vm->instr_ctx->slot_ctx), abort_on_invalid_curve ) ) {
378 6 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_ERR_SYSCALL_INVALID_ATTRIBUTE );
379 6 : return FD_VM_ERR_INVAL; /* SyscallError::InvalidAttribute */
380 6 : }
381 3 : goto soft_error;
382 54 : }
383 :
384 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1155-L1164 */
385 45 : ulong cost = fd_ulong_sat_add(
386 45 : base_cost,
387 45 : fd_ulong_sat_mul(
388 45 : incremental_cost,
389 45 : fd_ulong_sat_sub( points_len, 1 )
390 45 : )
391 45 : );
392 45 : FD_VM_CU_UPDATE( vm, cost );
393 :
394 : /* Edge case points_len==0.
395 : Agave computes the MSM, that returns the point at infinity, and stores the result.
396 : This means that we have to mem map result, and then set the point at infinity,
397 : that is 0x0100..00 for Edwards and 0x00..00 for Ristretto. */
398 39 : if ( FD_UNLIKELY( points_len==0 ) ) {
399 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 );
400 0 : memset( result, 0, 32 );
401 0 : result[0] = curve_id==FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS ? 1 : 0;
402 0 : *_ret = 0;
403 0 : return FD_VM_SUCCESS;
404 3 : }
405 :
406 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1166-L1178 */
407 96 : 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 );
408 78 : 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 );
409 :
410 0 : switch( curve_id ) {
411 :
412 12 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_EDWARDS: {
413 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L1180-L1189 */
414 12 : fd_ed25519_point_t _r[1];
415 12 : fd_ed25519_point_t * r = multi_scalar_mul_edwards( _r, scalars, points, points_len );
416 :
417 12 : if( FD_LIKELY( r ) ) {
418 18 : 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 );
419 0 : fd_ed25519_point_tobytes( result, r );
420 18 : ret = 0UL;
421 18 : }
422 12 : break;
423 12 : }
424 :
425 12 : case FD_VM_SYSCALL_SOL_CURVE_CURVE25519_RISTRETTO: {
426 12 : fd_ristretto255_point_t _r[1];
427 12 : fd_ristretto255_point_t * r = multi_scalar_mul_ristretto( _r, scalars, points, points_len );
428 :
429 12 : if( FD_LIKELY( r ) ) {
430 18 : 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 );
431 0 : fd_ristretto255_point_tobytes( result, r );
432 18 : ret = 0UL;
433 18 : }
434 12 : break;
435 12 : }
436 :
437 12 : default:
438 : /* COV: this can never happen because of the previous switch */
439 0 : return FD_VM_ERR_INVAL; /* SyscallError::InvalidAttribute */
440 78 : }
441 :
442 27 : soft_error:
443 27 : *_ret = ret;
444 27 : return FD_VM_SUCCESS;
445 78 : }
|