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