Line data Source code
1 : #include "fd_vm_syscall.h"
2 :
3 : #include "../../../ballet/bn254/fd_bn254.h"
4 : #include "../../../ballet/bn254/fd_poseidon.h"
5 : #include "../../../ballet/secp256k1/fd_secp256k1.h"
6 : #include "../../runtime/fd_bank.h"
7 :
8 : int
9 : fd_vm_syscall_sol_alt_bn128_group_op( void * _vm,
10 : ulong group_op,
11 : ulong input_addr,
12 : ulong input_sz,
13 : ulong result_addr,
14 : FD_PARAM_UNUSED ulong r5,
15 0 : ulong * _ret ) {
16 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1509 */
17 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
18 0 : ulong ret = 1UL; /* by default return Ok(1) == error */
19 :
20 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1520-L1549 */
21 0 : ulong cost = 0UL;
22 0 : ulong output_sz = 0UL;
23 0 : switch( group_op ) {
24 :
25 0 : case FD_VM_SYSCALL_SOL_ALT_BN128_ADD:
26 0 : output_sz = FD_VM_SYSCALL_SOL_ALT_BN128_G1_SZ;
27 0 : cost = FD_VM_ALT_BN128_ADDITION_COST;
28 0 : break;
29 :
30 0 : case FD_VM_SYSCALL_SOL_ALT_BN128_MUL:
31 0 : output_sz = FD_VM_SYSCALL_SOL_ALT_BN128_G1_SZ;
32 0 : cost = FD_VM_ALT_BN128_MULTIPLICATION_COST;
33 0 : break;
34 :
35 0 : case FD_VM_SYSCALL_SOL_ALT_BN128_PAIRING:
36 0 : output_sz = FD_VM_SYSCALL_SOL_ALT_BN128_PAIRING_OUTPUT_SZ;
37 0 : ulong elements_len = input_sz / FD_VM_SYSCALL_SOL_ALT_BN128_PAIRING_INPUT_EL_SZ;
38 0 : cost = FD_VM_ALT_BN128_PAIRING_ONE_PAIR_COST_FIRST
39 0 : + FD_VM_SHA256_BASE_COST
40 0 : + FD_VM_SYSCALL_SOL_ALT_BN128_PAIRING_OUTPUT_SZ;
41 0 : cost = fd_ulong_sat_add( cost,
42 0 : fd_ulong_sat_mul( FD_VM_ALT_BN128_PAIRING_ONE_PAIR_COST_OTHER,
43 0 : fd_ulong_sat_sub( elements_len, 1 ) ) );
44 0 : cost = fd_ulong_sat_add( cost, input_sz );
45 0 : break;
46 :
47 0 : default:
48 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
49 0 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
50 0 : }
51 :
52 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1551 */
53 :
54 0 : FD_VM_CU_UPDATE( vm, cost );
55 :
56 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1660-L1664 */
57 :
58 0 : fd_vm_haddr_query_t call_result_query = {
59 0 : .vaddr = result_addr,
60 0 : .align = FD_VM_ALIGN_RUST_U8,
61 0 : .sz = output_sz,
62 0 : .is_slice = 1,
63 0 : };
64 :
65 0 : fd_vm_haddr_query_t * queries[] = { &call_result_query };
66 0 : FD_VM_TRANSLATE_MUT( vm, queries );
67 :
68 0 : uchar * call_result = call_result_query.haddr;
69 0 : uchar const * input = FD_VM_MEM_SLICE_HADDR_LD( vm, input_addr, FD_VM_ALIGN_RUST_U8, input_sz );
70 :
71 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1567-L1598
72 : Note: this implementation is post SIMD-0129, we only support the simplified error codes. */
73 0 : switch( group_op ) {
74 :
75 0 : case FD_VM_SYSCALL_SOL_ALT_BN128_ADD:
76 : /* Compute add */
77 0 : if( FD_LIKELY( fd_bn254_g1_add_syscall( call_result, input, input_sz )==0 ) ) {
78 0 : ret = 0UL; /* success */
79 0 : }
80 0 : break;
81 :
82 0 : case FD_VM_SYSCALL_SOL_ALT_BN128_MUL:
83 : /* Compute scalar mul */
84 0 : if( FD_LIKELY( fd_bn254_g1_scalar_mul_syscall( call_result, input, input_sz,
85 0 : FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, fix_alt_bn128_multiplication_input_length ) )==0 ) ) {
86 0 : ret = 0UL; /* success */
87 0 : }
88 0 : break;
89 :
90 0 : case FD_VM_SYSCALL_SOL_ALT_BN128_PAIRING:
91 : /* Compute pairing with length check based on feature gate.
92 : https://github.com/anza-xyz/solana-sdk/blob/bn254%40v3.1.2/bn254/src/pairing.rs#L76-L82 */
93 0 : if( FD_LIKELY( fd_bn254_pairing_is_one_syscall( call_result, input, input_sz,
94 0 : FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, fix_alt_bn128_pairing_length_check ) )==0 ) ) {
95 0 : ret = 0UL; /* success */
96 0 : }
97 0 : break;
98 0 : }
99 :
100 0 : *_ret = ret;
101 0 : return FD_VM_SUCCESS; /* Ok(SUCCESS) or Ok(ERROR) */
102 0 : }
103 :
104 : int
105 : fd_vm_syscall_sol_alt_bn128_compression( void * _vm,
106 : ulong op,
107 : ulong input_addr,
108 : ulong input_sz,
109 : ulong result_addr,
110 : FD_PARAM_UNUSED ulong r5,
111 0 : ulong * _ret ) {
112 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1776 */
113 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
114 0 : ulong ret = 1UL; /* by default return Ok(1) == error */
115 :
116 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1791-L1811 */
117 0 : ulong cost = 0UL;
118 0 : ulong output_sz = 0UL;
119 0 : switch( op ) {
120 :
121 0 : case FD_VM_SYSCALL_SOL_ALT_BN128_G1_COMPRESS:
122 0 : output_sz = FD_VM_SYSCALL_SOL_ALT_BN128_G1_COMPRESSED_SZ;
123 0 : cost = FD_VM_ALT_BN128_G1_COMPRESS;
124 0 : break;
125 :
126 0 : case FD_VM_SYSCALL_SOL_ALT_BN128_G1_DECOMPRESS:
127 0 : output_sz = FD_VM_SYSCALL_SOL_ALT_BN128_G1_SZ;
128 0 : cost = FD_VM_ALT_BN128_G1_DECOMPRESS;
129 0 : break;
130 :
131 0 : case FD_VM_SYSCALL_SOL_ALT_BN128_G2_COMPRESS:
132 0 : output_sz = FD_VM_SYSCALL_SOL_ALT_BN128_G2_COMPRESSED_SZ;
133 0 : cost = FD_VM_ALT_BN128_G2_COMPRESS;
134 0 : break;
135 :
136 0 : case FD_VM_SYSCALL_SOL_ALT_BN128_G2_DECOMPRESS:
137 0 : output_sz = FD_VM_SYSCALL_SOL_ALT_BN128_G2_SZ;
138 0 : cost = FD_VM_ALT_BN128_G2_DECOMPRESS;
139 0 : break;
140 :
141 0 : default:
142 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE );
143 0 : return FD_VM_SYSCALL_ERR_INVALID_ATTRIBUTE; /* SyscallError::InvalidAttribute */
144 0 : }
145 0 : cost = fd_ulong_sat_add( cost, FD_VM_SYSCALL_BASE_COST );
146 :
147 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1813 */
148 :
149 0 : FD_VM_CU_UPDATE( vm, cost );
150 :
151 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1815-L1827 */
152 :
153 0 : fd_vm_haddr_query_t call_result_query = {
154 0 : .vaddr = result_addr,
155 0 : .align = FD_VM_ALIGN_RUST_U8,
156 0 : .sz = output_sz,
157 0 : .is_slice = 1,
158 0 : };
159 :
160 0 : fd_vm_haddr_query_t * queries[] = { &call_result_query };
161 0 : FD_VM_TRANSLATE_MUT( vm, queries );
162 :
163 0 : uchar * call_result = call_result_query.haddr;
164 0 : void const * input = FD_VM_MEM_SLICE_HADDR_LD( vm, input_addr, FD_VM_ALIGN_RUST_U8, input_sz );
165 :
166 : /* input and call_result may alias. Therefore, buffer via out_buf */
167 0 : uchar out_buf[128];
168 :
169 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1829-L1891
170 : Note: this implementation is post SIMD-0129, we only support the simplified error codes. */
171 0 : switch( op ) {
172 :
173 0 : case FD_VM_SYSCALL_SOL_ALT_BN128_G1_COMPRESS:
174 0 : if( FD_UNLIKELY( input_sz!=FD_VM_SYSCALL_SOL_ALT_BN128_G1_SZ ) ) {
175 0 : goto soft_error;
176 0 : }
177 0 : if( FD_LIKELY( fd_bn254_g1_compress( out_buf, fd_type_pun_const(input) ) ) ) {
178 0 : fd_memcpy( call_result, out_buf, FD_VM_SYSCALL_SOL_ALT_BN128_G1_COMPRESSED_SZ );
179 0 : ret = 0UL; /* success */
180 0 : }
181 0 : break;
182 :
183 0 : case FD_VM_SYSCALL_SOL_ALT_BN128_G1_DECOMPRESS:
184 0 : if( FD_UNLIKELY( input_sz!=FD_VM_SYSCALL_SOL_ALT_BN128_G1_COMPRESSED_SZ ) ) {
185 0 : goto soft_error;
186 0 : }
187 0 : if( FD_LIKELY( fd_bn254_g1_decompress( out_buf, fd_type_pun_const(input) ) ) ) {
188 0 : fd_memcpy( call_result, out_buf, FD_VM_SYSCALL_SOL_ALT_BN128_G1_SZ );
189 0 : ret = 0UL; /* success */
190 0 : }
191 0 : break;
192 :
193 0 : case FD_VM_SYSCALL_SOL_ALT_BN128_G2_COMPRESS:
194 0 : if( FD_UNLIKELY( input_sz!=FD_VM_SYSCALL_SOL_ALT_BN128_G2_SZ ) ) {
195 0 : goto soft_error;
196 0 : }
197 0 : if( FD_LIKELY( fd_bn254_g2_compress( out_buf, fd_type_pun_const(input) ) ) ) {
198 0 : fd_memcpy( call_result, out_buf, FD_VM_SYSCALL_SOL_ALT_BN128_G2_COMPRESSED_SZ );
199 0 : ret = 0UL; /* success */
200 0 : }
201 0 : break;
202 :
203 0 : case FD_VM_SYSCALL_SOL_ALT_BN128_G2_DECOMPRESS:
204 0 : if( FD_UNLIKELY( input_sz!=FD_VM_SYSCALL_SOL_ALT_BN128_G2_COMPRESSED_SZ ) ) {
205 0 : goto soft_error;
206 0 : }
207 0 : if( FD_LIKELY( fd_bn254_g2_decompress( out_buf, fd_type_pun_const(input) ) ) ) {
208 0 : fd_memcpy( call_result, out_buf, FD_VM_SYSCALL_SOL_ALT_BN128_G2_SZ );
209 0 : ret = 0UL; /* success */
210 0 : }
211 0 : break;
212 0 : }
213 :
214 0 : soft_error:
215 0 : *_ret = ret;
216 0 : return FD_VM_SUCCESS; /* Ok(SUCCESS) or Ok(ERROR) */
217 0 : }
218 :
219 : int
220 : fd_vm_syscall_sol_poseidon( void * _vm,
221 : ulong params,
222 : ulong endianness,
223 : ulong vals_addr,
224 : ulong vals_len,
225 : ulong result_addr,
226 0 : ulong * _ret ) {
227 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1678 */
228 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
229 0 : ulong ret = 1UL; /* by default return Ok(1) == error */
230 :
231 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1688 */
232 :
233 0 : if( FD_UNLIKELY( params!=0UL ) ) {
234 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_POSEIDON_INVALID_PARAMS );
235 0 : return FD_VM_SYSCALL_ERR_POSEIDON_INVALID_PARAMS; /* PoseidonSyscallError::InvalidParameters */
236 0 : }
237 :
238 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1689 */
239 :
240 0 : if( FD_UNLIKELY(
241 0 : endianness!=0UL /* Big endian */
242 0 : && endianness!=1UL /* Little endian */
243 0 : ) ) {
244 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_POSEIDON_INVALID_ENDIANNESS );
245 0 : return FD_VM_SYSCALL_ERR_POSEIDON_INVALID_ENDIANNESS; /* PoseidonSyscallError::InvalidEndianness */
246 0 : }
247 :
248 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1691-L1698 */
249 :
250 0 : if( FD_UNLIKELY( vals_len > FD_VM_SYSCALL_SOL_POSEIDON_MAX_VALS ) ) {
251 : /* Max msg_sz = 47 - 3 + 20 = 64 < 127 => we can use printf */
252 0 : fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
253 0 : "Poseidon hashing %lu sequences is not supported", vals_len );
254 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_LENGTH );
255 0 : return FD_VM_SYSCALL_ERR_INVALID_LENGTH; /* SyscallError::InvalidLength */
256 0 : }
257 :
258 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1700-L1707
259 : poseidon_cost(): https://github.com/solana-labs/solana/blob/v1.18.12/program-runtime/src/compute_budget.rs#L211 */
260 :
261 : /* vals_len^2 * A + C */
262 0 : ulong cost = fd_ulong_sat_add(
263 0 : fd_ulong_sat_mul(
264 0 : fd_ulong_sat_mul( vals_len, vals_len ),
265 0 : FD_VM_POSEIDON_COST_COEFFICIENT_A
266 0 : ),
267 0 : FD_VM_POSEIDON_COST_COEFFICIENT_C
268 0 : );
269 :
270 : /* The following can never happen, left as comment for completeness.
271 : if( FD_UNLIKELY( cost == ULONG_MAX ) ) {
272 : fd_vm_log_append_printf( vm, "Overflow while calculating the compute cost" );
273 : return FD_VM_SYSCALL_ERR_ARITHMETIC_OVERFLOW; // SyscallError::ArithmeticOverflow
274 : }
275 : */
276 :
277 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1708 */
278 :
279 0 : FD_VM_CU_UPDATE( vm, cost );
280 :
281 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1710-L1715 */
282 :
283 0 : fd_vm_haddr_query_t hash_result_query = {
284 0 : .vaddr = result_addr,
285 0 : .align = FD_VM_ALIGN_RUST_U8,
286 0 : .sz = 32UL,
287 0 : .is_slice = 1,
288 0 : };
289 :
290 0 : fd_vm_haddr_query_t * queries[] = { &hash_result_query };
291 0 : FD_VM_TRANSLATE_MUT( vm, queries );
292 :
293 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1716-L1732 */
294 :
295 : /* Agave allocates a vector of translated slices (that can return a fatal
296 : error), and then computes Poseidon, returning a soft error in case of
297 : issues (e.g. invalid input).
298 :
299 : We must be careful in returning the correct fatal vs soft error.
300 :
301 : The special case of vals_len==0 returns Ok(1), so for simplicity
302 : we capture it explicitly. */
303 :
304 0 : if( FD_UNLIKELY( !vals_len ) ) {
305 0 : goto soft_error;
306 0 : }
307 :
308 : /* First loop to memory map. This can return a fatal error. */
309 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) );
310 0 : void const * inputs_haddr[ FD_VM_SYSCALL_SOL_POSEIDON_MAX_VALS ];
311 0 : for( ulong i=0UL; i<vals_len; i++ ) {
312 0 : inputs_haddr[i] = FD_VM_MEM_SLICE_HADDR_LD( vm, input_vec_haddr[i].addr, FD_VM_ALIGN_RUST_U8, input_vec_haddr[i].len );
313 0 : }
314 :
315 : /* https://github.com/anza-xyz/agave/blob/v1.18.12/programs/bpf_loader/src/syscalls/mod.rs#L1734-L1750
316 : Note: this implementation is post SIMD-0129, we only support the simplified error codes. */
317 :
318 : /* Second loop to computed Poseidon. This can return a soft error. */
319 0 : int big_endian = endianness==0;
320 0 : int enforce_padding = FD_FEATURE_ACTIVE_BANK( vm->instr_ctx->bank, poseidon_enforce_padding );
321 0 : fd_poseidon_t pos[1];
322 0 : fd_poseidon_init( pos, big_endian );
323 :
324 0 : for( ulong i=0UL; i<vals_len; i++ ) {
325 0 : if( FD_UNLIKELY( fd_poseidon_append( pos, inputs_haddr[ i ], input_vec_haddr[i].len, enforce_padding )==NULL ) ) {
326 0 : goto soft_error;
327 0 : }
328 0 : }
329 :
330 0 : ret = !fd_poseidon_fini( pos, hash_result_query.haddr );
331 :
332 0 : soft_error:
333 0 : *_ret = ret;
334 0 : return FD_VM_SUCCESS; /* Ok(1) == error */
335 0 : }
336 :
337 : int
338 : fd_vm_syscall_sol_secp256k1_recover( /**/ void * _vm,
339 : /**/ ulong hash_vaddr,
340 : /**/ ulong recovery_id_val,
341 : /**/ ulong signature_vaddr,
342 : /**/ ulong result_vaddr,
343 : FD_PARAM_UNUSED ulong r5,
344 0 : /**/ ulong * _ret ) {
345 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L810 */
346 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
347 :
348 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L820-L821 */
349 :
350 0 : FD_VM_CU_UPDATE( vm, FD_VM_SECP256K1_RECOVER_COST );
351 :
352 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L952-L956 */
353 0 : fd_vm_haddr_query_t pubkey_result_query = {
354 0 : .vaddr = result_vaddr,
355 0 : .align = FD_VM_ALIGN_RUST_U8,
356 0 : .sz = 64UL,
357 0 : .is_slice = 1,
358 0 : };
359 :
360 0 : fd_vm_haddr_query_t * queries[] = { &pubkey_result_query };
361 0 : FD_VM_TRANSLATE_MUT( vm, queries );
362 :
363 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L957-L968 */
364 :
365 0 : uchar const * hash = FD_VM_MEM_HADDR_LD( vm, hash_vaddr, FD_VM_ALIGN_RUST_U8, 32UL );
366 0 : uchar const * sig = FD_VM_MEM_HADDR_LD( vm, signature_vaddr, FD_VM_ALIGN_RUST_U8, 64UL );
367 :
368 : /* CRITICAL */
369 :
370 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L842-L853 */
371 :
372 : /* Secp256k1RecoverError::InvalidHash
373 : This can never happen, as `libsecp256k1::Message::parse_slice(hash)`
374 : only checks that hash is 32-byte long, and that's by construction.
375 : https://github.com/paritytech/libsecp256k1/blob/v0.6.0/src/lib.rs#L657-L665
376 :
377 : if( FD_UNLIKELY( 0 ) ) {
378 : *_ret = 1UL; // Secp256k1RecoverError::InvalidHash
379 : return FD_VM_SUCCESS;
380 : }
381 : */
382 :
383 : /* Secp256k1RecoverError::InvalidRecoveryId
384 : Agave code has 2 checks: the first is a cast from u64 to u8.
385 : The second is `libsecp256k1::RecoveryId::parse(adjusted_recover_id_val)` that
386 : checks if `adjusted_recover_id_val < 4`.
387 : https://github.com/paritytech/libsecp256k1/blob/v0.6.0/src/lib.rs#L674-L680
388 : */
389 :
390 0 : if( FD_UNLIKELY( recovery_id_val >= 4UL ) ) {
391 0 : *_ret = 2UL; /* Secp256k1RecoverError::InvalidRecoveryId */
392 0 : return FD_VM_SUCCESS;
393 0 : }
394 :
395 : /* Secp256k1RecoverError::InvalidSignature
396 : We omit this check, as this is done as part of fd_secp256k1_recover() below,
397 : and the return code is the same.
398 :
399 : In more details, this checks that the signature is valid, i.e. if the
400 : signature is represented as two scalars (r, s), it checks that both r
401 : and s are canonical scalars.
402 :
403 : Note the `?` at the end of this line:
404 : https://github.com/paritytech/libsecp256k1/blob/v0.6.0/src/lib.rs#L535
405 : And following the code, `scalar::check_overflow` is checks that the scalar is valid:
406 : https://github.com/paritytech/libsecp256k1/blob/master/core/src/scalar.rs#L70-L87 */
407 :
408 : /* https://github.com/anza-xyz/agave/blob/v1.18.8/programs/bpf_loader/src/syscalls/mod.rs#L855-L860 */
409 :
410 0 : uchar secp256k1_pubkey[64];
411 0 : if( FD_UNLIKELY( !fd_secp256k1_recover( secp256k1_pubkey, hash, sig, (int)recovery_id_val ) ) ) {
412 0 : *_ret = 3UL; /* Secp256k1RecoverError::InvalidSignature */
413 0 : return FD_VM_SUCCESS;
414 0 : }
415 :
416 0 : memcpy( pubkey_result_query.haddr, secp256k1_pubkey, 64UL );
417 :
418 0 : *_ret = 0UL;
419 0 : return FD_VM_SUCCESS;
420 0 : }
|