leo_ast/interpreter_value/
core_function.rs

1// Copyright (C) 2019-2025 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use crate::{
18    CoreFunction,
19    Expression,
20    halt,
21    interpreter_value::{Value, util::ExpectTc},
22    tc_fail,
23};
24use leo_errors::{InterpreterHalt, Result};
25use leo_span::{Span, Symbol};
26
27use snarkvm::prelude::{CastLossy as _, Network as _, TestnetV0, ToBits};
28
29use rand::Rng as _;
30use rand_chacha::ChaCha20Rng;
31use std::collections::HashMap;
32
33/// A context in which we can evaluate core functions.
34///
35/// This is intended to be implemented by `Cursor`, which will be used during
36/// execution of the interpreter, and by `Vec<Value>`, which will be used
37/// during compile time evaluation for constant folding.
38///
39/// The default implementations for `rng`, `set_block_height`, and mapping lookup
40/// do nothing, as those features will not be available during compile time
41/// evaluation.
42pub trait CoreFunctionHelper {
43    fn pop_value_impl(&mut self) -> Option<Value>;
44
45    fn pop_value(&mut self) -> Result<Value> {
46        match self.pop_value_impl() {
47            Some(v) => Ok(v),
48            None => {
49                Err(InterpreterHalt::new("value expected - this may be a bug in the Leo interpreter".to_string())
50                    .into())
51            }
52        }
53    }
54
55    fn set_block_height(&mut self, _height: u32) {}
56
57    fn lookup_mapping(&self, _program: Option<Symbol>, _name: Symbol) -> Option<&HashMap<Value, Value>> {
58        None
59    }
60
61    fn lookup_mapping_mut(&mut self, _program: Option<Symbol>, _name: Symbol) -> Option<&mut HashMap<Value, Value>> {
62        None
63    }
64
65    fn rng(&mut self) -> Option<&mut ChaCha20Rng> {
66        None
67    }
68}
69
70impl CoreFunctionHelper for Vec<Value> {
71    fn pop_value_impl(&mut self) -> Option<Value> {
72        self.pop()
73    }
74}
75
76pub fn evaluate_core_function(
77    helper: &mut dyn CoreFunctionHelper,
78    core_function: CoreFunction,
79    arguments: &[Expression],
80    span: Span,
81) -> Result<Option<Value>> {
82    macro_rules! apply {
83        ($func: expr, $value: ident, $to: ident) => {{
84            let v = helper.pop_value()?;
85            let bits = v.$to();
86            Value::$value($func(&bits).expect_tc(span)?)
87        }};
88    }
89
90    macro_rules! apply_cast {
91        ($func: expr, $value: ident, $to: ident) => {{
92            let v = helper.pop_value()?;
93            let bits = v.$to();
94            let group = $func(&bits).expect_tc(span)?;
95            let x = group.to_x_coordinate();
96            Value::$value(x.cast_lossy())
97        }};
98    }
99
100    macro_rules! apply_cast_int {
101        ($func: expr, $value: ident, $int_ty: ident, $to: ident) => {{
102            let v = helper.pop_value()?;
103            let bits = v.$to();
104            let group = $func(&bits).expect_tc(span)?;
105            let x = group.to_x_coordinate();
106            let bits = x.to_bits_le();
107            let mut result: $int_ty = 0;
108            for bit in 0..std::cmp::min($int_ty::BITS as usize, bits.len()) {
109                let setbit = (if bits[bit] { 1 } else { 0 }) << bit;
110                result |= setbit;
111            }
112            Value::$value(result)
113        }};
114    }
115
116    macro_rules! apply_cast2 {
117        ($func: expr, $value: ident) => {{
118            let Value::Scalar(randomizer) = helper.pop_value()? else {
119                tc_fail!();
120            };
121            let v = helper.pop_value()?;
122            let bits = v.to_bits_le();
123            let group = $func(&bits, &randomizer).expect_tc(span)?;
124            let x = group.to_x_coordinate();
125            Value::$value(x.cast_lossy())
126        }};
127    }
128
129    macro_rules! maybe_gen {
130        () => {
131            if let Some(rng) = helper.rng() {
132                rng.r#gen()
133            } else {
134                return Ok(None);
135            }
136        };
137    }
138
139    let value = match core_function {
140        CoreFunction::BHP256CommitToAddress => {
141            apply_cast2!(TestnetV0::commit_to_group_bhp256, Address)
142        }
143        CoreFunction::BHP256CommitToField => {
144            apply_cast2!(TestnetV0::commit_to_group_bhp256, Field)
145        }
146        CoreFunction::BHP256CommitToGroup => {
147            apply_cast2!(TestnetV0::commit_to_group_bhp256, Group)
148        }
149        CoreFunction::BHP256HashToAddress => {
150            apply_cast!(TestnetV0::hash_to_group_bhp256, Address, to_bits_le)
151        }
152        CoreFunction::BHP256HashToField => apply!(TestnetV0::hash_bhp256, Field, to_bits_le),
153        CoreFunction::BHP256HashToGroup => apply!(TestnetV0::hash_to_group_bhp256, Group, to_bits_le),
154        CoreFunction::BHP256HashToI8 => {
155            apply_cast_int!(TestnetV0::hash_to_group_bhp256, I8, i8, to_bits_le)
156        }
157        CoreFunction::BHP256HashToI16 => {
158            apply_cast_int!(TestnetV0::hash_to_group_bhp256, I16, i16, to_bits_le)
159        }
160        CoreFunction::BHP256HashToI32 => {
161            apply_cast_int!(TestnetV0::hash_to_group_bhp256, I32, i32, to_bits_le)
162        }
163        CoreFunction::BHP256HashToI64 => {
164            apply_cast_int!(TestnetV0::hash_to_group_bhp256, I64, i64, to_bits_le)
165        }
166        CoreFunction::BHP256HashToI128 => {
167            apply_cast_int!(TestnetV0::hash_to_group_bhp256, I128, i128, to_bits_le)
168        }
169        CoreFunction::BHP256HashToU8 => {
170            apply_cast_int!(TestnetV0::hash_to_group_bhp256, U8, u8, to_bits_le)
171        }
172        CoreFunction::BHP256HashToU16 => {
173            apply_cast_int!(TestnetV0::hash_to_group_bhp256, U16, u16, to_bits_le)
174        }
175        CoreFunction::BHP256HashToU32 => {
176            apply_cast_int!(TestnetV0::hash_to_group_bhp256, U32, u32, to_bits_le)
177        }
178        CoreFunction::BHP256HashToU64 => {
179            apply_cast_int!(TestnetV0::hash_to_group_bhp256, U64, u64, to_bits_le)
180        }
181        CoreFunction::BHP256HashToU128 => {
182            apply_cast_int!(TestnetV0::hash_to_group_bhp256, U128, u128, to_bits_le)
183        }
184        CoreFunction::BHP256HashToScalar => {
185            apply_cast!(TestnetV0::hash_to_group_bhp256, Scalar, to_bits_le)
186        }
187        CoreFunction::BHP512CommitToAddress => {
188            apply_cast2!(TestnetV0::commit_to_group_bhp512, Address)
189        }
190        CoreFunction::BHP512CommitToField => {
191            apply_cast2!(TestnetV0::commit_to_group_bhp512, Field)
192        }
193        CoreFunction::BHP512CommitToGroup => {
194            apply_cast2!(TestnetV0::commit_to_group_bhp512, Group)
195        }
196        CoreFunction::BHP512HashToAddress => {
197            apply_cast!(TestnetV0::hash_to_group_bhp512, Address, to_bits_le)
198        }
199        CoreFunction::BHP512HashToField => apply!(TestnetV0::hash_bhp512, Field, to_bits_le),
200        CoreFunction::BHP512HashToGroup => apply!(TestnetV0::hash_to_group_bhp512, Group, to_bits_le),
201        CoreFunction::BHP512HashToI8 => {
202            apply_cast_int!(TestnetV0::hash_to_group_bhp512, I8, i8, to_bits_le)
203        }
204        CoreFunction::BHP512HashToI16 => {
205            apply_cast_int!(TestnetV0::hash_to_group_bhp512, I16, i16, to_bits_le)
206        }
207        CoreFunction::BHP512HashToI32 => {
208            apply_cast_int!(TestnetV0::hash_to_group_bhp512, I32, i32, to_bits_le)
209        }
210        CoreFunction::BHP512HashToI64 => {
211            apply_cast_int!(TestnetV0::hash_to_group_bhp512, I64, i64, to_bits_le)
212        }
213        CoreFunction::BHP512HashToI128 => {
214            apply_cast_int!(TestnetV0::hash_to_group_bhp512, I128, i128, to_bits_le)
215        }
216        CoreFunction::BHP512HashToU8 => {
217            apply_cast_int!(TestnetV0::hash_to_group_bhp512, U8, u8, to_bits_le)
218        }
219        CoreFunction::BHP512HashToU16 => {
220            apply_cast_int!(TestnetV0::hash_to_group_bhp512, U16, u16, to_bits_le)
221        }
222        CoreFunction::BHP512HashToU32 => {
223            apply_cast_int!(TestnetV0::hash_to_group_bhp512, U32, u32, to_bits_le)
224        }
225        CoreFunction::BHP512HashToU64 => {
226            apply_cast_int!(TestnetV0::hash_to_group_bhp512, U64, u64, to_bits_le)
227        }
228        CoreFunction::BHP512HashToU128 => {
229            apply_cast_int!(TestnetV0::hash_to_group_bhp512, U128, u128, to_bits_le)
230        }
231        CoreFunction::BHP512HashToScalar => {
232            apply_cast!(TestnetV0::hash_to_group_bhp512, Scalar, to_bits_le)
233        }
234        CoreFunction::BHP768CommitToAddress => {
235            apply_cast2!(TestnetV0::commit_to_group_bhp768, Address)
236        }
237        CoreFunction::BHP768CommitToField => {
238            apply_cast2!(TestnetV0::commit_to_group_bhp768, Field)
239        }
240        CoreFunction::BHP768CommitToGroup => {
241            apply_cast2!(TestnetV0::commit_to_group_bhp768, Group)
242        }
243        CoreFunction::BHP768HashToAddress => {
244            apply_cast!(TestnetV0::hash_to_group_bhp768, Address, to_bits_le)
245        }
246        CoreFunction::BHP768HashToField => apply!(TestnetV0::hash_bhp768, Field, to_bits_le),
247        CoreFunction::BHP768HashToGroup => apply!(TestnetV0::hash_to_group_bhp768, Group, to_bits_le),
248        CoreFunction::BHP768HashToI8 => {
249            apply_cast_int!(TestnetV0::hash_to_group_bhp768, I8, i8, to_bits_le)
250        }
251        CoreFunction::BHP768HashToI16 => {
252            apply_cast_int!(TestnetV0::hash_to_group_bhp768, I16, i16, to_bits_le)
253        }
254        CoreFunction::BHP768HashToI32 => {
255            apply_cast_int!(TestnetV0::hash_to_group_bhp768, I32, i32, to_bits_le)
256        }
257        CoreFunction::BHP768HashToI64 => {
258            apply_cast_int!(TestnetV0::hash_to_group_bhp768, I64, i64, to_bits_le)
259        }
260        CoreFunction::BHP768HashToI128 => {
261            apply_cast_int!(TestnetV0::hash_to_group_bhp768, I128, i128, to_bits_le)
262        }
263        CoreFunction::BHP768HashToU8 => {
264            apply_cast_int!(TestnetV0::hash_to_group_bhp768, U8, u8, to_bits_le)
265        }
266        CoreFunction::BHP768HashToU16 => {
267            apply_cast_int!(TestnetV0::hash_to_group_bhp768, U16, u16, to_bits_le)
268        }
269        CoreFunction::BHP768HashToU32 => {
270            apply_cast_int!(TestnetV0::hash_to_group_bhp768, U32, u32, to_bits_le)
271        }
272        CoreFunction::BHP768HashToU64 => {
273            apply_cast_int!(TestnetV0::hash_to_group_bhp768, U64, u64, to_bits_le)
274        }
275        CoreFunction::BHP768HashToU128 => {
276            apply_cast_int!(TestnetV0::hash_to_group_bhp768, U128, u128, to_bits_le)
277        }
278        CoreFunction::BHP768HashToScalar => {
279            apply_cast!(TestnetV0::hash_to_group_bhp768, Scalar, to_bits_le)
280        }
281        CoreFunction::BHP1024CommitToAddress => {
282            apply_cast2!(TestnetV0::commit_to_group_bhp1024, Address)
283        }
284        CoreFunction::BHP1024CommitToField => {
285            apply_cast2!(TestnetV0::commit_to_group_bhp1024, Field)
286        }
287        CoreFunction::BHP1024CommitToGroup => {
288            apply_cast2!(TestnetV0::commit_to_group_bhp1024, Group)
289        }
290        CoreFunction::BHP1024HashToAddress => {
291            apply_cast!(TestnetV0::hash_to_group_bhp1024, Address, to_bits_le)
292        }
293        CoreFunction::BHP1024HashToField => apply!(TestnetV0::hash_bhp1024, Field, to_bits_le),
294        CoreFunction::BHP1024HashToGroup => apply!(TestnetV0::hash_to_group_bhp1024, Group, to_bits_le),
295        CoreFunction::BHP1024HashToI8 => {
296            apply_cast_int!(TestnetV0::hash_to_group_bhp1024, I8, i8, to_bits_le)
297        }
298        CoreFunction::BHP1024HashToI16 => {
299            apply_cast_int!(TestnetV0::hash_to_group_bhp1024, I16, i16, to_bits_le)
300        }
301        CoreFunction::BHP1024HashToI32 => {
302            apply_cast_int!(TestnetV0::hash_to_group_bhp1024, I32, i32, to_bits_le)
303        }
304        CoreFunction::BHP1024HashToI64 => {
305            apply_cast_int!(TestnetV0::hash_to_group_bhp1024, I64, i64, to_bits_le)
306        }
307        CoreFunction::BHP1024HashToI128 => {
308            apply_cast_int!(TestnetV0::hash_to_group_bhp1024, I128, i128, to_bits_le)
309        }
310        CoreFunction::BHP1024HashToU8 => {
311            apply_cast_int!(TestnetV0::hash_to_group_bhp1024, U8, u8, to_bits_le)
312        }
313        CoreFunction::BHP1024HashToU16 => {
314            apply_cast_int!(TestnetV0::hash_to_group_bhp1024, U16, u16, to_bits_le)
315        }
316        CoreFunction::BHP1024HashToU32 => {
317            apply_cast_int!(TestnetV0::hash_to_group_bhp1024, U32, u32, to_bits_le)
318        }
319        CoreFunction::BHP1024HashToU64 => {
320            apply_cast_int!(TestnetV0::hash_to_group_bhp1024, U64, u64, to_bits_le)
321        }
322        CoreFunction::BHP1024HashToU128 => {
323            apply_cast_int!(TestnetV0::hash_to_group_bhp1024, U128, u128, to_bits_le)
324        }
325        CoreFunction::BHP1024HashToScalar => {
326            apply_cast!(TestnetV0::hash_to_group_bhp1024, Scalar, to_bits_le)
327        }
328        CoreFunction::Keccak256HashToAddress => apply_cast!(
329            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_keccak256(v).expect_tc(span)?),
330            Address,
331            to_bits_le
332        ),
333        CoreFunction::Keccak256HashToField => apply_cast!(
334            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_keccak256(v).expect_tc(span)?),
335            Field,
336            to_bits_le
337        ),
338        CoreFunction::Keccak256HashToGroup => {
339            apply!(
340                |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_keccak256(v).expect_tc(span)?),
341                Group,
342                to_bits_le
343            )
344        }
345        CoreFunction::Keccak256HashToI8 => apply_cast_int!(
346            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_keccak256(v).expect_tc(span)?),
347            I8,
348            i8,
349            to_bits_le
350        ),
351        CoreFunction::Keccak256HashToI16 => apply_cast_int!(
352            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_keccak256(v).expect_tc(span)?),
353            I16,
354            i16,
355            to_bits_le
356        ),
357
358        CoreFunction::Keccak256HashToI32 => apply_cast_int!(
359            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_keccak256(v).expect_tc(span)?),
360            I32,
361            i32,
362            to_bits_le
363        ),
364        CoreFunction::Keccak256HashToI64 => apply_cast_int!(
365            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_keccak256(v).expect_tc(span)?),
366            I64,
367            i64,
368            to_bits_le
369        ),
370        CoreFunction::Keccak256HashToI128 => apply_cast_int!(
371            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_keccak256(v).expect_tc(span)?),
372            I128,
373            i128,
374            to_bits_le
375        ),
376        CoreFunction::Keccak256HashToU8 => apply_cast_int!(
377            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_keccak256(v).expect_tc(span)?),
378            U8,
379            u8,
380            to_bits_le
381        ),
382        CoreFunction::Keccak256HashToU16 => apply_cast_int!(
383            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_keccak256(v).expect_tc(span)?),
384            U16,
385            u16,
386            to_bits_le
387        ),
388        CoreFunction::Keccak256HashToU32 => apply_cast_int!(
389            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_keccak256(v).expect_tc(span)?),
390            U32,
391            u32,
392            to_bits_le
393        ),
394        CoreFunction::Keccak256HashToU64 => apply_cast_int!(
395            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_keccak256(v).expect_tc(span)?),
396            U64,
397            u64,
398            to_bits_le
399        ),
400        CoreFunction::Keccak256HashToU128 => apply_cast_int!(
401            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_keccak256(v).expect_tc(span)?),
402            U128,
403            u128,
404            to_bits_le
405        ),
406        CoreFunction::Keccak256HashToScalar => apply_cast!(
407            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_keccak256(v).expect_tc(span)?),
408            Scalar,
409            to_bits_le
410        ),
411        CoreFunction::Keccak384HashToAddress => apply_cast!(
412            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak384(v).expect_tc(span)?),
413            Address,
414            to_bits_le
415        ),
416        CoreFunction::Keccak384HashToField => apply_cast!(
417            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak384(v).expect_tc(span)?),
418            Field,
419            to_bits_le
420        ),
421        CoreFunction::Keccak384HashToGroup => {
422            apply!(
423                |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak384(v).expect_tc(span)?),
424                Group,
425                to_bits_le
426            )
427        }
428        CoreFunction::Keccak384HashToI8 => apply_cast_int!(
429            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak384(v).expect_tc(span)?),
430            I8,
431            i8,
432            to_bits_le
433        ),
434        CoreFunction::Keccak384HashToI16 => apply_cast_int!(
435            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak384(v).expect_tc(span)?),
436            I16,
437            i16,
438            to_bits_le
439        ),
440        CoreFunction::Keccak384HashToI32 => apply_cast_int!(
441            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak384(v).expect_tc(span)?),
442            I32,
443            i32,
444            to_bits_le
445        ),
446        CoreFunction::Keccak384HashToI64 => apply_cast_int!(
447            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak384(v).expect_tc(span)?),
448            I64,
449            i64,
450            to_bits_le
451        ),
452        CoreFunction::Keccak384HashToI128 => apply_cast_int!(
453            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak384(v).expect_tc(span)?),
454            I128,
455            i128,
456            to_bits_le
457        ),
458        CoreFunction::Keccak384HashToU8 => apply_cast_int!(
459            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak384(v).expect_tc(span)?),
460            U8,
461            u8,
462            to_bits_le
463        ),
464        CoreFunction::Keccak384HashToU16 => apply_cast_int!(
465            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak384(v).expect_tc(span)?),
466            U16,
467            u16,
468            to_bits_le
469        ),
470        CoreFunction::Keccak384HashToU32 => apply_cast_int!(
471            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak384(v).expect_tc(span)?),
472            U32,
473            u32,
474            to_bits_le
475        ),
476        CoreFunction::Keccak384HashToU64 => apply_cast_int!(
477            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak384(v).expect_tc(span)?),
478            U64,
479            u64,
480            to_bits_le
481        ),
482        CoreFunction::Keccak384HashToU128 => apply_cast_int!(
483            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak384(v).expect_tc(span)?),
484            U128,
485            u128,
486            to_bits_le
487        ),
488        CoreFunction::Keccak384HashToScalar => apply_cast!(
489            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak384(v).expect_tc(span)?),
490            Scalar,
491            to_bits_le
492        ),
493        CoreFunction::Keccak512HashToAddress => apply_cast!(
494            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak512(v).expect_tc(span)?),
495            Address,
496            to_bits_le
497        ),
498        CoreFunction::Keccak512HashToField => apply_cast!(
499            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak512(v).expect_tc(span)?),
500            Field,
501            to_bits_le
502        ),
503        CoreFunction::Keccak512HashToGroup => {
504            apply!(
505                |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak512(v).expect_tc(span)?),
506                Group,
507                to_bits_le
508            )
509        }
510        CoreFunction::Keccak512HashToI8 => apply_cast_int!(
511            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak512(v).expect_tc(span)?),
512            I8,
513            i8,
514            to_bits_le
515        ),
516        CoreFunction::Keccak512HashToI16 => apply_cast_int!(
517            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak512(v).expect_tc(span)?),
518            I16,
519            i16,
520            to_bits_le
521        ),
522        CoreFunction::Keccak512HashToI32 => apply_cast_int!(
523            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak512(v).expect_tc(span)?),
524            I32,
525            i32,
526            to_bits_le
527        ),
528        CoreFunction::Keccak512HashToI64 => apply_cast_int!(
529            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak512(v).expect_tc(span)?),
530            I64,
531            i64,
532            to_bits_le
533        ),
534        CoreFunction::Keccak512HashToI128 => apply_cast_int!(
535            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak512(v).expect_tc(span)?),
536            I128,
537            i128,
538            to_bits_le
539        ),
540        CoreFunction::Keccak512HashToU8 => apply_cast_int!(
541            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak512(v).expect_tc(span)?),
542            U8,
543            u8,
544            to_bits_le
545        ),
546        CoreFunction::Keccak512HashToU16 => apply_cast_int!(
547            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak512(v).expect_tc(span)?),
548            U16,
549            u16,
550            to_bits_le
551        ),
552        CoreFunction::Keccak512HashToU32 => apply_cast_int!(
553            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak512(v).expect_tc(span)?),
554            U32,
555            u32,
556            to_bits_le
557        ),
558        CoreFunction::Keccak512HashToU64 => apply_cast_int!(
559            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak512(v).expect_tc(span)?),
560            U64,
561            u64,
562            to_bits_le
563        ),
564        CoreFunction::Keccak512HashToU128 => apply_cast_int!(
565            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak512(v).expect_tc(span)?),
566            U128,
567            u128,
568            to_bits_le
569        ),
570        CoreFunction::Keccak512HashToScalar => apply_cast!(
571            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_keccak512(v).expect_tc(span)?),
572            Scalar,
573            to_bits_le
574        ),
575        CoreFunction::Pedersen64CommitToAddress => {
576            apply_cast2!(TestnetV0::commit_to_group_ped64, Address)
577        }
578        CoreFunction::Pedersen64CommitToField => {
579            apply_cast2!(TestnetV0::commit_to_group_ped64, Field)
580        }
581        CoreFunction::Pedersen64CommitToGroup => {
582            apply_cast2!(TestnetV0::commit_to_group_ped64, Group)
583        }
584        CoreFunction::Pedersen64HashToAddress => {
585            apply_cast!(TestnetV0::hash_to_group_ped64, Address, to_bits_le)
586        }
587        CoreFunction::Pedersen64HashToField => apply!(TestnetV0::hash_ped64, Field, to_bits_le),
588        CoreFunction::Pedersen64HashToGroup => apply!(TestnetV0::hash_to_group_ped64, Group, to_bits_le),
589        CoreFunction::Pedersen64HashToI8 => {
590            apply_cast_int!(TestnetV0::hash_to_group_ped64, I8, i8, to_bits_le)
591        }
592        CoreFunction::Pedersen64HashToI16 => {
593            apply_cast_int!(TestnetV0::hash_to_group_ped64, I16, i16, to_bits_le)
594        }
595        CoreFunction::Pedersen64HashToI32 => {
596            apply_cast_int!(TestnetV0::hash_to_group_ped64, I32, i32, to_bits_le)
597        }
598        CoreFunction::Pedersen64HashToI64 => {
599            apply_cast_int!(TestnetV0::hash_to_group_ped64, I64, i64, to_bits_le)
600        }
601        CoreFunction::Pedersen64HashToI128 => {
602            apply_cast_int!(TestnetV0::hash_to_group_ped64, I128, i128, to_bits_le)
603        }
604        CoreFunction::Pedersen64HashToU8 => {
605            apply_cast_int!(TestnetV0::hash_to_group_ped64, U8, u8, to_bits_le)
606        }
607        CoreFunction::Pedersen64HashToU16 => {
608            apply_cast_int!(TestnetV0::hash_to_group_ped64, U16, u16, to_bits_le)
609        }
610        CoreFunction::Pedersen64HashToU32 => {
611            apply_cast_int!(TestnetV0::hash_to_group_ped64, U32, u32, to_bits_le)
612        }
613        CoreFunction::Pedersen64HashToU64 => {
614            apply_cast_int!(TestnetV0::hash_to_group_ped64, U64, u64, to_bits_le)
615        }
616        CoreFunction::Pedersen64HashToU128 => {
617            apply_cast_int!(TestnetV0::hash_to_group_ped64, U128, u128, to_bits_le)
618        }
619        CoreFunction::Pedersen64HashToScalar => {
620            apply_cast!(TestnetV0::hash_to_group_ped64, Scalar, to_bits_le)
621        }
622        CoreFunction::Pedersen128HashToAddress => {
623            apply_cast!(TestnetV0::hash_to_group_ped128, Address, to_bits_le)
624        }
625        CoreFunction::Pedersen128HashToField => {
626            apply_cast!(TestnetV0::hash_to_group_ped128, Field, to_bits_le)
627        }
628        CoreFunction::Pedersen128HashToGroup => {
629            apply_cast!(TestnetV0::hash_to_group_ped128, Group, to_bits_le)
630        }
631        CoreFunction::Pedersen128HashToI8 => {
632            apply_cast_int!(TestnetV0::hash_to_group_ped128, I8, i8, to_bits_le)
633        }
634        CoreFunction::Pedersen128HashToI16 => {
635            apply_cast_int!(TestnetV0::hash_to_group_ped64, I16, i16, to_bits_le)
636        }
637        CoreFunction::Pedersen128HashToI32 => {
638            apply_cast_int!(TestnetV0::hash_to_group_ped128, I32, i32, to_bits_le)
639        }
640        CoreFunction::Pedersen128HashToI64 => {
641            apply_cast_int!(TestnetV0::hash_to_group_ped64, I64, i64, to_bits_le)
642        }
643        CoreFunction::Pedersen128HashToI128 => {
644            apply_cast_int!(TestnetV0::hash_to_group_ped128, I128, i128, to_bits_le)
645        }
646        CoreFunction::Pedersen128HashToU8 => {
647            apply_cast_int!(TestnetV0::hash_to_group_ped128, U8, u8, to_bits_le)
648        }
649        CoreFunction::Pedersen128HashToU16 => {
650            apply_cast_int!(TestnetV0::hash_to_group_ped64, U16, u16, to_bits_le)
651        }
652        CoreFunction::Pedersen128HashToU32 => {
653            apply_cast_int!(TestnetV0::hash_to_group_ped128, U32, u32, to_bits_le)
654        }
655        CoreFunction::Pedersen128HashToU64 => {
656            apply_cast_int!(TestnetV0::hash_to_group_ped64, U64, u64, to_bits_le)
657        }
658        CoreFunction::Pedersen128HashToU128 => {
659            apply_cast_int!(TestnetV0::hash_to_group_ped128, U128, u128, to_bits_le)
660        }
661        CoreFunction::Pedersen128HashToScalar => {
662            apply_cast!(TestnetV0::hash_to_group_ped128, Scalar, to_bits_le)
663        }
664        CoreFunction::Pedersen128CommitToAddress => {
665            apply_cast2!(TestnetV0::commit_to_group_ped128, Address)
666        }
667        CoreFunction::Pedersen128CommitToField => {
668            apply_cast2!(TestnetV0::commit_to_group_ped128, Field)
669        }
670        CoreFunction::Pedersen128CommitToGroup => {
671            apply_cast2!(TestnetV0::commit_to_group_ped128, Group)
672        }
673        CoreFunction::Poseidon2HashToAddress => {
674            apply_cast!(TestnetV0::hash_to_group_psd2, Address, to_fields)
675        }
676        CoreFunction::Poseidon2HashToField => {
677            apply!(TestnetV0::hash_psd2, Field, to_fields)
678        }
679        CoreFunction::Poseidon2HashToGroup => {
680            apply_cast!(TestnetV0::hash_to_group_psd2, Group, to_fields)
681        }
682        CoreFunction::Poseidon2HashToI8 => {
683            apply_cast_int!(TestnetV0::hash_to_group_psd2, I8, i8, to_fields)
684        }
685        CoreFunction::Poseidon2HashToI16 => {
686            apply_cast_int!(TestnetV0::hash_to_group_psd2, I16, i16, to_fields)
687        }
688        CoreFunction::Poseidon2HashToI32 => {
689            apply_cast_int!(TestnetV0::hash_to_group_psd2, I32, i32, to_fields)
690        }
691        CoreFunction::Poseidon2HashToI64 => {
692            apply_cast_int!(TestnetV0::hash_to_group_psd2, I64, i64, to_fields)
693        }
694        CoreFunction::Poseidon2HashToI128 => {
695            apply_cast_int!(TestnetV0::hash_to_group_psd2, I128, i128, to_fields)
696        }
697        CoreFunction::Poseidon2HashToU8 => {
698            apply_cast_int!(TestnetV0::hash_to_group_psd2, U8, u8, to_fields)
699        }
700        CoreFunction::Poseidon2HashToU16 => {
701            apply_cast_int!(TestnetV0::hash_to_group_psd2, U16, u16, to_fields)
702        }
703        CoreFunction::Poseidon2HashToU32 => {
704            apply_cast_int!(TestnetV0::hash_to_group_psd2, U32, u32, to_fields)
705        }
706        CoreFunction::Poseidon2HashToU64 => {
707            apply_cast_int!(TestnetV0::hash_to_group_psd2, U64, u64, to_fields)
708        }
709        CoreFunction::Poseidon2HashToU128 => {
710            apply_cast_int!(TestnetV0::hash_to_group_psd2, U128, u128, to_fields)
711        }
712        CoreFunction::Poseidon2HashToScalar => {
713            apply_cast!(TestnetV0::hash_to_group_psd4, Scalar, to_fields)
714        }
715        CoreFunction::Poseidon4HashToAddress => {
716            apply_cast!(TestnetV0::hash_to_group_psd4, Address, to_fields)
717        }
718        CoreFunction::Poseidon4HashToField => {
719            apply!(TestnetV0::hash_psd4, Field, to_fields)
720        }
721        CoreFunction::Poseidon4HashToGroup => {
722            apply_cast!(TestnetV0::hash_to_group_psd4, Group, to_fields)
723        }
724        CoreFunction::Poseidon4HashToI8 => {
725            apply_cast_int!(TestnetV0::hash_to_group_psd4, I8, i8, to_fields)
726        }
727        CoreFunction::Poseidon4HashToI16 => {
728            apply_cast_int!(TestnetV0::hash_to_group_psd4, I16, i16, to_fields)
729        }
730        CoreFunction::Poseidon4HashToI32 => {
731            apply_cast_int!(TestnetV0::hash_to_group_psd4, I32, i32, to_fields)
732        }
733        CoreFunction::Poseidon4HashToI64 => {
734            apply_cast_int!(TestnetV0::hash_to_group_psd4, I64, i64, to_fields)
735        }
736        CoreFunction::Poseidon4HashToI128 => {
737            apply_cast_int!(TestnetV0::hash_to_group_psd4, I128, i128, to_fields)
738        }
739        CoreFunction::Poseidon4HashToU8 => {
740            apply_cast_int!(TestnetV0::hash_to_group_psd4, U8, u8, to_fields)
741        }
742        CoreFunction::Poseidon4HashToU16 => {
743            apply_cast_int!(TestnetV0::hash_to_group_psd4, U16, u16, to_fields)
744        }
745        CoreFunction::Poseidon4HashToU32 => {
746            apply_cast_int!(TestnetV0::hash_to_group_psd4, U32, u32, to_fields)
747        }
748        CoreFunction::Poseidon4HashToU64 => {
749            apply_cast_int!(TestnetV0::hash_to_group_psd4, U64, u64, to_fields)
750        }
751        CoreFunction::Poseidon4HashToU128 => {
752            apply_cast_int!(TestnetV0::hash_to_group_psd4, U128, u128, to_fields)
753        }
754        CoreFunction::Poseidon4HashToScalar => {
755            apply_cast!(TestnetV0::hash_to_group_psd4, Scalar, to_fields)
756        }
757        CoreFunction::Poseidon8HashToAddress => {
758            apply_cast!(TestnetV0::hash_to_group_psd8, Address, to_fields)
759        }
760        CoreFunction::Poseidon8HashToField => {
761            apply!(TestnetV0::hash_psd8, Field, to_fields)
762        }
763        CoreFunction::Poseidon8HashToGroup => {
764            apply_cast!(TestnetV0::hash_to_group_psd8, Group, to_fields)
765        }
766        CoreFunction::Poseidon8HashToI8 => {
767            apply_cast_int!(TestnetV0::hash_to_group_psd8, I8, i8, to_fields)
768        }
769        CoreFunction::Poseidon8HashToI16 => {
770            apply_cast_int!(TestnetV0::hash_to_group_psd8, I16, i16, to_fields)
771        }
772        CoreFunction::Poseidon8HashToI32 => {
773            apply_cast_int!(TestnetV0::hash_to_group_psd8, I32, i32, to_fields)
774        }
775        CoreFunction::Poseidon8HashToI64 => {
776            apply_cast_int!(TestnetV0::hash_to_group_psd8, I64, i64, to_fields)
777        }
778        CoreFunction::Poseidon8HashToI128 => {
779            apply_cast_int!(TestnetV0::hash_to_group_psd8, I128, i128, to_fields)
780        }
781        CoreFunction::Poseidon8HashToU8 => {
782            apply_cast_int!(TestnetV0::hash_to_group_psd8, U8, u8, to_fields)
783        }
784        CoreFunction::Poseidon8HashToU16 => {
785            apply_cast_int!(TestnetV0::hash_to_group_psd8, U16, u16, to_fields)
786        }
787        CoreFunction::Poseidon8HashToU32 => {
788            apply_cast_int!(TestnetV0::hash_to_group_psd8, U32, u32, to_fields)
789        }
790        CoreFunction::Poseidon8HashToU64 => {
791            apply_cast_int!(TestnetV0::hash_to_group_psd8, U64, u64, to_fields)
792        }
793        CoreFunction::Poseidon8HashToU128 => {
794            apply_cast_int!(TestnetV0::hash_to_group_psd8, U128, u128, to_fields)
795        }
796        CoreFunction::Poseidon8HashToScalar => {
797            apply_cast!(TestnetV0::hash_to_group_psd8, Scalar, to_fields)
798        }
799        CoreFunction::SHA3_256HashToAddress => apply_cast!(
800            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_sha3_256(v).expect_tc(span)?),
801            Address,
802            to_bits_le
803        ),
804        CoreFunction::SHA3_256HashToField => apply_cast!(
805            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_sha3_256(v).expect_tc(span)?),
806            Field,
807            to_bits_le
808        ),
809        CoreFunction::SHA3_256HashToGroup => apply_cast!(
810            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_sha3_256(v).expect_tc(span)?),
811            Group,
812            to_bits_le
813        ),
814        CoreFunction::SHA3_256HashToI8 => apply_cast_int!(
815            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_sha3_256(v).expect_tc(span)?),
816            I8,
817            i8,
818            to_bits_le
819        ),
820        CoreFunction::SHA3_256HashToI16 => apply_cast_int!(
821            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_sha3_256(v).expect_tc(span)?),
822            I16,
823            i16,
824            to_bits_le
825        ),
826        CoreFunction::SHA3_256HashToI32 => apply_cast_int!(
827            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_sha3_256(v).expect_tc(span)?),
828            I32,
829            i32,
830            to_bits_le
831        ),
832        CoreFunction::SHA3_256HashToI64 => apply_cast_int!(
833            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_sha3_256(v).expect_tc(span)?),
834            I64,
835            i64,
836            to_bits_le
837        ),
838        CoreFunction::SHA3_256HashToI128 => apply_cast_int!(
839            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_sha3_256(v).expect_tc(span)?),
840            I128,
841            i128,
842            to_bits_le
843        ),
844        CoreFunction::SHA3_256HashToU8 => apply_cast_int!(
845            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_sha3_256(v).expect_tc(span)?),
846            U8,
847            u8,
848            to_bits_le
849        ),
850        CoreFunction::SHA3_256HashToU16 => apply_cast_int!(
851            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_sha3_256(v).expect_tc(span)?),
852            U16,
853            u16,
854            to_bits_le
855        ),
856        CoreFunction::SHA3_256HashToU32 => apply_cast_int!(
857            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_sha3_256(v).expect_tc(span)?),
858            U32,
859            u32,
860            to_bits_le
861        ),
862        CoreFunction::SHA3_256HashToU64 => apply_cast_int!(
863            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_sha3_256(v).expect_tc(span)?),
864            U64,
865            u64,
866            to_bits_le
867        ),
868        CoreFunction::SHA3_256HashToU128 => apply_cast_int!(
869            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_sha3_256(v).expect_tc(span)?),
870            U128,
871            u128,
872            to_bits_le
873        ),
874        CoreFunction::SHA3_256HashToScalar => apply_cast!(
875            |v| TestnetV0::hash_to_group_bhp256(&TestnetV0::hash_sha3_256(v).expect_tc(span)?),
876            Scalar,
877            to_bits_le
878        ),
879        CoreFunction::SHA3_384HashToAddress => apply_cast!(
880            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_384(v).expect_tc(span)?),
881            Address,
882            to_bits_le
883        ),
884        CoreFunction::SHA3_384HashToField => apply_cast!(
885            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_384(v).expect_tc(span)?),
886            Field,
887            to_bits_le
888        ),
889        CoreFunction::SHA3_384HashToGroup => apply_cast!(
890            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_384(v).expect_tc(span)?),
891            Group,
892            to_bits_le
893        ),
894        CoreFunction::SHA3_384HashToI8 => apply_cast_int!(
895            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_384(v).expect_tc(span)?),
896            I8,
897            i8,
898            to_bits_le
899        ),
900        CoreFunction::SHA3_384HashToI16 => apply_cast_int!(
901            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_384(v).expect_tc(span)?),
902            I16,
903            i16,
904            to_bits_le
905        ),
906        CoreFunction::SHA3_384HashToI32 => apply_cast_int!(
907            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_384(v).expect_tc(span)?),
908            I32,
909            i32,
910            to_bits_le
911        ),
912        CoreFunction::SHA3_384HashToI64 => apply_cast_int!(
913            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_384(v).expect_tc(span)?),
914            I64,
915            i64,
916            to_bits_le
917        ),
918        CoreFunction::SHA3_384HashToI128 => apply_cast_int!(
919            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_384(v).expect_tc(span)?),
920            I128,
921            i128,
922            to_bits_le
923        ),
924        CoreFunction::SHA3_384HashToU8 => apply_cast_int!(
925            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_384(v).expect_tc(span)?),
926            U8,
927            u8,
928            to_bits_le
929        ),
930        CoreFunction::SHA3_384HashToU16 => apply_cast_int!(
931            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_384(v).expect_tc(span)?),
932            U16,
933            u16,
934            to_bits_le
935        ),
936        CoreFunction::SHA3_384HashToU32 => apply_cast_int!(
937            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_384(v).expect_tc(span)?),
938            U32,
939            u32,
940            to_bits_le
941        ),
942        CoreFunction::SHA3_384HashToU64 => apply_cast_int!(
943            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_384(v).expect_tc(span)?),
944            U64,
945            u64,
946            to_bits_le
947        ),
948        CoreFunction::SHA3_384HashToU128 => apply_cast_int!(
949            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_384(v).expect_tc(span)?),
950            U128,
951            u128,
952            to_bits_le
953        ),
954        CoreFunction::SHA3_384HashToScalar => apply_cast!(
955            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_384(v).expect_tc(span)?),
956            Scalar,
957            to_bits_le
958        ),
959        CoreFunction::SHA3_512HashToAddress => apply_cast!(
960            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_512(v).expect_tc(span)?),
961            Address,
962            to_bits_le
963        ),
964        CoreFunction::SHA3_512HashToField => apply_cast!(
965            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_512(v).expect_tc(span)?),
966            Field,
967            to_bits_le
968        ),
969        CoreFunction::SHA3_512HashToGroup => apply_cast!(
970            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_512(v).expect_tc(span)?),
971            Group,
972            to_bits_le
973        ),
974        CoreFunction::SHA3_512HashToI8 => apply_cast_int!(
975            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_512(v).expect_tc(span)?),
976            I8,
977            i8,
978            to_bits_le
979        ),
980        CoreFunction::SHA3_512HashToI16 => apply_cast_int!(
981            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_512(v).expect_tc(span)?),
982            I16,
983            i16,
984            to_bits_le
985        ),
986        CoreFunction::SHA3_512HashToI32 => apply_cast_int!(
987            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_512(v).expect_tc(span)?),
988            I32,
989            i32,
990            to_bits_le
991        ),
992        CoreFunction::SHA3_512HashToI64 => apply_cast_int!(
993            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_512(v).expect_tc(span)?),
994            I64,
995            i64,
996            to_bits_le
997        ),
998        CoreFunction::SHA3_512HashToI128 => apply_cast_int!(
999            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_512(v).expect_tc(span)?),
1000            I128,
1001            i128,
1002            to_bits_le
1003        ),
1004        CoreFunction::SHA3_512HashToU8 => apply_cast_int!(
1005            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_512(v).expect_tc(span)?),
1006            U8,
1007            u8,
1008            to_bits_le
1009        ),
1010        CoreFunction::SHA3_512HashToU16 => apply_cast_int!(
1011            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_512(v).expect_tc(span)?),
1012            U16,
1013            u16,
1014            to_bits_le
1015        ),
1016        CoreFunction::SHA3_512HashToU32 => apply_cast_int!(
1017            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_512(v).expect_tc(span)?),
1018            U32,
1019            u32,
1020            to_bits_le
1021        ),
1022        CoreFunction::SHA3_512HashToU64 => apply_cast_int!(
1023            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_512(v).expect_tc(span)?),
1024            U64,
1025            u64,
1026            to_bits_le
1027        ),
1028        CoreFunction::SHA3_512HashToU128 => apply_cast_int!(
1029            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_512(v).expect_tc(span)?),
1030            U128,
1031            u128,
1032            to_bits_le
1033        ),
1034        CoreFunction::SHA3_512HashToScalar => apply_cast!(
1035            |v| TestnetV0::hash_to_group_bhp512(&TestnetV0::hash_sha3_512(v).expect_tc(span)?),
1036            Scalar,
1037            to_bits_le
1038        ),
1039        CoreFunction::GroupToXCoordinate => {
1040            let Value::Group(g) = helper.pop_value()? else {
1041                tc_fail!();
1042            };
1043            Value::Field(g.to_x_coordinate())
1044        }
1045        CoreFunction::GroupToYCoordinate => {
1046            let Value::Group(g) = helper.pop_value()? else {
1047                tc_fail!();
1048            };
1049            Value::Field(g.to_y_coordinate())
1050        }
1051        CoreFunction::ChaChaRandAddress => Value::Address(maybe_gen!()),
1052        CoreFunction::ChaChaRandBool => Value::Bool(maybe_gen!()),
1053        CoreFunction::ChaChaRandField => Value::Field(maybe_gen!()),
1054        CoreFunction::ChaChaRandGroup => Value::Group(maybe_gen!()),
1055        CoreFunction::ChaChaRandI8 => Value::I8(maybe_gen!()),
1056        CoreFunction::ChaChaRandI16 => Value::I16(maybe_gen!()),
1057        CoreFunction::ChaChaRandI32 => Value::I32(maybe_gen!()),
1058        CoreFunction::ChaChaRandI64 => Value::I64(maybe_gen!()),
1059        CoreFunction::ChaChaRandI128 => Value::I128(maybe_gen!()),
1060        CoreFunction::ChaChaRandU8 => Value::U8(maybe_gen!()),
1061        CoreFunction::ChaChaRandU16 => Value::U16(maybe_gen!()),
1062        CoreFunction::ChaChaRandU32 => Value::U32(maybe_gen!()),
1063        CoreFunction::ChaChaRandU64 => Value::U64(maybe_gen!()),
1064        CoreFunction::ChaChaRandU128 => Value::U128(maybe_gen!()),
1065        CoreFunction::ChaChaRandScalar => Value::Scalar(maybe_gen!()),
1066        CoreFunction::CheatCodePrintMapping => {
1067            let (program, name) = match &arguments[0] {
1068                Expression::Identifier(id) => (None, id.name),
1069                Expression::Locator(locator) => (Some(locator.program.name.name), locator.name),
1070                _ => tc_fail!(),
1071            };
1072            if let Some(mapping) = helper.lookup_mapping(program, name) {
1073                // TODO: What is the appropriate way to print this to the console.
1074                // Print the name of the mapping.
1075                println!(
1076                    "Mapping: {}",
1077                    if let Some(program) = program { format!("{}/{}", program, name) } else { name.to_string() }
1078                );
1079                // Print the contents of the mapping.
1080                for (key, value) in mapping {
1081                    println!("  {} -> {}", key, value);
1082                }
1083            } else {
1084                tc_fail!();
1085            }
1086            Value::Unit
1087        }
1088        CoreFunction::CheatCodeSetBlockHeight => {
1089            let Value::U32(height) = helper.pop_value()? else {
1090                tc_fail!();
1091            };
1092            helper.set_block_height(height);
1093            Value::Unit
1094        }
1095        CoreFunction::MappingGet => {
1096            let key = helper.pop_value().expect_tc(span)?;
1097            let (program, name) = match &arguments[0] {
1098                Expression::Identifier(id) => (None, id.name),
1099                Expression::Locator(locator) => (Some(locator.program.name.name), locator.name),
1100                _ => tc_fail!(),
1101            };
1102            match helper.lookup_mapping(program, name).and_then(|mapping| mapping.get(&key)) {
1103                Some(v) => v.clone(),
1104                None => halt!(span, "map lookup failure"),
1105            }
1106        }
1107        CoreFunction::MappingGetOrUse => {
1108            let use_value = helper.pop_value().expect_tc(span)?;
1109            let key = helper.pop_value().expect_tc(span)?;
1110            let (program, name) = match &arguments[0] {
1111                Expression::Identifier(id) => (None, id.name),
1112                Expression::Locator(locator) => (Some(locator.program.name.name), locator.name),
1113                _ => tc_fail!(),
1114            };
1115            match helper.lookup_mapping(program, name).and_then(|mapping| mapping.get(&key)) {
1116                Some(v) => v.clone(),
1117                None => use_value,
1118            }
1119        }
1120        CoreFunction::MappingSet => {
1121            let value = helper.pop_value()?;
1122            let key = helper.pop_value()?;
1123            let (program, name) = match &arguments[0] {
1124                Expression::Identifier(id) => (None, id.name),
1125                Expression::Locator(locator) => (Some(locator.program.name.name), locator.name),
1126                _ => tc_fail!(),
1127            };
1128            if let Some(mapping) = helper.lookup_mapping_mut(program, name) {
1129                mapping.insert(key, value);
1130            } else {
1131                tc_fail!();
1132            }
1133            Value::Unit
1134        }
1135        CoreFunction::MappingRemove => {
1136            let key = helper.pop_value()?;
1137            let (program, name) = match &arguments[0] {
1138                Expression::Identifier(id) => (None, id.name),
1139                Expression::Locator(locator) => (Some(locator.program.name.name), locator.name),
1140                _ => tc_fail!(),
1141            };
1142            if let Some(mapping) = helper.lookup_mapping_mut(program, name) {
1143                mapping.remove(&key);
1144            } else {
1145                tc_fail!();
1146            }
1147            Value::Unit
1148        }
1149        CoreFunction::MappingContains => {
1150            let key = helper.pop_value()?;
1151            let (program, name) = match &arguments[0] {
1152                Expression::Identifier(id) => (None, id.name),
1153                Expression::Locator(locator) => (Some(locator.program.name.name), locator.name),
1154                _ => tc_fail!(),
1155            };
1156            if let Some(mapping) = helper.lookup_mapping_mut(program, name) {
1157                Value::Bool(mapping.contains_key(&key))
1158            } else {
1159                tc_fail!();
1160            }
1161        }
1162        CoreFunction::SignatureVerify => todo!(),
1163        CoreFunction::FutureAwait => panic!("await must be handled elsewhere"),
1164    };
1165
1166    Ok(Some(value))
1167}