Skip to main content

amaru_uplc/machine/
runtime.rs

1use core::str;
2use std::array::TryFromSliceError;
3
4use crate::{
5    arena::Arena,
6    binder::Eval,
7    bls::{Compressable, SCALAR_PERIOD},
8    builtin::DefaultFunction,
9    constant::{self, Constant, Integer},
10    data::PlutusData,
11    machine::cost_model::builtin_costs::BuiltinCostModel,
12    typ::Type,
13};
14use bumpalo::collections::{CollectIn, String as BumpString, Vec as BumpVec};
15use num::{Integer as NumInteger, Signed, Zero};
16
17use super::{cost_model, value::Value, Machine, MachineError};
18
19pub const INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH: i64 = 8192;
20
21pub enum BuiltinSemantics {
22    V1,
23    V2,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum PlutusVersion {
28    V1,
29    V2,
30    V3,
31}
32
33impl From<&PlutusVersion> for BuiltinSemantics {
34    fn from(version: &PlutusVersion) -> Self {
35        match version {
36            PlutusVersion::V1 => BuiltinSemantics::V1,
37            PlutusVersion::V2 => BuiltinSemantics::V1,
38            PlutusVersion::V3 => BuiltinSemantics::V2,
39        }
40    }
41}
42
43#[derive(Debug)]
44pub struct Runtime<'a, V>
45where
46    V: Eval<'a>,
47{
48    pub args: BumpVec<'a, &'a Value<'a, V>>,
49    pub fun: &'a DefaultFunction,
50    pub forces: usize,
51}
52
53impl<'a, V> Runtime<'a, V>
54where
55    V: Eval<'a>,
56{
57    pub fn new(arena: &'a Arena, fun: &'a DefaultFunction) -> &'a Self {
58        arena.alloc(Self {
59            args: BumpVec::new_in(arena.as_bump()),
60            fun,
61            forces: 0,
62        })
63    }
64
65    pub fn force(&self, arena: &'a Arena) -> &'a Self {
66        let new_runtime = arena.alloc(Runtime {
67            args: self.args.clone(),
68            fun: self.fun,
69            forces: self.forces + 1,
70        });
71
72        new_runtime
73    }
74
75    pub fn push(&self, arena: &'a Arena, arg: &'a Value<'a, V>) -> &'a Self {
76        let new_runtime = arena.alloc(Runtime {
77            args: self.args.clone(),
78            fun: self.fun,
79            forces: self.forces,
80        });
81
82        new_runtime.args.push(arg);
83
84        new_runtime
85    }
86
87    pub fn needs_force(&self) -> bool {
88        self.forces < self.fun.force_count()
89    }
90
91    pub fn is_arrow(&self) -> bool {
92        self.args.len() < self.fun.arity()
93    }
94
95    pub fn is_ready(&self) -> bool {
96        self.args.len() == self.fun.arity()
97    }
98}
99
100impl<'a, B: BuiltinCostModel> Machine<'a, B> {
101    pub fn call<V>(
102        &mut self,
103        runtime: &'a Runtime<'a, V>,
104    ) -> Result<&'a Value<'a, V>, MachineError<'a, V>>
105    where
106        V: Eval<'a>,
107    {
108        match runtime.fun {
109            DefaultFunction::AddInteger => {
110                let arg1 = runtime.args[0].unwrap_integer()?;
111                let arg2 = runtime.args[1].unwrap_integer()?;
112
113                let budget = self
114                    .costs
115                    .builtin_costs
116                    .get_cost(
117                        DefaultFunction::AddInteger,
118                        &[
119                            cost_model::integer_ex_mem(arg1),
120                            cost_model::integer_ex_mem(arg2),
121                        ],
122                    )
123                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::AddInteger))?;
124
125                self.spend_budget(budget)?;
126
127                let result = arg1 + arg2;
128                let new = self.arena.alloc_integer(result);
129
130                let value = Value::integer(self.arena, new);
131
132                Ok(value)
133            }
134            DefaultFunction::SubtractInteger => {
135                let arg1 = runtime.args[0].unwrap_integer()?;
136                let arg2 = runtime.args[1].unwrap_integer()?;
137
138                let budget = self
139                    .costs
140                    .builtin_costs
141                    .get_cost(
142                        DefaultFunction::SubtractInteger,
143                        &[
144                            cost_model::integer_ex_mem(arg1),
145                            cost_model::integer_ex_mem(arg2),
146                        ],
147                    )
148                    .ok_or(MachineError::NoCostForBuiltin(
149                        DefaultFunction::SubtractInteger,
150                    ))?;
151
152                self.spend_budget(budget)?;
153
154                let result = arg1 - arg2;
155
156                let new = self.arena.alloc_integer(result);
157
158                let value = Value::integer(self.arena, new);
159
160                Ok(value)
161            }
162            DefaultFunction::EqualsInteger => {
163                let arg1 = runtime.args[0].unwrap_integer()?;
164                let arg2 = runtime.args[1].unwrap_integer()?;
165
166                let budget = self
167                    .costs
168                    .builtin_costs
169                    .get_cost(
170                        DefaultFunction::EqualsInteger,
171                        &[
172                            cost_model::integer_ex_mem(arg1),
173                            cost_model::integer_ex_mem(arg2),
174                        ],
175                    )
176                    .ok_or(MachineError::NoCostForBuiltin(
177                        DefaultFunction::EqualsInteger,
178                    ))?;
179
180                self.spend_budget(budget)?;
181
182                let result = arg1 == arg2;
183
184                let value = Value::bool(self.arena, result);
185
186                Ok(value)
187            }
188            DefaultFunction::LessThanEqualsInteger => {
189                let arg1 = runtime.args[0].unwrap_integer()?;
190                let arg2 = runtime.args[1].unwrap_integer()?;
191
192                let budget = self
193                    .costs
194                    .builtin_costs
195                    .get_cost(
196                        DefaultFunction::LessThanEqualsInteger,
197                        &[
198                            cost_model::integer_ex_mem(arg1),
199                            cost_model::integer_ex_mem(arg2),
200                        ],
201                    )
202                    .ok_or(MachineError::NoCostForBuiltin(
203                        DefaultFunction::LessThanEqualsInteger,
204                    ))?;
205
206                self.spend_budget(budget)?;
207
208                let result = arg1 <= arg2;
209
210                let value = Value::bool(self.arena, result);
211
212                Ok(value)
213            }
214            DefaultFunction::AppendByteString => {
215                let arg1 = runtime.args[0].unwrap_byte_string()?;
216                let arg2 = runtime.args[1].unwrap_byte_string()?;
217
218                let budget = self
219                    .costs
220                    .builtin_costs
221                    .get_cost(
222                        DefaultFunction::AppendByteString,
223                        &[
224                            cost_model::byte_string_ex_mem(arg1),
225                            cost_model::byte_string_ex_mem(arg2),
226                        ],
227                    )
228                    .ok_or(MachineError::NoCostForBuiltin(
229                        DefaultFunction::AppendByteString,
230                    ))?;
231
232                self.spend_budget(budget)?;
233
234                let mut result =
235                    BumpVec::with_capacity_in(arg1.len() + arg2.len(), self.arena.as_bump());
236
237                result.extend_from_slice(arg1);
238                result.extend_from_slice(arg2);
239
240                let result = self.arena.alloc(result);
241
242                let value = Value::byte_string(self.arena, result);
243
244                Ok(value)
245            }
246            DefaultFunction::EqualsByteString => {
247                let arg1 = runtime.args[0].unwrap_byte_string()?;
248                let arg2 = runtime.args[1].unwrap_byte_string()?;
249
250                let budget = self
251                    .costs
252                    .builtin_costs
253                    .get_cost(
254                        DefaultFunction::EqualsByteString,
255                        &[
256                            cost_model::byte_string_ex_mem(arg1),
257                            cost_model::byte_string_ex_mem(arg2),
258                        ],
259                    )
260                    .ok_or(MachineError::NoCostForBuiltin(
261                        DefaultFunction::EqualsByteString,
262                    ))?;
263
264                self.spend_budget(budget)?;
265
266                let result = arg1 == arg2;
267
268                let value = Value::bool(self.arena, result);
269
270                Ok(value)
271            }
272            DefaultFunction::IfThenElse => {
273                let arg1 = runtime.args[0].unwrap_bool()?;
274                let arg2 = runtime.args[1];
275                let arg3 = runtime.args[2];
276                let budget = self
277                    .costs
278                    .builtin_costs
279                    .get_cost(
280                        DefaultFunction::IfThenElse,
281                        &[
282                            cost_model::BOOL_EX_MEM,
283                            cost_model::value_ex_mem(arg2),
284                            cost_model::value_ex_mem(arg3),
285                        ],
286                    )
287                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::IfThenElse))?;
288                self.spend_budget(budget)?;
289
290                if arg1 {
291                    Ok(arg2)
292                } else {
293                    Ok(arg3)
294                }
295            }
296            DefaultFunction::MultiplyInteger => {
297                let arg1 = runtime.args[0].unwrap_integer()?;
298                let arg2 = runtime.args[1].unwrap_integer()?;
299
300                let budget = self
301                    .costs
302                    .builtin_costs
303                    .get_cost(
304                        DefaultFunction::MultiplyInteger,
305                        &[
306                            cost_model::integer_ex_mem(arg1),
307                            cost_model::integer_ex_mem(arg2),
308                        ],
309                    )
310                    .ok_or(MachineError::NoCostForBuiltin(
311                        DefaultFunction::MultiplyInteger,
312                    ))?;
313
314                self.spend_budget(budget)?;
315
316                let result = arg1 * arg2;
317
318                let new = self.arena.alloc_integer(result);
319
320                let value = Value::integer(self.arena, new);
321
322                Ok(value)
323            }
324            DefaultFunction::DivideInteger => {
325                let arg1 = runtime.args[0].unwrap_integer()?;
326                let arg2 = runtime.args[1].unwrap_integer()?;
327
328                let budget = self
329                    .costs
330                    .builtin_costs
331                    .get_cost(
332                        DefaultFunction::DivideInteger,
333                        &[
334                            cost_model::integer_ex_mem(arg1),
335                            cost_model::integer_ex_mem(arg2),
336                        ],
337                    )
338                    .ok_or(MachineError::NoCostForBuiltin(
339                        DefaultFunction::DivideInteger,
340                    ))?;
341
342                self.spend_budget(budget)?;
343
344                if !arg2.is_zero() {
345                    let (result, _) = arg1.div_mod_floor(arg2);
346
347                    let new = self.arena.alloc_integer(result);
348
349                    let value = Value::integer(self.arena, new);
350
351                    Ok(value)
352                } else {
353                    Err(MachineError::division_by_zero(arg1, arg2))
354                }
355            }
356            DefaultFunction::QuotientInteger => {
357                let arg1 = runtime.args[0].unwrap_integer()?;
358                let arg2 = runtime.args[1].unwrap_integer()?;
359
360                let budget = self
361                    .costs
362                    .builtin_costs
363                    .get_cost(
364                        DefaultFunction::QuotientInteger,
365                        &[
366                            cost_model::integer_ex_mem(arg1),
367                            cost_model::integer_ex_mem(arg2),
368                        ],
369                    )
370                    .ok_or(MachineError::NoCostForBuiltin(
371                        DefaultFunction::QuotientInteger,
372                    ))?;
373
374                self.spend_budget(budget)?;
375
376                if !arg2.is_zero() {
377                    let (quotient, _) = arg1.div_rem(arg2);
378                    let q = self.arena.alloc_integer(quotient);
379                    let value = Value::integer(self.arena, q);
380                    Ok(value)
381                } else {
382                    Err(MachineError::division_by_zero(arg1, arg2))
383                }
384            }
385            DefaultFunction::RemainderInteger => {
386                let arg1 = runtime.args[0].unwrap_integer()?;
387                let arg2 = runtime.args[1].unwrap_integer()?;
388
389                let budget = self
390                    .costs
391                    .builtin_costs
392                    .get_cost(
393                        DefaultFunction::RemainderInteger,
394                        &[
395                            cost_model::integer_ex_mem(arg1),
396                            cost_model::integer_ex_mem(arg2),
397                        ],
398                    )
399                    .ok_or(MachineError::NoCostForBuiltin(
400                        DefaultFunction::RemainderInteger,
401                    ))?;
402
403                self.spend_budget(budget)?;
404
405                if !arg2.is_zero() {
406                    let (_, remainder) = arg1.div_rem(arg2);
407                    let r = self.arena.alloc_integer(remainder);
408                    let value = Value::integer(self.arena, r);
409                    Ok(value)
410                } else {
411                    Err(MachineError::division_by_zero(arg1, arg2))
412                }
413            }
414            DefaultFunction::ModInteger => {
415                let arg1 = runtime.args[0].unwrap_integer()?;
416                let arg2 = runtime.args[1].unwrap_integer()?;
417
418                let budget = self
419                    .costs
420                    .builtin_costs
421                    .get_cost(
422                        DefaultFunction::ModInteger,
423                        &[
424                            cost_model::integer_ex_mem(arg1),
425                            cost_model::integer_ex_mem(arg2),
426                        ],
427                    )
428                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::ModInteger))?;
429
430                self.spend_budget(budget)?;
431
432                if !arg2.is_zero() {
433                    let (_, result) = arg1.div_mod_floor(arg2);
434                    let result = self.arena.alloc_integer(result);
435                    let value = Value::integer(self.arena, result);
436
437                    Ok(value)
438                } else {
439                    Err(MachineError::division_by_zero(arg1, arg2))
440                }
441            }
442            DefaultFunction::LessThanInteger => {
443                let arg1 = runtime.args[0].unwrap_integer()?;
444                let arg2 = runtime.args[1].unwrap_integer()?;
445
446                let budget = self
447                    .costs
448                    .builtin_costs
449                    .get_cost(
450                        DefaultFunction::LessThanInteger,
451                        &[
452                            cost_model::integer_ex_mem(arg1),
453                            cost_model::integer_ex_mem(arg2),
454                        ],
455                    )
456                    .ok_or(MachineError::NoCostForBuiltin(
457                        DefaultFunction::LessThanInteger,
458                    ))?;
459
460                self.spend_budget(budget)?;
461
462                let result = arg1 < arg2;
463
464                let value = Value::bool(self.arena, result);
465
466                Ok(value)
467            }
468            DefaultFunction::ConsByteString => {
469                let arg1 = runtime.args[0].unwrap_integer()?;
470                let arg2 = runtime.args[1].unwrap_byte_string()?;
471
472                let budget = self
473                    .costs
474                    .builtin_costs
475                    .get_cost(
476                        DefaultFunction::ConsByteString,
477                        &[
478                            cost_model::integer_ex_mem(arg1),
479                            cost_model::byte_string_ex_mem(arg2),
480                        ],
481                    )
482                    .ok_or(MachineError::NoCostForBuiltin(
483                        DefaultFunction::ConsByteString,
484                    ))?;
485
486                self.spend_budget(budget)?;
487
488                let byte: u8 = match &self.semantics {
489                    BuiltinSemantics::V1 => {
490                        let wrap: Integer = arg1 % 256;
491
492                        wrap.try_into().expect("should cast to u64 just fine")
493                    }
494                    BuiltinSemantics::V2 => {
495                        if *arg1 > Integer::from(255) || *arg1 < Integer::from(0) {
496                            return Err(MachineError::byte_string_cons_not_a_byte(arg1));
497                        }
498
499                        arg1.try_into().expect("should cast to u8 just fine")
500                    }
501                };
502
503                let mut ret = BumpVec::with_capacity_in(arg2.len() + 1, self.arena.as_bump());
504
505                ret.push(byte);
506
507                ret.extend_from_slice(arg2);
508
509                let ret = self.arena.alloc(ret);
510
511                let value = Value::byte_string(self.arena, ret);
512
513                Ok(value)
514            }
515            DefaultFunction::SliceByteString => {
516                let arg1 = runtime.args[0].unwrap_integer()?;
517                let arg2 = runtime.args[1].unwrap_integer()?;
518                let arg3 = runtime.args[2].unwrap_byte_string()?;
519
520                let budget = self
521                    .costs
522                    .builtin_costs
523                    .get_cost(
524                        DefaultFunction::SliceByteString,
525                        &[
526                            cost_model::integer_ex_mem(arg1),
527                            cost_model::integer_ex_mem(arg2),
528                            cost_model::byte_string_ex_mem(arg3),
529                        ],
530                    )
531                    .ok_or(MachineError::NoCostForBuiltin(
532                        DefaultFunction::SliceByteString,
533                    ))?;
534
535                self.spend_budget(budget)?;
536
537                let skip: usize = if *arg1 < Integer::ZERO {
538                    0
539                } else if *arg1 > arg3.len().into() {
540                    arg3.len()
541                } else {
542                    arg1.try_into().expect("should cast to usize just fine")
543                };
544
545                let take: usize = if *arg2 < Integer::ZERO {
546                    0
547                } else if *arg2 > arg3.len().into() {
548                    arg3.len()
549                } else {
550                    arg2.try_into().expect("should cast to usize just fine")
551                };
552
553                let skip_take: usize = if skip + take > arg3.len() {
554                    arg3.len()
555                } else {
556                    skip + take
557                };
558
559                let value = Value::byte_string(self.arena, &arg3[skip..(skip_take)]);
560
561                Ok(value)
562            }
563            DefaultFunction::LengthOfByteString => {
564                let arg1 = runtime.args[0].unwrap_byte_string()?;
565
566                let budget = self
567                    .costs
568                    .builtin_costs
569                    .get_cost(
570                        DefaultFunction::LengthOfByteString,
571                        &[cost_model::byte_string_ex_mem(arg1)],
572                    )
573                    .ok_or(MachineError::NoCostForBuiltin(
574                        DefaultFunction::LengthOfByteString,
575                    ))?;
576
577                self.spend_budget(budget)?;
578
579                let result: Integer = arg1.len().into();
580
581                let new = self.arena.alloc_integer(result);
582                let value = Value::integer(self.arena, new);
583
584                Ok(value)
585            }
586            DefaultFunction::IndexByteString => {
587                let arg1 = runtime.args[0].unwrap_byte_string()?;
588                let arg2 = runtime.args[1].unwrap_integer()?;
589
590                let budget = self
591                    .costs
592                    .builtin_costs
593                    .get_cost(
594                        DefaultFunction::IndexByteString,
595                        &[
596                            cost_model::byte_string_ex_mem(arg1),
597                            cost_model::integer_ex_mem(arg2),
598                        ],
599                    )
600                    .ok_or(MachineError::NoCostForBuiltin(
601                        DefaultFunction::IndexByteString,
602                    ))?;
603
604                self.spend_budget(budget)?;
605
606                let index: i128 = arg2.try_into().unwrap();
607
608                if 0 <= index && (index as usize) < arg1.len() {
609                    let result: Integer = arg1[index as usize].into();
610                    let new = self.arena.alloc_integer(result);
611                    let value = Value::integer(self.arena, new);
612
613                    Ok(value)
614                } else {
615                    Err(MachineError::byte_string_out_of_bounds(arg1, arg2))
616                }
617            }
618            DefaultFunction::LessThanByteString => {
619                let arg1 = runtime.args[0].unwrap_byte_string()?;
620                let arg2 = runtime.args[1].unwrap_byte_string()?;
621
622                let budget = self
623                    .costs
624                    .builtin_costs
625                    .get_cost(
626                        DefaultFunction::LessThanByteString,
627                        &[
628                            cost_model::byte_string_ex_mem(arg1),
629                            cost_model::byte_string_ex_mem(arg2),
630                        ],
631                    )
632                    .ok_or(MachineError::NoCostForBuiltin(
633                        DefaultFunction::LessThanByteString,
634                    ))?;
635
636                self.spend_budget(budget)?;
637
638                let result = arg1 < arg2;
639
640                let value = Value::bool(self.arena, result);
641
642                Ok(value)
643            }
644            DefaultFunction::LessThanEqualsByteString => {
645                let arg1 = runtime.args[0].unwrap_byte_string()?;
646                let arg2 = runtime.args[1].unwrap_byte_string()?;
647
648                let budget = self
649                    .costs
650                    .builtin_costs
651                    .get_cost(
652                        DefaultFunction::LessThanEqualsByteString,
653                        &[
654                            cost_model::byte_string_ex_mem(arg1),
655                            cost_model::byte_string_ex_mem(arg2),
656                        ],
657                    )
658                    .ok_or(MachineError::NoCostForBuiltin(
659                        DefaultFunction::LessThanEqualsByteString,
660                    ))?;
661
662                self.spend_budget(budget)?;
663
664                let result = arg1 <= arg2;
665
666                let value = Value::bool(self.arena, result);
667
668                Ok(value)
669            }
670            DefaultFunction::Sha2_256 => {
671                use cryptoxide::{digest::Digest, sha2::Sha256};
672
673                let arg1 = runtime.args[0].unwrap_byte_string()?;
674
675                let budget = self
676                    .costs
677                    .builtin_costs
678                    .get_cost(
679                        DefaultFunction::Sha2_256,
680                        &[cost_model::byte_string_ex_mem(arg1)],
681                    )
682                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::Sha2_256))?;
683
684                self.spend_budget(budget)?;
685
686                let mut hasher = Sha256::new();
687
688                hasher.input(arg1);
689
690                let mut bytes =
691                    BumpVec::with_capacity_in(hasher.output_bytes(), self.arena.as_bump());
692
693                unsafe {
694                    bytes.set_len(hasher.output_bytes());
695                }
696
697                hasher.result(&mut bytes);
698
699                let bytes = self.arena.alloc(bytes);
700
701                let value = Value::byte_string(self.arena, bytes);
702
703                Ok(value)
704            }
705            DefaultFunction::Sha3_256 => {
706                use cryptoxide::{digest::Digest, sha3::Sha3_256};
707
708                let arg1 = runtime.args[0].unwrap_byte_string()?;
709
710                let budget = self
711                    .costs
712                    .builtin_costs
713                    .get_cost(
714                        DefaultFunction::Sha3_256,
715                        &[cost_model::byte_string_ex_mem(arg1)],
716                    )
717                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::Sha3_256))?;
718
719                self.spend_budget(budget)?;
720
721                let mut hasher = Sha3_256::new();
722
723                hasher.input(arg1);
724
725                let mut bytes =
726                    BumpVec::with_capacity_in(hasher.output_bytes(), self.arena.as_bump());
727
728                unsafe {
729                    bytes.set_len(hasher.output_bytes());
730                }
731
732                hasher.result(&mut bytes);
733
734                let bytes = self.arena.alloc(bytes);
735
736                let value = Value::byte_string(self.arena, bytes);
737
738                Ok(value)
739            }
740            DefaultFunction::Blake2b_256 => {
741                use cryptoxide::{blake2b::Blake2b, digest::Digest};
742
743                let arg1 = runtime.args[0].unwrap_byte_string()?;
744
745                let budget = self
746                    .costs
747                    .builtin_costs
748                    .get_cost(
749                        DefaultFunction::Blake2b_256,
750                        &[cost_model::byte_string_ex_mem(arg1)],
751                    )
752                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::Blake2b_256))?;
753
754                self.spend_budget(budget)?;
755
756                let mut digest = BumpVec::with_capacity_in(32, self.arena.as_bump());
757
758                unsafe {
759                    digest.set_len(32);
760                }
761
762                let mut context = Blake2b::new(32);
763
764                context.input(arg1);
765                context.result(&mut digest);
766
767                let digest = self.arena.alloc(digest);
768
769                let value = Value::byte_string(self.arena, digest);
770
771                Ok(value)
772            }
773            DefaultFunction::Keccak_256 => {
774                use cryptoxide::{digest::Digest, sha3::Keccak256};
775
776                let arg1 = runtime.args[0].unwrap_byte_string()?;
777
778                let budget = self
779                    .costs
780                    .builtin_costs
781                    .get_cost(
782                        DefaultFunction::Keccak_256,
783                        &[cost_model::byte_string_ex_mem(arg1)],
784                    )
785                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::Keccak_256))?;
786
787                self.spend_budget(budget)?;
788
789                let mut hasher = Keccak256::new();
790
791                hasher.input(arg1);
792
793                let mut bytes =
794                    BumpVec::with_capacity_in(hasher.output_bytes(), self.arena.as_bump());
795
796                unsafe {
797                    bytes.set_len(hasher.output_bytes());
798                }
799
800                hasher.result(&mut bytes);
801
802                let bytes = self.arena.alloc(bytes);
803
804                let value = Value::byte_string(self.arena, bytes);
805
806                Ok(value)
807            }
808            DefaultFunction::Blake2b_224 => {
809                use cryptoxide::{blake2b::Blake2b, digest::Digest};
810
811                let arg1 = runtime.args[0].unwrap_byte_string()?;
812
813                let budget = self
814                    .costs
815                    .builtin_costs
816                    .get_cost(
817                        DefaultFunction::Blake2b_224,
818                        &[cost_model::byte_string_ex_mem(arg1)],
819                    )
820                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::Blake2b_224))?;
821
822                self.spend_budget(budget)?;
823
824                let mut digest = BumpVec::with_capacity_in(28, self.arena.as_bump());
825
826                unsafe {
827                    digest.set_len(28);
828                }
829
830                let mut context = Blake2b::new(28);
831
832                context.input(arg1);
833                context.result(&mut digest);
834
835                let digest = self.arena.alloc(digest);
836
837                let value = Value::byte_string(self.arena, digest);
838
839                Ok(value)
840            }
841            DefaultFunction::VerifyEd25519Signature => {
842                use cryptoxide::ed25519;
843
844                let public_key = runtime.args[0].unwrap_byte_string()?;
845                let message = runtime.args[1].unwrap_byte_string()?;
846                let signature = runtime.args[2].unwrap_byte_string()?;
847
848                let budget = self
849                    .costs
850                    .builtin_costs
851                    .get_cost(
852                        DefaultFunction::VerifyEd25519Signature,
853                        &[
854                            cost_model::byte_string_ex_mem(public_key),
855                            cost_model::byte_string_ex_mem(message),
856                            cost_model::byte_string_ex_mem(signature),
857                        ],
858                    )
859                    .ok_or(MachineError::NoCostForBuiltin(
860                        DefaultFunction::VerifyEd25519Signature,
861                    ))?;
862
863                self.spend_budget(budget)?;
864
865                let public_key: [u8; 32] =
866                    public_key.try_into().map_err(|e: TryFromSliceError| {
867                        MachineError::unexpected_ed25519_public_key_length(e)
868                    })?;
869
870                let signature: [u8; 64] =
871                    signature.try_into().map_err(|e: TryFromSliceError| {
872                        MachineError::unexpected_ed25519_signature_length(e)
873                    })?;
874
875                let valid = ed25519::verify(message, &public_key, &signature);
876
877                let value = Value::bool(self.arena, valid);
878
879                Ok(value)
880            }
881            DefaultFunction::VerifyEcdsaSecp256k1Signature => {
882                use secp256k1::{ecdsa::Signature, Message, PublicKey, Secp256k1};
883
884                let public_key = runtime.args[0].unwrap_byte_string()?;
885                let message = runtime.args[1].unwrap_byte_string()?;
886                let signature = runtime.args[2].unwrap_byte_string()?;
887
888                let budget = self
889                    .costs
890                    .builtin_costs
891                    .get_cost(
892                        DefaultFunction::VerifyEcdsaSecp256k1Signature,
893                        &[
894                            cost_model::byte_string_ex_mem(public_key),
895                            cost_model::byte_string_ex_mem(message),
896                            cost_model::byte_string_ex_mem(signature),
897                        ],
898                    )
899                    .ok_or(MachineError::NoCostForBuiltin(
900                        DefaultFunction::VerifyEcdsaSecp256k1Signature,
901                    ))?;
902
903                self.spend_budget(budget)?;
904
905                let secp = Secp256k1::verification_only();
906
907                let public_key =
908                    PublicKey::from_slice(public_key).map_err(MachineError::secp256k1)?;
909
910                let signature =
911                    Signature::from_compact(signature).map_err(MachineError::secp256k1)?;
912
913                let message =
914                    Message::from_digest_slice(message).map_err(MachineError::secp256k1)?;
915
916                let valid = secp.verify_ecdsa(&message, &signature, &public_key);
917
918                let value = Value::bool(self.arena, valid.is_ok());
919
920                Ok(value)
921            }
922            DefaultFunction::VerifySchnorrSecp256k1Signature => {
923                use secp256k1::{schnorr::Signature, Secp256k1, XOnlyPublicKey};
924
925                let public_key = runtime.args[0].unwrap_byte_string()?;
926                let message = runtime.args[1].unwrap_byte_string()?;
927                let signature = runtime.args[2].unwrap_byte_string()?;
928
929                let budget = self
930                    .costs
931                    .builtin_costs
932                    .get_cost(
933                        DefaultFunction::VerifySchnorrSecp256k1Signature,
934                        &[
935                            cost_model::byte_string_ex_mem(public_key),
936                            cost_model::byte_string_ex_mem(message),
937                            cost_model::byte_string_ex_mem(signature),
938                        ],
939                    )
940                    .ok_or(MachineError::NoCostForBuiltin(
941                        DefaultFunction::VerifySchnorrSecp256k1Signature,
942                    ))?;
943
944                self.spend_budget(budget)?;
945
946                let secp = Secp256k1::verification_only();
947
948                let public_key =
949                    XOnlyPublicKey::from_slice(public_key).map_err(MachineError::secp256k1)?;
950
951                let signature =
952                    Signature::from_slice(signature).map_err(MachineError::secp256k1)?;
953
954                let valid = secp.verify_schnorr(&signature, message, &public_key);
955
956                let value = Value::bool(self.arena, valid.is_ok());
957
958                Ok(value)
959            }
960            DefaultFunction::AppendString => {
961                let arg1 = runtime.args[0].unwrap_string()?;
962                let arg2 = runtime.args[1].unwrap_string()?;
963
964                let budget = self
965                    .costs
966                    .builtin_costs
967                    .get_cost(
968                        DefaultFunction::AppendString,
969                        &[
970                            cost_model::string_ex_mem(arg1),
971                            cost_model::string_ex_mem(arg2),
972                        ],
973                    )
974                    .ok_or(MachineError::NoCostForBuiltin(
975                        DefaultFunction::AppendString,
976                    ))?;
977
978                self.spend_budget(budget)?;
979
980                let mut new = BumpString::new_in(self.arena.as_bump());
981
982                new.push_str(arg1);
983                new.push_str(arg2);
984
985                let new = self.arena.alloc(new);
986
987                let value = Value::string(self.arena, new);
988
989                Ok(value)
990            }
991            DefaultFunction::EqualsString => {
992                let arg1 = runtime.args[0].unwrap_string()?;
993                let arg2 = runtime.args[1].unwrap_string()?;
994
995                let budget = self
996                    .costs
997                    .builtin_costs
998                    .get_cost(
999                        DefaultFunction::EqualsString,
1000                        &[
1001                            cost_model::string_ex_mem(arg1),
1002                            cost_model::string_ex_mem(arg2),
1003                        ],
1004                    )
1005                    .ok_or(MachineError::NoCostForBuiltin(
1006                        DefaultFunction::EqualsString,
1007                    ))?;
1008
1009                self.spend_budget(budget)?;
1010
1011                let value = Value::bool(self.arena, arg1 == arg2);
1012
1013                Ok(value)
1014            }
1015            DefaultFunction::EncodeUtf8 => {
1016                let arg1 = runtime.args[0].unwrap_string()?;
1017
1018                let budget = self
1019                    .costs
1020                    .builtin_costs
1021                    .get_cost(
1022                        DefaultFunction::EncodeUtf8,
1023                        &[cost_model::string_ex_mem(arg1)],
1024                    )
1025                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::EncodeUtf8))?;
1026
1027                self.spend_budget(budget)?;
1028
1029                let s_bytes = arg1.as_bytes();
1030
1031                let mut bytes = BumpVec::with_capacity_in(s_bytes.len(), self.arena.as_bump());
1032
1033                bytes.extend_from_slice(s_bytes);
1034
1035                let bytes = self.arena.alloc(bytes);
1036
1037                let value = Value::byte_string(self.arena, bytes);
1038
1039                Ok(value)
1040            }
1041            DefaultFunction::DecodeUtf8 => {
1042                let arg1 = runtime.args[0].unwrap_byte_string()?;
1043
1044                let budget = self
1045                    .costs
1046                    .builtin_costs
1047                    .get_cost(
1048                        DefaultFunction::DecodeUtf8,
1049                        &[cost_model::byte_string_ex_mem(arg1)],
1050                    )
1051                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::DecodeUtf8))?;
1052
1053                self.spend_budget(budget)?;
1054
1055                let string = str::from_utf8(arg1).map_err(|e| MachineError::decode_utf8(e))?;
1056
1057                let value = Value::string(self.arena, string);
1058
1059                Ok(value)
1060            }
1061            DefaultFunction::ChooseUnit => {
1062                runtime.args[0].unwrap_unit()?;
1063                let arg2 = runtime.args[1];
1064
1065                let budget = self
1066                    .costs
1067                    .builtin_costs
1068                    .get_cost(
1069                        DefaultFunction::ChooseUnit,
1070                        &[cost_model::UNIT_EX_MEM, cost_model::value_ex_mem(arg2)],
1071                    )
1072                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::ChooseUnit))?;
1073
1074                self.spend_budget(budget)?;
1075
1076                Ok(arg2)
1077            }
1078            DefaultFunction::Trace => {
1079                let arg1 = runtime.args[0].unwrap_string()?;
1080                let arg2 = runtime.args[1];
1081
1082                let budget = self
1083                    .costs
1084                    .builtin_costs
1085                    .get_cost(
1086                        DefaultFunction::Trace,
1087                        &[
1088                            cost_model::string_ex_mem(arg1),
1089                            cost_model::value_ex_mem(arg2),
1090                        ],
1091                    )
1092                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::Trace))?;
1093
1094                self.spend_budget(budget)?;
1095
1096                self.logs.push(arg1.to_string());
1097
1098                Ok(arg2)
1099            }
1100            DefaultFunction::FstPair => {
1101                let (_, _, first, second) = runtime.args[0].unwrap_pair()?;
1102
1103                let budget = self
1104                    .costs
1105                    .builtin_costs
1106                    .get_cost(
1107                        DefaultFunction::FstPair,
1108                        &[cost_model::pair_ex_mem(first, second)],
1109                    )
1110                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::FstPair))?;
1111
1112                self.spend_budget(budget)?;
1113
1114                let value = Value::con(self.arena, first);
1115
1116                Ok(value)
1117            }
1118            DefaultFunction::SndPair => {
1119                let (_, _, first, second) = runtime.args[0].unwrap_pair()?;
1120
1121                let budget = self
1122                    .costs
1123                    .builtin_costs
1124                    .get_cost(
1125                        DefaultFunction::SndPair,
1126                        &[cost_model::pair_ex_mem(first, second)],
1127                    )
1128                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::SndPair))?;
1129
1130                self.spend_budget(budget)?;
1131
1132                let value = Value::con(self.arena, second);
1133
1134                Ok(value)
1135            }
1136            DefaultFunction::ChooseList => {
1137                let (_, list) = runtime.args[0].unwrap_list()?;
1138                let arg2 = runtime.args[1];
1139                let arg3 = runtime.args[2];
1140
1141                let budget = self
1142                    .costs
1143                    .builtin_costs
1144                    .get_cost(
1145                        DefaultFunction::ChooseList,
1146                        &[
1147                            cost_model::proto_list_ex_mem(list),
1148                            cost_model::value_ex_mem(arg2),
1149                            cost_model::value_ex_mem(arg3),
1150                        ],
1151                    )
1152                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::ChooseList))?;
1153
1154                self.spend_budget(budget)?;
1155
1156                if list.is_empty() {
1157                    Ok(arg2)
1158                } else {
1159                    Ok(arg3)
1160                }
1161            }
1162            DefaultFunction::MkCons => {
1163                let item = runtime.args[0].unwrap_constant()?;
1164                let (typ, list) = runtime.args[1].unwrap_list()?;
1165
1166                let budget = self
1167                    .costs
1168                    .builtin_costs
1169                    .get_cost(
1170                        DefaultFunction::MkCons,
1171                        &[
1172                            cost_model::constant_ex_mem(item),
1173                            cost_model::proto_list_ex_mem(list),
1174                        ],
1175                    )
1176                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::MkCons))?;
1177
1178                self.spend_budget(budget)?;
1179
1180                if item.type_of(self.arena) != typ {
1181                    return Err(MachineError::mk_cons_type_mismatch(item));
1182                }
1183
1184                let mut new_list = BumpVec::with_capacity_in(list.len() + 1, self.arena.as_bump());
1185
1186                new_list.push(item);
1187
1188                new_list.extend_from_slice(list);
1189
1190                let new_list = self.arena.alloc(new_list);
1191
1192                let constant = Constant::proto_list(self.arena, typ, new_list);
1193
1194                let value = constant.value(self.arena);
1195
1196                Ok(value)
1197            }
1198            DefaultFunction::HeadList => {
1199                let (_, list) = runtime.args[0].unwrap_list()?;
1200
1201                let budget = self
1202                    .costs
1203                    .builtin_costs
1204                    .get_cost(
1205                        DefaultFunction::HeadList,
1206                        &[cost_model::proto_list_ex_mem(list)],
1207                    )
1208                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::HeadList))?;
1209
1210                self.spend_budget(budget)?;
1211
1212                if list.is_empty() {
1213                    Err(MachineError::empty_list(list))
1214                } else {
1215                    let value = Value::con(self.arena, list[0]);
1216
1217                    Ok(value)
1218                }
1219            }
1220            DefaultFunction::TailList => {
1221                let (t1, list) = runtime.args[0].unwrap_list()?;
1222
1223                let budget = self
1224                    .costs
1225                    .builtin_costs
1226                    .get_cost(
1227                        DefaultFunction::TailList,
1228                        &[cost_model::proto_list_ex_mem(list)],
1229                    )
1230                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::TailList))?;
1231
1232                self.spend_budget(budget)?;
1233
1234                if list.is_empty() {
1235                    Err(MachineError::empty_list(list))
1236                } else {
1237                    let constant = Constant::proto_list(self.arena, t1, &list[1..]);
1238
1239                    let value = Value::con(self.arena, constant);
1240
1241                    Ok(value)
1242                }
1243            }
1244            DefaultFunction::NullList => {
1245                let (_, list) = runtime.args[0].unwrap_list()?;
1246
1247                let budget = self
1248                    .costs
1249                    .builtin_costs
1250                    .get_cost(
1251                        DefaultFunction::NullList,
1252                        &[cost_model::proto_list_ex_mem(list)],
1253                    )
1254                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::NullList))?;
1255
1256                self.spend_budget(budget)?;
1257
1258                let value = Value::bool(self.arena, list.is_empty());
1259
1260                Ok(value)
1261            }
1262            DefaultFunction::ChooseData => {
1263                let arg1 = runtime.args[0].unwrap_constant()?.unwrap_data()?;
1264                let arg2 = runtime.args[1];
1265                let arg3 = runtime.args[2];
1266                let arg4 = runtime.args[3];
1267                let arg5 = runtime.args[4];
1268                let arg6 = runtime.args[5];
1269
1270                let budget = self
1271                    .costs
1272                    .builtin_costs
1273                    .get_cost(
1274                        DefaultFunction::ChooseData,
1275                        &[
1276                            cost_model::data_ex_mem(arg1),
1277                            cost_model::value_ex_mem(arg2),
1278                            cost_model::value_ex_mem(arg3),
1279                            cost_model::value_ex_mem(arg4),
1280                            cost_model::value_ex_mem(arg5),
1281                            cost_model::value_ex_mem(arg6),
1282                        ],
1283                    )
1284                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::ChooseData))?;
1285
1286                self.spend_budget(budget)?;
1287
1288                match arg1 {
1289                    PlutusData::Constr { .. } => Ok(arg2),
1290                    PlutusData::Map(_) => Ok(arg3),
1291                    PlutusData::List(_) => Ok(arg4),
1292                    PlutusData::Integer(_) => Ok(arg5),
1293                    PlutusData::ByteString(_) => Ok(arg6),
1294                }
1295            }
1296            DefaultFunction::ConstrData => {
1297                let tag = runtime.args[0].unwrap_integer()?;
1298                let (typ, fields) = runtime.args[1].unwrap_list()?;
1299
1300                let budget = self
1301                    .costs
1302                    .builtin_costs
1303                    .get_cost(
1304                        DefaultFunction::ConstrData,
1305                        &[
1306                            cost_model::integer_ex_mem(tag),
1307                            cost_model::proto_list_ex_mem(fields),
1308                        ],
1309                    )
1310                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::ConstrData))?;
1311
1312                self.spend_budget(budget)?;
1313
1314                if *typ != Type::Data {
1315                    return Err(MachineError::type_mismatch(
1316                        Type::Data,
1317                        runtime.args[1].unwrap_constant()?,
1318                    ));
1319                }
1320
1321                let tag = tag.try_into().expect("should cast to u64 just fine");
1322                let fields: BumpVec<'_, _> = fields
1323                    .iter()
1324                    .map(|d| match d {
1325                        Constant::Data(d) => *d,
1326                        _ => unreachable!(),
1327                    })
1328                    .collect_in(self.arena.as_bump());
1329                let fields = self.arena.alloc(fields);
1330
1331                let data = PlutusData::constr(self.arena, tag, fields);
1332
1333                let constant = Constant::data(self.arena, data);
1334
1335                let value = Value::con(self.arena, constant);
1336
1337                Ok(value)
1338            }
1339            DefaultFunction::MapData => {
1340                let (r#type, list) = runtime.args[0].unwrap_list()?;
1341
1342                if !matches!(r#type, Type::Pair(Type::Data, Type::Data)) {
1343                    return Err(MachineError::type_mismatch(
1344                        Type::List(Type::pair(
1345                            self.arena,
1346                            Type::data(self.arena),
1347                            Type::data(self.arena),
1348                        )),
1349                        runtime.args[0].unwrap_constant()?,
1350                    ));
1351                }
1352
1353                let budget = self
1354                    .costs
1355                    .builtin_costs
1356                    .get_cost(
1357                        DefaultFunction::MapData,
1358                        &[cost_model::proto_list_ex_mem(list)],
1359                    )
1360                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::MapData))?;
1361
1362                self.spend_budget(budget)?;
1363
1364                let mut map = BumpVec::new_in(self.arena.as_bump());
1365
1366                for item in list {
1367                    let Constant::ProtoPair(Type::Data, Type::Data, left, right) = item else {
1368                        unreachable!("is this really unreachable?")
1369                    };
1370
1371                    let Constant::Data(key) = left else {
1372                        unreachable!()
1373                    };
1374
1375                    let Constant::Data(value) = right else {
1376                        unreachable!()
1377                    };
1378
1379                    map.push((*key, *value));
1380                }
1381
1382                let map = self.arena.alloc(map);
1383
1384                let value = PlutusData::map(self.arena, map)
1385                    .constant(self.arena)
1386                    .value(self.arena);
1387
1388                Ok(value)
1389            }
1390            DefaultFunction::ListData => {
1391                let (typ, fields) = runtime.args[0].unwrap_list()?;
1392
1393                let budget = self
1394                    .costs
1395                    .builtin_costs
1396                    .get_cost(
1397                        DefaultFunction::ListData,
1398                        &[cost_model::proto_list_ex_mem(fields)],
1399                    )
1400                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::ListData))?;
1401
1402                self.spend_budget(budget)?;
1403
1404                if *typ != Type::Data {
1405                    return Err(MachineError::type_mismatch(
1406                        Type::Data,
1407                        runtime.args[0].unwrap_constant()?,
1408                    ));
1409                }
1410
1411                let fields: BumpVec<'_, _> = fields
1412                    .iter()
1413                    .map(|d| match d {
1414                        Constant::Data(d) => *d,
1415                        _ => unreachable!(),
1416                    })
1417                    .collect_in(self.arena.as_bump());
1418                let fields = self.arena.alloc(fields);
1419
1420                let value = PlutusData::list(self.arena, fields)
1421                    .constant(self.arena)
1422                    .value(self.arena);
1423
1424                Ok(value)
1425            }
1426            DefaultFunction::IData => {
1427                let i = runtime.args[0].unwrap_integer()?;
1428
1429                let budget = self
1430                    .costs
1431                    .builtin_costs
1432                    .get_cost(DefaultFunction::IData, &[cost_model::integer_ex_mem(i)])
1433                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::IData))?;
1434
1435                self.spend_budget(budget)?;
1436
1437                let i = PlutusData::integer(self.arena, i);
1438
1439                let value = i.constant(self.arena).value(self.arena);
1440
1441                Ok(value)
1442            }
1443            DefaultFunction::BData => {
1444                let b = runtime.args[0].unwrap_byte_string()?;
1445
1446                let budget = self
1447                    .costs
1448                    .builtin_costs
1449                    .get_cost(DefaultFunction::BData, &[cost_model::byte_string_ex_mem(b)])
1450                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::BData))?;
1451
1452                self.spend_budget(budget)?;
1453
1454                let b = PlutusData::byte_string(self.arena, b);
1455
1456                let value = b.constant(self.arena).value(self.arena);
1457
1458                Ok(value)
1459            }
1460            DefaultFunction::UnConstrData => {
1461                let (tag, fields) = runtime.args[0]
1462                    .unwrap_constant()?
1463                    .unwrap_data()?
1464                    .unwrap_constr()?;
1465
1466                let budget = self
1467                    .costs
1468                    .builtin_costs
1469                    .get_cost(
1470                        DefaultFunction::UnConstrData,
1471                        &[cost_model::data_list_ex_mem(fields)],
1472                    )
1473                    .ok_or(MachineError::NoCostForBuiltin(
1474                        DefaultFunction::UnConstrData,
1475                    ))?;
1476
1477                self.spend_budget(budget)?;
1478
1479                let list: BumpVec<'_, _> = fields
1480                    .iter()
1481                    .map(|d| Constant::data(self.arena, d))
1482                    .collect_in(self.arena.as_bump());
1483                let list = self.arena.alloc(list);
1484
1485                let constant = Constant::proto_pair(
1486                    self.arena,
1487                    Type::integer(self.arena),
1488                    Type::list(self.arena, Type::data(self.arena)),
1489                    Constant::integer_from(self.arena, *tag as i128),
1490                    Constant::proto_list(self.arena, Type::data(self.arena), list),
1491                );
1492
1493                let value = Value::con(self.arena, constant);
1494
1495                Ok(value)
1496            }
1497            DefaultFunction::UnMapData => {
1498                let map = runtime.args[0]
1499                    .unwrap_constant()?
1500                    .unwrap_data()?
1501                    .unwrap_map()?;
1502
1503                let budget = self
1504                    .costs
1505                    .builtin_costs
1506                    .get_cost(
1507                        DefaultFunction::UnMapData,
1508                        &[cost_model::data_map_ex_mem(map)],
1509                    )
1510                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::UnMapData))?;
1511
1512                self.spend_budget(budget)?;
1513
1514                let list: BumpVec<'_, _> = map
1515                    .iter()
1516                    .map(|(k, v)| {
1517                        Constant::proto_pair(
1518                            self.arena,
1519                            Type::data(self.arena),
1520                            Type::data(self.arena),
1521                            Constant::data(self.arena, k),
1522                            Constant::data(self.arena, v),
1523                        )
1524                    })
1525                    .collect_in(self.arena.as_bump());
1526                let list = self.arena.alloc(list);
1527
1528                let constant = Constant::proto_list(
1529                    self.arena,
1530                    Type::pair(self.arena, Type::data(self.arena), Type::data(self.arena)),
1531                    list,
1532                );
1533
1534                let value = Value::con(self.arena, constant);
1535
1536                Ok(value)
1537            }
1538            DefaultFunction::UnListData => {
1539                let list = runtime.args[0]
1540                    .unwrap_constant()?
1541                    .unwrap_data()?
1542                    .unwrap_list()?;
1543
1544                let budget = self
1545                    .costs
1546                    .builtin_costs
1547                    .get_cost(
1548                        DefaultFunction::UnListData,
1549                        &[cost_model::data_list_ex_mem(list)],
1550                    )
1551                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::UnListData))?;
1552
1553                self.spend_budget(budget)?;
1554
1555                let list: BumpVec<'_, _> = list
1556                    .iter()
1557                    .map(|d| Constant::data(self.arena, d))
1558                    .collect_in(self.arena.as_bump());
1559                let list = self.arena.alloc(list);
1560
1561                let constant = Constant::proto_list(self.arena, Type::data(self.arena), list);
1562
1563                let value = Value::con(self.arena, constant);
1564
1565                Ok(value)
1566            }
1567            DefaultFunction::UnIData => {
1568                let i = runtime.args[0]
1569                    .unwrap_constant()?
1570                    .unwrap_data()?
1571                    .unwrap_integer()?;
1572
1573                let budget = self
1574                    .costs
1575                    .builtin_costs
1576                    .get_cost(
1577                        DefaultFunction::UnIData,
1578                        &[cost_model::data_integer_ex_mem(i)],
1579                    )
1580                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::UnIData))?;
1581
1582                self.spend_budget(budget)?;
1583
1584                let value = Value::integer(self.arena, i);
1585
1586                Ok(value)
1587            }
1588            DefaultFunction::UnBData => {
1589                let bs = runtime.args[0]
1590                    .unwrap_constant()?
1591                    .unwrap_data()?
1592                    .unwrap_byte_string()?;
1593
1594                let budget = self
1595                    .costs
1596                    .builtin_costs
1597                    .get_cost(
1598                        DefaultFunction::UnBData,
1599                        &[cost_model::data_byte_string_ex_mem(bs)],
1600                    )
1601                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::UnBData))?;
1602
1603                self.spend_budget(budget)?;
1604
1605                let value = Value::byte_string(self.arena, bs);
1606
1607                Ok(value)
1608            }
1609            DefaultFunction::EqualsData => {
1610                let d1 = runtime.args[0].unwrap_constant()?.unwrap_data()?;
1611                let d2 = runtime.args[1].unwrap_constant()?.unwrap_data()?;
1612
1613                let budget = self
1614                    .costs
1615                    .builtin_costs
1616                    .get_cost(
1617                        DefaultFunction::EqualsData,
1618                        &[cost_model::data_ex_mem(d1), cost_model::data_ex_mem(d2)],
1619                    )
1620                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::EqualsData))?;
1621
1622                self.spend_budget(budget)?;
1623
1624                let value = Value::bool(self.arena, d1.eq(d2));
1625
1626                Ok(value)
1627            }
1628            DefaultFunction::SerialiseData => {
1629                let arg1 = runtime.args[0].unwrap_constant()?.unwrap_data()?;
1630
1631                let budget = self
1632                    .costs
1633                    .builtin_costs
1634                    .get_cost(
1635                        DefaultFunction::SerialiseData,
1636                        &[cost_model::data_ex_mem(arg1)],
1637                    )
1638                    .ok_or(MachineError::NoCostForBuiltin(
1639                        DefaultFunction::SerialiseData,
1640                    ))?;
1641
1642                self.spend_budget(budget)?;
1643
1644                let bytes = arg1.to_bytes(self.arena)?;
1645                let value = Value::byte_string(self.arena, bytes);
1646
1647                Ok(value)
1648            }
1649            DefaultFunction::MkPairData => {
1650                let d1 = runtime.args[0].unwrap_constant()?.unwrap_data()?;
1651                let d2 = runtime.args[1].unwrap_constant()?.unwrap_data()?;
1652
1653                let budget = self
1654                    .costs
1655                    .builtin_costs
1656                    .get_cost(
1657                        DefaultFunction::MkPairData,
1658                        &[cost_model::data_ex_mem(d1), cost_model::data_ex_mem(d2)],
1659                    )
1660                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::MkPairData))?;
1661
1662                self.spend_budget(budget)?;
1663
1664                let constant = Constant::proto_pair(
1665                    self.arena,
1666                    Type::data(self.arena),
1667                    Type::data(self.arena),
1668                    Constant::data(self.arena, d1),
1669                    Constant::data(self.arena, d2),
1670                );
1671
1672                let value = Value::con(self.arena, constant);
1673
1674                Ok(value)
1675            }
1676            DefaultFunction::MkNilData => {
1677                runtime.args[0].unwrap_unit()?;
1678
1679                let budget = self
1680                    .costs
1681                    .builtin_costs
1682                    .get_cost(DefaultFunction::MkNilData, &[cost_model::UNIT_EX_MEM])
1683                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::MkNilData))?;
1684
1685                self.spend_budget(budget)?;
1686
1687                let list = BumpVec::new_in(self.arena.as_bump());
1688                let list = self.arena.alloc(list);
1689
1690                let constant = Constant::proto_list(self.arena, Type::data(self.arena), list);
1691
1692                let value = Value::con(self.arena, constant);
1693
1694                Ok(value)
1695            }
1696            DefaultFunction::MkNilPairData => {
1697                runtime.args[0].unwrap_unit()?;
1698
1699                let budget = self
1700                    .costs
1701                    .builtin_costs
1702                    .get_cost(DefaultFunction::MkNilPairData, &[cost_model::UNIT_EX_MEM])
1703                    .ok_or(MachineError::NoCostForBuiltin(
1704                        DefaultFunction::MkNilPairData,
1705                    ))?;
1706
1707                self.spend_budget(budget)?;
1708
1709                let list = BumpVec::new_in(self.arena.as_bump());
1710                let list = self.arena.alloc(list);
1711
1712                let constant = Constant::proto_list(
1713                    self.arena,
1714                    Type::pair(self.arena, Type::data(self.arena), Type::data(self.arena)),
1715                    list,
1716                );
1717
1718                let value = Value::con(self.arena, constant);
1719
1720                Ok(value)
1721            }
1722            DefaultFunction::Bls12_381_G1_Add => {
1723                let arg1 = runtime.args[0].unwrap_bls12_381_g1_element()?;
1724                let arg2 = runtime.args[1].unwrap_bls12_381_g1_element()?;
1725
1726                let budget = self
1727                    .costs
1728                    .builtin_costs
1729                    .get_cost(
1730                        DefaultFunction::Bls12_381_G1_Add,
1731                        &[
1732                            cost_model::g1_element_ex_mem(),
1733                            cost_model::g1_element_ex_mem(),
1734                        ],
1735                    )
1736                    .ok_or(MachineError::NoCostForBuiltin(
1737                        DefaultFunction::Bls12_381_G1_Add,
1738                    ))?;
1739
1740                self.spend_budget(budget)?;
1741
1742                let out = self.arena.alloc(blst::blst_p1::default());
1743
1744                unsafe {
1745                    blst::blst_p1_add_or_double(out as *mut _, arg1 as *const _, arg2 as *const _);
1746                }
1747
1748                let constant = Constant::g1(self.arena, out);
1749
1750                let value = Value::con(self.arena, constant);
1751
1752                Ok(value)
1753            }
1754            DefaultFunction::Bls12_381_G1_Neg => {
1755                let arg1 = runtime.args[0].unwrap_bls12_381_g1_element()?;
1756
1757                let budget = self
1758                    .costs
1759                    .builtin_costs
1760                    .get_cost(
1761                        DefaultFunction::Bls12_381_G1_Neg,
1762                        &[cost_model::g1_element_ex_mem()],
1763                    )
1764                    .ok_or(MachineError::NoCostForBuiltin(
1765                        DefaultFunction::Bls12_381_G1_Neg,
1766                    ))?;
1767
1768                self.spend_budget(budget)?;
1769
1770                let out = self.arena.alloc(*arg1);
1771
1772                unsafe {
1773                    // second arg was true in the Cardano code
1774                    blst::blst_p1_cneg(out as *mut _, true);
1775                }
1776
1777                let constant = Constant::g1(self.arena, out);
1778
1779                let value = Value::con(self.arena, constant);
1780
1781                Ok(value)
1782            }
1783            DefaultFunction::Bls12_381_G1_ScalarMul => {
1784                let arg1 = runtime.args[0].unwrap_integer()?;
1785                let arg2 = runtime.args[1].unwrap_bls12_381_g1_element()?;
1786
1787                let budget = self
1788                    .costs
1789                    .builtin_costs
1790                    .get_cost(
1791                        DefaultFunction::Bls12_381_G1_ScalarMul,
1792                        &[
1793                            cost_model::integer_ex_mem(arg1),
1794                            cost_model::g1_element_ex_mem(),
1795                        ],
1796                    )
1797                    .ok_or(MachineError::NoCostForBuiltin(
1798                        DefaultFunction::Bls12_381_G1_ScalarMul,
1799                    ))?;
1800
1801                self.spend_budget(budget)?;
1802
1803                let size_scalar = size_of::<blst::blst_scalar>();
1804
1805                let arg1 = arg1.mod_floor(&SCALAR_PERIOD);
1806                let (_, mut arg1) = arg1.to_bytes_be();
1807
1808                if size_scalar > arg1.len() {
1809                    let diff = size_scalar - arg1.len();
1810
1811                    let mut new_vec = vec![0; diff];
1812
1813                    new_vec.append(&mut arg1);
1814
1815                    arg1 = new_vec;
1816                }
1817
1818                let out = self.arena.alloc(blst::blst_p1::default());
1819                let scalar = self.arena.alloc(blst::blst_scalar::default());
1820
1821                unsafe {
1822                    blst::blst_scalar_from_bendian(scalar as *mut _, arg1.as_ptr() as *const _);
1823
1824                    blst::blst_p1_mult(
1825                        out as *mut _,
1826                        arg2 as *const _,
1827                        scalar.b.as_ptr() as *const _,
1828                        size_scalar * 8,
1829                    );
1830                }
1831
1832                let constant = Constant::g1(self.arena, out);
1833
1834                let value = Value::con(self.arena, constant);
1835
1836                Ok(value)
1837            }
1838            DefaultFunction::Bls12_381_G1_Equal => {
1839                let arg1 = runtime.args[0].unwrap_bls12_381_g1_element()?;
1840                let arg2 = runtime.args[1].unwrap_bls12_381_g1_element()?;
1841
1842                let budget = self
1843                    .costs
1844                    .builtin_costs
1845                    .get_cost(
1846                        DefaultFunction::Bls12_381_G1_Equal,
1847                        &[
1848                            cost_model::g1_element_ex_mem(),
1849                            cost_model::g1_element_ex_mem(),
1850                        ],
1851                    )
1852                    .ok_or(MachineError::NoCostForBuiltin(
1853                        DefaultFunction::Bls12_381_G1_Equal,
1854                    ))?;
1855
1856                self.spend_budget(budget)?;
1857
1858                let is_equal = unsafe { blst::blst_p1_is_equal(arg1, arg2) };
1859
1860                let value = Value::bool(self.arena, is_equal);
1861
1862                Ok(value)
1863            }
1864            DefaultFunction::Bls12_381_G1_Compress => {
1865                let arg1 = runtime.args[0].unwrap_bls12_381_g1_element()?;
1866
1867                let budget = self
1868                    .costs
1869                    .builtin_costs
1870                    .get_cost(
1871                        DefaultFunction::Bls12_381_G1_Compress,
1872                        &[cost_model::g1_element_ex_mem()],
1873                    )
1874                    .ok_or(MachineError::NoCostForBuiltin(
1875                        DefaultFunction::Bls12_381_G1_Compress,
1876                    ))?;
1877
1878                self.spend_budget(budget)?;
1879
1880                let out = arg1.compress(self.arena);
1881
1882                let value = Value::byte_string(self.arena, out);
1883
1884                Ok(value)
1885            }
1886            DefaultFunction::Bls12_381_G1_Uncompress => {
1887                let arg1 = runtime.args[0].unwrap_byte_string()?;
1888
1889                let budget = self
1890                    .costs
1891                    .builtin_costs
1892                    .get_cost(
1893                        DefaultFunction::Bls12_381_G1_Uncompress,
1894                        &[cost_model::byte_string_ex_mem(arg1)],
1895                    )
1896                    .ok_or(MachineError::NoCostForBuiltin(
1897                        DefaultFunction::Bls12_381_G1_Uncompress,
1898                    ))?;
1899
1900                self.spend_budget(budget)?;
1901
1902                let out = blst::blst_p1::uncompress(self.arena, arg1).map_err(MachineError::bls)?;
1903
1904                let constant = Constant::g1(self.arena, out);
1905
1906                let value = Value::con(self.arena, constant);
1907
1908                Ok(value)
1909            }
1910            DefaultFunction::Bls12_381_G1_HashToGroup => {
1911                let arg1 = runtime.args[0].unwrap_byte_string()?;
1912                let arg2 = runtime.args[1].unwrap_byte_string()?;
1913
1914                let budget = self
1915                    .costs
1916                    .builtin_costs
1917                    .get_cost(
1918                        DefaultFunction::Bls12_381_G1_HashToGroup,
1919                        &[
1920                            cost_model::byte_string_ex_mem(arg1),
1921                            cost_model::byte_string_ex_mem(arg2),
1922                        ],
1923                    )
1924                    .ok_or(MachineError::NoCostForBuiltin(
1925                        DefaultFunction::Bls12_381_G1_HashToGroup,
1926                    ))?;
1927
1928                self.spend_budget(budget)?;
1929
1930                if arg2.len() > 255 {
1931                    return Err(MachineError::hash_to_curve_dst_too_big());
1932                }
1933
1934                let out = self.arena.alloc(blst::blst_p1::default());
1935                let aug = [];
1936
1937                unsafe {
1938                    blst::blst_hash_to_g1(
1939                        out as *mut _,
1940                        arg1.as_ptr(),
1941                        arg1.len(),
1942                        arg2.as_ptr(),
1943                        arg2.len(),
1944                        aug.as_ptr(),
1945                        0,
1946                    );
1947                };
1948
1949                let constant = Constant::g1(self.arena, out);
1950
1951                let value = Value::con(self.arena, constant);
1952
1953                Ok(value)
1954            }
1955            DefaultFunction::Bls12_381_G2_Add => {
1956                let arg1 = runtime.args[0].unwrap_bls12_381_g2_element()?;
1957                let arg2 = runtime.args[1].unwrap_bls12_381_g2_element()?;
1958
1959                let budget = self
1960                    .costs
1961                    .builtin_costs
1962                    .get_cost(
1963                        DefaultFunction::Bls12_381_G2_Add,
1964                        &[
1965                            cost_model::g2_element_ex_mem(),
1966                            cost_model::g2_element_ex_mem(),
1967                        ],
1968                    )
1969                    .ok_or(MachineError::NoCostForBuiltin(
1970                        DefaultFunction::Bls12_381_G2_Add,
1971                    ))?;
1972
1973                self.spend_budget(budget)?;
1974
1975                let out = self.arena.alloc(blst::blst_p2::default());
1976
1977                unsafe {
1978                    blst::blst_p2_add_or_double(out as *mut _, arg1 as *const _, arg2 as *const _);
1979                }
1980
1981                let constant = Constant::g2(self.arena, out);
1982
1983                let value = Value::con(self.arena, constant);
1984
1985                Ok(value)
1986            }
1987            DefaultFunction::Bls12_381_G2_Neg => {
1988                let arg1 = runtime.args[0].unwrap_bls12_381_g2_element()?;
1989
1990                let budget = self
1991                    .costs
1992                    .builtin_costs
1993                    .get_cost(
1994                        DefaultFunction::Bls12_381_G2_Neg,
1995                        &[cost_model::g2_element_ex_mem()],
1996                    )
1997                    .ok_or(MachineError::NoCostForBuiltin(
1998                        DefaultFunction::Bls12_381_G2_Neg,
1999                    ))?;
2000
2001                self.spend_budget(budget)?;
2002
2003                let out = self.arena.alloc(*arg1);
2004
2005                unsafe {
2006                    // second arg was true in the Cardano code
2007                    blst::blst_p2_cneg(out as *mut _, true);
2008                }
2009
2010                let constant = Constant::g2(self.arena, out);
2011
2012                let value = Value::con(self.arena, constant);
2013
2014                Ok(value)
2015            }
2016            DefaultFunction::Bls12_381_G2_ScalarMul => {
2017                let arg1 = runtime.args[0].unwrap_integer()?;
2018                let arg2 = runtime.args[1].unwrap_bls12_381_g2_element()?;
2019
2020                let budget = self
2021                    .costs
2022                    .builtin_costs
2023                    .get_cost(
2024                        DefaultFunction::Bls12_381_G2_ScalarMul,
2025                        &[
2026                            cost_model::integer_ex_mem(arg1),
2027                            cost_model::g2_element_ex_mem(),
2028                        ],
2029                    )
2030                    .ok_or(MachineError::NoCostForBuiltin(
2031                        DefaultFunction::Bls12_381_G2_ScalarMul,
2032                    ))?;
2033
2034                self.spend_budget(budget)?;
2035
2036                let size_scalar = size_of::<blst::blst_scalar>();
2037
2038                let arg1 = arg1.mod_floor(&SCALAR_PERIOD);
2039
2040                let (_, mut arg1) = arg1.to_bytes_be();
2041
2042                if size_scalar > arg1.len() {
2043                    let diff = size_scalar - arg1.len();
2044
2045                    let mut new_vec = vec![0; diff];
2046                    unsafe {
2047                        new_vec.set_len(diff);
2048                    }
2049
2050                    new_vec.append(&mut arg1);
2051
2052                    arg1 = new_vec;
2053                }
2054
2055                let out = self.arena.alloc(blst::blst_p2::default());
2056                let scalar = self.arena.alloc(blst::blst_scalar::default());
2057
2058                unsafe {
2059                    blst::blst_scalar_from_bendian(scalar as *mut _, arg1.as_ptr() as *const _);
2060
2061                    blst::blst_p2_mult(
2062                        out as *mut _,
2063                        arg2 as *const _,
2064                        scalar.b.as_ptr() as *const _,
2065                        size_scalar * 8,
2066                    );
2067                }
2068
2069                let constant = Constant::g2(self.arena, out);
2070
2071                let value = Value::con(self.arena, constant);
2072
2073                Ok(value)
2074            }
2075            DefaultFunction::Bls12_381_G2_Equal => {
2076                let arg1 = runtime.args[0].unwrap_bls12_381_g2_element()?;
2077                let arg2 = runtime.args[1].unwrap_bls12_381_g2_element()?;
2078
2079                let budget = self
2080                    .costs
2081                    .builtin_costs
2082                    .get_cost(
2083                        DefaultFunction::Bls12_381_G2_Equal,
2084                        &[
2085                            cost_model::g2_element_ex_mem(),
2086                            cost_model::g2_element_ex_mem(),
2087                        ],
2088                    )
2089                    .ok_or(MachineError::NoCostForBuiltin(
2090                        DefaultFunction::Bls12_381_G2_Equal,
2091                    ))?;
2092
2093                self.spend_budget(budget)?;
2094
2095                let is_equal = unsafe { blst::blst_p2_is_equal(arg1, arg2) };
2096
2097                let value = Value::bool(self.arena, is_equal);
2098
2099                Ok(value)
2100            }
2101            DefaultFunction::Bls12_381_G2_Compress => {
2102                let arg1 = runtime.args[0].unwrap_bls12_381_g2_element()?;
2103
2104                let budget = self
2105                    .costs
2106                    .builtin_costs
2107                    .get_cost(
2108                        DefaultFunction::Bls12_381_G2_Compress,
2109                        &[cost_model::g2_element_ex_mem()],
2110                    )
2111                    .ok_or(MachineError::NoCostForBuiltin(
2112                        DefaultFunction::Bls12_381_G2_Compress,
2113                    ))?;
2114
2115                self.spend_budget(budget)?;
2116
2117                let out = arg1.compress(self.arena);
2118
2119                let value = Value::byte_string(self.arena, out);
2120
2121                Ok(value)
2122            }
2123            DefaultFunction::Bls12_381_G2_Uncompress => {
2124                let arg1 = runtime.args[0].unwrap_byte_string()?;
2125
2126                let budget = self
2127                    .costs
2128                    .builtin_costs
2129                    .get_cost(
2130                        DefaultFunction::Bls12_381_G2_Uncompress,
2131                        &[cost_model::byte_string_ex_mem(arg1)],
2132                    )
2133                    .ok_or(MachineError::NoCostForBuiltin(
2134                        DefaultFunction::Bls12_381_G2_Uncompress,
2135                    ))?;
2136
2137                self.spend_budget(budget)?;
2138
2139                let out = blst::blst_p2::uncompress(self.arena, arg1).map_err(MachineError::bls)?;
2140
2141                let constant = Constant::g2(self.arena, out);
2142
2143                let value = Value::con(self.arena, constant);
2144
2145                Ok(value)
2146            }
2147            DefaultFunction::Bls12_381_G2_HashToGroup => {
2148                let arg1 = runtime.args[0].unwrap_byte_string()?;
2149                let arg2 = runtime.args[1].unwrap_byte_string()?;
2150
2151                let budget = self
2152                    .costs
2153                    .builtin_costs
2154                    .get_cost(
2155                        DefaultFunction::Bls12_381_G2_HashToGroup,
2156                        &[
2157                            cost_model::byte_string_ex_mem(arg1),
2158                            cost_model::byte_string_ex_mem(arg2),
2159                        ],
2160                    )
2161                    .ok_or(MachineError::NoCostForBuiltin(
2162                        DefaultFunction::Bls12_381_G2_HashToGroup,
2163                    ))?;
2164
2165                self.spend_budget(budget)?;
2166
2167                if arg2.len() > 255 {
2168                    return Err(MachineError::hash_to_curve_dst_too_big());
2169                }
2170
2171                let out = self.arena.alloc(blst::blst_p2::default());
2172                let aug = [];
2173
2174                unsafe {
2175                    blst::blst_hash_to_g2(
2176                        out as *mut _,
2177                        arg1.as_ptr(),
2178                        arg1.len(),
2179                        arg2.as_ptr(),
2180                        arg2.len(),
2181                        aug.as_ptr(),
2182                        0,
2183                    );
2184                };
2185
2186                let constant = Constant::g2(self.arena, out);
2187
2188                let value = Value::con(self.arena, constant);
2189
2190                Ok(value)
2191            }
2192            DefaultFunction::Bls12_381_MillerLoop => {
2193                let arg1 = runtime.args[0].unwrap_bls12_381_g1_element()?;
2194                let arg2 = runtime.args[1].unwrap_bls12_381_g2_element()?;
2195
2196                let budget = self
2197                    .costs
2198                    .builtin_costs
2199                    .get_cost(
2200                        DefaultFunction::Bls12_381_MillerLoop,
2201                        &[
2202                            cost_model::g1_element_ex_mem(),
2203                            cost_model::g2_element_ex_mem(),
2204                        ],
2205                    )
2206                    .ok_or(MachineError::NoCostForBuiltin(
2207                        DefaultFunction::Bls12_381_MillerLoop,
2208                    ))?;
2209
2210                self.spend_budget(budget)?;
2211
2212                let out = self.arena.alloc(blst::blst_fp12::default());
2213
2214                let affine1 = self.arena.alloc(blst::blst_p1_affine::default());
2215                let affine2 = self.arena.alloc(blst::blst_p2_affine::default());
2216
2217                unsafe {
2218                    blst::blst_p1_to_affine(affine1 as *mut _, arg1);
2219                    blst::blst_p2_to_affine(affine2 as *mut _, arg2);
2220
2221                    blst::blst_miller_loop(out as *mut _, affine2, affine1);
2222                }
2223
2224                let constant = Constant::ml_result(self.arena, out);
2225
2226                let value = Value::con(self.arena, constant);
2227
2228                Ok(value)
2229            }
2230            DefaultFunction::Bls12_381_MulMlResult => {
2231                let arg1 = runtime.args[0].unwrap_bls12_381_ml_result()?;
2232                let arg2 = runtime.args[1].unwrap_bls12_381_ml_result()?;
2233
2234                let budget = self
2235                    .costs
2236                    .builtin_costs
2237                    .get_cost(
2238                        DefaultFunction::Bls12_381_MulMlResult,
2239                        &[
2240                            cost_model::ml_result_ex_mem(),
2241                            cost_model::ml_result_ex_mem(),
2242                        ],
2243                    )
2244                    .ok_or(MachineError::NoCostForBuiltin(
2245                        DefaultFunction::Bls12_381_MulMlResult,
2246                    ))?;
2247
2248                self.spend_budget(budget)?;
2249
2250                let out = self.arena.alloc(blst::blst_fp12::default());
2251
2252                unsafe {
2253                    blst::blst_fp12_mul(out as *mut _, arg1, arg2);
2254                }
2255
2256                let constant = Constant::ml_result(self.arena, out);
2257
2258                let value = Value::con(self.arena, constant);
2259
2260                Ok(value)
2261            }
2262            DefaultFunction::Bls12_381_FinalVerify => {
2263                let arg1 = runtime.args[0].unwrap_bls12_381_ml_result()?;
2264                let arg2 = runtime.args[1].unwrap_bls12_381_ml_result()?;
2265
2266                let budget = self
2267                    .costs
2268                    .builtin_costs
2269                    .get_cost(
2270                        DefaultFunction::Bls12_381_FinalVerify,
2271                        &[
2272                            cost_model::ml_result_ex_mem(),
2273                            cost_model::ml_result_ex_mem(),
2274                        ],
2275                    )
2276                    .ok_or(MachineError::NoCostForBuiltin(
2277                        DefaultFunction::Bls12_381_FinalVerify,
2278                    ))?;
2279
2280                self.spend_budget(budget)?;
2281
2282                let verified = unsafe { blst::blst_fp12_finalverify(arg1, arg2) };
2283
2284                let value = Value::bool(self.arena, verified);
2285
2286                Ok(value)
2287            }
2288            DefaultFunction::IntegerToByteString => {
2289                let endianness = runtime.args[0].unwrap_bool()?;
2290                let size = runtime.args[1].unwrap_integer()?;
2291                let input = runtime.args[2].unwrap_integer()?;
2292
2293                if size.is_negative() {
2294                    return Err(MachineError::integer_to_byte_string_negative_size(size));
2295                }
2296
2297                if *size > INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH.into() {
2298                    return Err(MachineError::integer_to_byte_string_size_too_big(
2299                        size,
2300                        INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH,
2301                    ));
2302                }
2303
2304                let arg1: i64 = i64::try_from(size).unwrap();
2305
2306                let arg1_exmem = if arg1 == 0 { 0 } else { ((arg1 - 1) / 8) + 1 };
2307
2308                let budget = self
2309                    .costs
2310                    .builtin_costs
2311                    .get_cost(
2312                        DefaultFunction::IntegerToByteString,
2313                        &[
2314                            cost_model::BOOL_EX_MEM,
2315                            arg1_exmem,
2316                            cost_model::integer_ex_mem(input),
2317                        ],
2318                    )
2319                    .ok_or(MachineError::NoCostForBuiltin(
2320                        DefaultFunction::IntegerToByteString,
2321                    ))?;
2322
2323                self.spend_budget(budget)?;
2324
2325                // NOTE:
2326                // We ought to also check for negative size and too large sizes. These checks
2327                // however happens prior to calling the builtin as part of the costing step. So by
2328                // the time we reach this builtin call, the size can be assumed to be
2329                //
2330                // >= 0 && < INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH
2331
2332                if size.is_zero()
2333                    && cost_model::integer_log2_x(input)
2334                        >= 8 * INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH
2335                {
2336                    let required = cost_model::integer_log2_x(input) / 8 + 1;
2337
2338                    return Err(MachineError::integer_to_byte_string_size_too_big(
2339                        constant::integer_from(self.arena, required as i128),
2340                        INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH,
2341                    ));
2342                }
2343
2344                if input.is_negative() {
2345                    return Err(MachineError::integer_to_byte_string_negative_input(input));
2346                }
2347
2348                let size_unwrapped: usize = size.try_into().unwrap();
2349
2350                if input.is_zero() {
2351                    let mut new_bytes =
2352                        BumpVec::with_capacity_in(size_unwrapped, self.arena.as_bump());
2353
2354                    unsafe {
2355                        new_bytes.set_len(size_unwrapped);
2356                    }
2357
2358                    new_bytes.fill(0);
2359
2360                    let new_bytes = self.arena.alloc(new_bytes);
2361
2362                    let value = Value::byte_string(self.arena, new_bytes);
2363
2364                    return Ok(value);
2365                }
2366
2367                let mut bytes = if endianness {
2368                    integer_to_bytes(self.arena, input, true)
2369                } else {
2370                    integer_to_bytes(self.arena, input, false)
2371                };
2372
2373                if !size.is_zero() && bytes.len() > size_unwrapped {
2374                    return Err(MachineError::integer_to_byte_string_size_too_small(
2375                        size,
2376                        bytes.len(),
2377                    ));
2378                }
2379
2380                if size_unwrapped > 0 {
2381                    let padding_size = size_unwrapped - bytes.len();
2382
2383                    let mut padding = BumpVec::with_capacity_in(padding_size, self.arena.as_bump());
2384
2385                    unsafe {
2386                        padding.set_len(padding_size);
2387                    }
2388
2389                    padding.fill(0);
2390
2391                    if endianness {
2392                        padding.append(&mut bytes);
2393
2394                        bytes = padding;
2395                    } else {
2396                        bytes.append(&mut padding);
2397                    }
2398                };
2399
2400                let bytes = self.arena.alloc(bytes);
2401
2402                let value = Value::byte_string(self.arena, bytes);
2403
2404                Ok(value)
2405            }
2406            DefaultFunction::ByteStringToInteger => {
2407                let endianness = runtime.args[0].unwrap_bool()?;
2408                let bytes = runtime.args[1].unwrap_byte_string()?;
2409
2410                let budget = self
2411                    .costs
2412                    .builtin_costs
2413                    .get_cost(
2414                        DefaultFunction::ByteStringToInteger,
2415                        &[
2416                            cost_model::BOOL_EX_MEM,
2417                            cost_model::byte_string_ex_mem(bytes),
2418                        ],
2419                    )
2420                    .ok_or(MachineError::NoCostForBuiltin(
2421                        DefaultFunction::ByteStringToInteger,
2422                    ))?;
2423
2424                self.spend_budget(budget)?;
2425
2426                let number = self.arena.alloc_integer(if endianness {
2427                    Integer::from_bytes_be(num_bigint::Sign::Plus, bytes)
2428                } else {
2429                    Integer::from_bytes_le(num_bigint::Sign::Plus, bytes)
2430                });
2431
2432                let value = Value::integer(self.arena, number);
2433
2434                Ok(value)
2435            }
2436            DefaultFunction::AndByteString => {
2437                let should_pad = runtime.args[0].unwrap_bool()?;
2438                let left_bytes = runtime.args[1].unwrap_byte_string()?;
2439                let right_bytes = runtime.args[2].unwrap_byte_string()?;
2440
2441                let budget = self
2442                    .costs
2443                    .builtin_costs
2444                    .get_cost(
2445                        DefaultFunction::AndByteString,
2446                        &[
2447                            cost_model::BOOL_EX_MEM,
2448                            cost_model::byte_string_ex_mem(left_bytes),
2449                            cost_model::byte_string_ex_mem(right_bytes),
2450                        ],
2451                    )
2452                    .ok_or(MachineError::NoCostForBuiltin(
2453                        DefaultFunction::AndByteString,
2454                    ))?;
2455
2456                self.spend_budget(budget)?;
2457
2458                let bytes_result: Vec<u8> = if should_pad {
2459                    let max_len = left_bytes.len().max(right_bytes.len());
2460                    (0..max_len)
2461                        .map(|index| {
2462                            let left_byte = left_bytes.get(index).copied().unwrap_or(0xFF);
2463                            let right_byte = right_bytes.get(index).copied().unwrap_or(0xFF);
2464                            left_byte & right_byte
2465                        })
2466                        .collect()
2467                } else {
2468                    left_bytes
2469                        .iter()
2470                        .zip(right_bytes)
2471                        .map(|(b1, b2)| b1 & b2)
2472                        .collect()
2473                };
2474                let result = self.arena.alloc(bytes_result);
2475                let value = Value::byte_string(self.arena, result);
2476                Ok(value)
2477            }
2478            DefaultFunction::OrByteString => {
2479                let should_pad = runtime.args[0].unwrap_bool()?;
2480                let left_bytes = runtime.args[1].unwrap_byte_string()?;
2481                let right_bytes = runtime.args[2].unwrap_byte_string()?;
2482
2483                let budget = self
2484                    .costs
2485                    .builtin_costs
2486                    .get_cost(
2487                        DefaultFunction::OrByteString,
2488                        &[
2489                            cost_model::BOOL_EX_MEM,
2490                            cost_model::byte_string_ex_mem(left_bytes),
2491                            cost_model::byte_string_ex_mem(right_bytes),
2492                        ],
2493                    )
2494                    .ok_or(MachineError::NoCostForBuiltin(
2495                        DefaultFunction::OrByteString,
2496                    ))?;
2497
2498                self.spend_budget(budget)?;
2499
2500                let bytes_result: Vec<u8> = if should_pad {
2501                    let max_len = left_bytes.len().max(right_bytes.len());
2502                    (0..max_len)
2503                        .map(|index| {
2504                            let left_byte = left_bytes.get(index).copied().unwrap_or(0x00);
2505                            let right_byte = right_bytes.get(index).copied().unwrap_or(0x00);
2506                            left_byte | right_byte
2507                        })
2508                        .collect()
2509                } else {
2510                    left_bytes
2511                        .iter()
2512                        .zip(right_bytes)
2513                        .map(|(b1, b2)| b1 | b2)
2514                        .collect()
2515                };
2516
2517                let result = self.arena.alloc(bytes_result);
2518                let value = Value::byte_string(self.arena, result);
2519
2520                Ok(value)
2521            }
2522            DefaultFunction::XorByteString => {
2523                let should_pad = runtime.args[0].unwrap_bool()?;
2524                let left_bytes = runtime.args[1].unwrap_byte_string()?;
2525                let right_bytes = runtime.args[2].unwrap_byte_string()?;
2526
2527                let budget = self
2528                    .costs
2529                    .builtin_costs
2530                    .get_cost(
2531                        DefaultFunction::OrByteString,
2532                        &[
2533                            cost_model::BOOL_EX_MEM,
2534                            cost_model::byte_string_ex_mem(left_bytes),
2535                            cost_model::byte_string_ex_mem(right_bytes),
2536                        ],
2537                    )
2538                    .ok_or(MachineError::NoCostForBuiltin(
2539                        DefaultFunction::XorByteString,
2540                    ))?;
2541
2542                self.spend_budget(budget)?;
2543
2544                let bytes_result: Vec<u8> = if should_pad {
2545                    let max_len = left_bytes.len().max(right_bytes.len());
2546                    (0..max_len)
2547                        .map(|index| {
2548                            let left_byte = left_bytes.get(index).copied().unwrap_or(0x00);
2549                            let right_byte = right_bytes.get(index).copied().unwrap_or(0x00);
2550                            left_byte ^ right_byte
2551                        })
2552                        .collect()
2553                } else {
2554                    left_bytes
2555                        .iter()
2556                        .zip(right_bytes)
2557                        .map(|(b1, b2)| b1 ^ b2)
2558                        .collect()
2559                };
2560
2561                let result = self.arena.alloc(bytes_result);
2562                let value = Value::byte_string(self.arena, result);
2563
2564                Ok(value)
2565            }
2566            DefaultFunction::ComplementByteString => {
2567                let bytes = runtime.args[0].unwrap_byte_string()?;
2568
2569                let budget = self
2570                    .costs
2571                    .builtin_costs
2572                    .get_cost(
2573                        DefaultFunction::ComplementByteString,
2574                        &[cost_model::byte_string_ex_mem(bytes)],
2575                    )
2576                    .ok_or(MachineError::NoCostForBuiltin(
2577                        DefaultFunction::ComplementByteString,
2578                    ))?;
2579                self.spend_budget(budget)?;
2580
2581                let result = self
2582                    .arena
2583                    .alloc(bytes.iter().map(|b| b ^ 255).collect::<Vec<_>>());
2584
2585                Ok(Value::byte_string(self.arena, result))
2586            }
2587            DefaultFunction::ReadBit => {
2588                let bytes = runtime.args[0].unwrap_byte_string()?;
2589                let bit_index = runtime.args[1].unwrap_integer()?;
2590
2591                let budget = self
2592                    .costs
2593                    .builtin_costs
2594                    .get_cost(
2595                        DefaultFunction::ReadBit,
2596                        &[
2597                            cost_model::byte_string_ex_mem(bytes),
2598                            cost_model::integer_ex_mem(bit_index),
2599                        ],
2600                    )
2601                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::ReadBit))?;
2602
2603                self.spend_budget(budget)?;
2604
2605                if bytes.is_empty() {
2606                    return Err(MachineError::empty_byte_array());
2607                }
2608
2609                if bit_index < &Integer::ZERO || bit_index >= &Integer::from(bytes.len() * 8) {
2610                    return Err(MachineError::read_bit_out_of_bounds(
2611                        bit_index,
2612                        bytes.len() * 8,
2613                    ));
2614                }
2615
2616                let (byte_index, bit_offset) = bit_index.div_rem(&8.into());
2617                let bit_offset = usize::try_from(bit_offset).unwrap();
2618
2619                let flipped_index = bytes.len() - 1 - usize::try_from(byte_index).unwrap();
2620                let byte = bytes[flipped_index];
2621
2622                let bit_test = (byte >> bit_offset) & 1 == 1;
2623
2624                Ok(Value::bool(self.arena, bit_test))
2625            }
2626            DefaultFunction::WriteBits => {
2627                let mut bytes = runtime.args[0].unwrap_byte_string()?.to_vec();
2628                let indices = runtime.args[1].unwrap_int_list()?;
2629                let set_bit = runtime.args[2].unwrap_bool()?;
2630
2631                let budget = self
2632                    .costs
2633                    .builtin_costs
2634                    .get_cost(
2635                        DefaultFunction::WriteBits,
2636                        &[
2637                            cost_model::byte_string_ex_mem(bytes.as_slice()),
2638                            cost_model::proto_list_ex_mem(indices),
2639                            cost_model::BOOL_EX_MEM,
2640                        ],
2641                    )
2642                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::WriteBits))?;
2643
2644                self.spend_budget(budget)?;
2645
2646                for index in indices {
2647                    let Constant::Integer(bit_index) = index else {
2648                        unreachable!("bit_index must be an integer")
2649                    };
2650
2651                    if *bit_index < &Integer::ZERO || *bit_index >= &Integer::from(bytes.len() * 8)
2652                    {
2653                        return Err(MachineError::write_bits_out_of_bounds(
2654                            bit_index,
2655                            bytes.len() * 8,
2656                        ));
2657                    }
2658
2659                    let (byte_index, bit_offset) = bit_index.div_rem(&8.into());
2660                    let bit_offset = usize::try_from(bit_offset).unwrap();
2661                    let flipped_index = bytes.len() - 1 - usize::try_from(byte_index).unwrap();
2662                    let bit_mask: u8 = 1 << bit_offset;
2663
2664                    if set_bit {
2665                        bytes[flipped_index] |= bit_mask;
2666                    } else {
2667                        bytes[flipped_index] &= !bit_mask;
2668                    }
2669                }
2670
2671                let result = self.arena.alloc(bytes);
2672                Ok(Value::byte_string(self.arena, result))
2673            }
2674            DefaultFunction::ReplicateByte => {
2675                let size = runtime.args[0].unwrap_integer()?;
2676                let byte = runtime.args[1].unwrap_integer()?;
2677
2678                if size.is_negative() {
2679                    return Err(MachineError::replicate_byte_negative_size(size));
2680                }
2681
2682                if *size > INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH.into() {
2683                    return Err(MachineError::replicate_byte_size_too_big(
2684                        size,
2685                        INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH,
2686                    ));
2687                }
2688
2689                let arg0: i64 = i64::try_from(size).unwrap();
2690
2691                let arg0_ex_mem = if arg0 == 0 { 0 } else { ((arg0 - 1) / 8) + 1 };
2692
2693                let budget = self
2694                    .costs
2695                    .builtin_costs
2696                    .get_cost(
2697                        DefaultFunction::ReplicateByte,
2698                        &[arg0_ex_mem, cost_model::integer_ex_mem(byte)],
2699                    )
2700                    .ok_or(MachineError::NoCostForBuiltin(
2701                        DefaultFunction::ReplicateByte,
2702                    ))?;
2703
2704                self.spend_budget(budget)?;
2705
2706                if size.is_zero()
2707                    && cost_model::integer_log2_x(byte)
2708                        >= 8 * INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH
2709                {
2710                    let required = cost_model::integer_log2_x(byte) / 8 + 1;
2711
2712                    return Err(MachineError::replicate_byte_size_too_big(
2713                        constant::integer_from(self.arena, required as i128),
2714                        INTEGER_TO_BYTE_STRING_MAXIMUM_OUTPUT_LENGTH,
2715                    ));
2716                }
2717
2718                if byte.is_negative() {
2719                    return Err(MachineError::replicate_byte_negative_input(byte));
2720                }
2721
2722                let size: usize = size.try_into().unwrap();
2723
2724                let Ok(byte) = u8::try_from(byte) else {
2725                    return Err(MachineError::outside_byte_bounds(byte));
2726                };
2727
2728                let result = if size == 0 {
2729                    self.arena.alloc(vec![])
2730                } else {
2731                    self.arena.alloc([byte].repeat(size))
2732                };
2733
2734                Ok(Value::byte_string(self.arena, result))
2735            }
2736            DefaultFunction::ShiftByteString => {
2737                let bytes = runtime.args[0].unwrap_byte_string()?;
2738                let shift = runtime.args[1].unwrap_integer()?;
2739
2740                let arg1: i64 = u64::try_from(shift.abs())
2741                    .unwrap()
2742                    .try_into()
2743                    .unwrap_or(i64::MAX);
2744
2745                let budget = self
2746                    .costs
2747                    .builtin_costs
2748                    .get_cost(
2749                        DefaultFunction::ShiftByteString,
2750                        &[cost_model::byte_string_ex_mem(bytes), arg1],
2751                    )
2752                    .ok_or(MachineError::NoCostForBuiltin(
2753                        DefaultFunction::ShiftByteString,
2754                    ))?;
2755                self.spend_budget(budget)?;
2756
2757                let length = bytes.len();
2758                let result = self.arena.alloc(vec![0; length]);
2759
2760                if Integer::from(length) * 8 <= shift.abs() {
2761                    return Ok(Value::byte_string(self.arena, result));
2762                }
2763
2764                let is_shift_left = shift >= &Integer::ZERO;
2765                let byte_shift = usize::try_from(shift.abs() / 8).unwrap();
2766                let bit_shift = usize::try_from(shift.abs() % 8).unwrap();
2767
2768                if is_shift_left {
2769                    if bit_shift == 0 {
2770                        // If we can shift entire bytes, that's much simpler
2771                        let copy_len = length - bit_shift;
2772                        // For example, consider the following byte array [1,0,1,0,1] being shifted 8 bits (1 byte)
2773                        // Result: [0,1,0,1,0]
2774                        result[..copy_len].copy_from_slice(&bytes[byte_shift..]);
2775                    } else {
2776                        // This case is a bit trickier, so let's walk through an example:
2777                        // say we are shifting the following byte string by 12 bits:
2778                        // [AB CD EF 12]
2779                        // We know we want to skip the first byte, and shift results 4 bits
2780                        // In order to shift partial bytes, we need to get the "overflow" from the next byte
2781                        // That is the complement_shift (in this case 4)
2782                        // i=0:
2783                        // src_idx = 0 + 1 = 1
2784                        // result[0] = CD << 4 = D0
2785                        // result[0] |= EF >> 4 = D0 | 0E = DE
2786                        // i=1
2787                        // src_idx = 1 + 1 = 2
2788                        // result[1] = EF << 4 = F0
2789                        // reuslt[1] |= 12 >> 4 = F0 | 01 = F1
2790                        // i=2
2791                        // src_idx = 2 + 1 = 3
2792                        // result[2] = 12 << 4 = 20
2793                        // 3 + 1  < length = false
2794                        // So our result is:
2795                        // [DE F1 20 00]
2796                        let complement_shift = 8 - bit_shift;
2797                        #[allow(clippy::needless_range_loop)]
2798                        for i in 0..(length - byte_shift) {
2799                            let src_idx = i + byte_shift;
2800
2801                            result[i] = bytes[src_idx] << bit_shift;
2802                            if src_idx + 1 < length {
2803                                result[i] |= bytes[src_idx + 1] >> complement_shift;
2804                            }
2805                        }
2806                    }
2807                } else {
2808                    // Right shift has the same logic as left shift with the inverse operations
2809                    if bit_shift == 0 {
2810                        let copy_len = length - byte_shift;
2811                        result[byte_shift..].copy_from_slice(&bytes[..copy_len]);
2812                    } else {
2813                        // See left shift case for explanation, but invert all operations
2814                        let complement_shift = 8 - bit_shift;
2815                        #[allow(clippy::needless_range_loop)]
2816                        for i in 0..(length - byte_shift) {
2817                            let dst_idx = i + byte_shift;
2818                            result[dst_idx] = bytes[i] >> bit_shift;
2819
2820                            if i > 0 {
2821                                result[dst_idx] |= bytes[i - 1] << complement_shift;
2822                            }
2823                        }
2824                    }
2825                }
2826
2827                Ok(Value::byte_string(self.arena, result))
2828            }
2829            DefaultFunction::RotateByteString => {
2830                let bytes = runtime.args[0].unwrap_byte_string()?;
2831                let shift = runtime.args[1].unwrap_integer()?;
2832
2833                let arg1: i64 = u64::try_from(shift.abs())
2834                    .unwrap()
2835                    .try_into()
2836                    .unwrap_or(i64::MAX);
2837
2838                let budget = self
2839                    .costs
2840                    .builtin_costs
2841                    .get_cost(
2842                        DefaultFunction::RotateByteString,
2843                        &[cost_model::byte_string_ex_mem(bytes), arg1],
2844                    )
2845                    .ok_or(MachineError::NoCostForBuiltin(
2846                        DefaultFunction::RotateByteString,
2847                    ))?;
2848                self.spend_budget(budget)?;
2849
2850                let length = bytes.len();
2851                let result = self.arena.alloc(bytes.to_vec());
2852
2853                if bytes.is_empty() {
2854                    return Ok(Value::byte_string(self.arena, result));
2855                }
2856
2857                let shift = shift.mod_floor(&(length * 8).into());
2858                if shift == Integer::ZERO {
2859                    return Ok(Value::byte_string(self.arena, result));
2860                }
2861                let byte_shift = usize::try_from(&shift / 8).unwrap();
2862                let bit_shift = usize::try_from(shift % 8).unwrap();
2863
2864                if bit_shift == 0 {
2865                    // left rotation is the same as shift left
2866                    // except the overflowed bits are brought to the right
2867                    let copy_len = length - byte_shift;
2868
2869                    result[..copy_len].copy_from_slice(&bytes[byte_shift..(copy_len + byte_shift)]);
2870                    result[copy_len..].copy_from_slice(&bytes[..byte_shift]);
2871                } else {
2872                    let complement_shift = 8 - bit_shift;
2873                    let wraparound_bits = bytes[0] >> complement_shift;
2874                    #[allow(clippy::needless_range_loop)]
2875                    for i in 0..(length - byte_shift) {
2876                        let src_idx = i + byte_shift;
2877
2878                        result[i] = bytes[src_idx] << bit_shift;
2879
2880                        if src_idx + 1 < length {
2881                            result[i] |= bytes[src_idx + 1] >> complement_shift;
2882                        } else if byte_shift > 0 {
2883                            result[i] |= bytes[0] >> complement_shift;
2884                        } else {
2885                            // In the case we're doing less than a full byte shift
2886                            // we still need to wrap the bit
2887                            result[i] |= wraparound_bits;
2888                        }
2889                    }
2890
2891                    for i in 0..byte_shift {
2892                        let dst_idx = length - byte_shift + i;
2893                        result[dst_idx] = bytes[i] << bit_shift;
2894
2895                        if i + 1 < byte_shift {
2896                            result[dst_idx] |= bytes[i + 1] >> complement_shift;
2897                        } else {
2898                            result[dst_idx] |= bytes[byte_shift] >> complement_shift;
2899                        }
2900                    }
2901                }
2902
2903                Ok(Value::byte_string(self.arena, result))
2904            }
2905            DefaultFunction::CountSetBits => {
2906                let bytes = runtime.args[0].unwrap_byte_string()?;
2907
2908                let budget = self
2909                    .costs
2910                    .builtin_costs
2911                    .get_cost(
2912                        DefaultFunction::CountSetBits,
2913                        &[cost_model::byte_string_ex_mem(bytes)],
2914                    )
2915                    .ok_or(MachineError::NoCostForBuiltin(
2916                        DefaultFunction::CountSetBits,
2917                    ))?;
2918                self.spend_budget(budget)?;
2919
2920                let weight: Integer = hamming::weight(bytes).into();
2921                let result = self.arena.alloc_integer(weight);
2922                Ok(Value::integer(self.arena, result))
2923            }
2924            DefaultFunction::FindFirstSetBit => {
2925                let bytes = runtime.args[0].unwrap_byte_string()?;
2926
2927                let budget = self
2928                    .costs
2929                    .builtin_costs
2930                    .get_cost(
2931                        DefaultFunction::FindFirstSetBit,
2932                        &[cost_model::byte_string_ex_mem(bytes)],
2933                    )
2934                    .ok_or(MachineError::NoCostForBuiltin(
2935                        DefaultFunction::FindFirstSetBit,
2936                    ))?;
2937                self.spend_budget(budget)?;
2938
2939                let first_bit = bytes
2940                    .iter()
2941                    .rev()
2942                    .enumerate()
2943                    .find_map(|(byte_index, &byte)| {
2944                        let reversed_byte = byte.reverse_bits();
2945                        if reversed_byte == 0 {
2946                            None
2947                        } else {
2948                            let bit_index = reversed_byte.leading_zeros() as usize;
2949                            Some(isize::try_from(bit_index + byte_index * 8).unwrap())
2950                        }
2951                    });
2952
2953                let first_bit: Integer = first_bit.unwrap_or(-1).into();
2954                let result = self.arena.alloc_integer(first_bit);
2955                Ok(Value::integer(self.arena, result))
2956            }
2957            DefaultFunction::Ripemd_160 => {
2958                use cryptoxide::{digest::Digest, ripemd160::Ripemd160};
2959                let input = runtime.args[0].unwrap_byte_string()?;
2960                let budget = self
2961                    .costs
2962                    .builtin_costs
2963                    .get_cost(
2964                        DefaultFunction::Ripemd_160,
2965                        &[cost_model::byte_string_ex_mem(input)],
2966                    )
2967                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::Ripemd_160))?;
2968                self.spend_budget(budget)?;
2969
2970                let mut hasher = Ripemd160::new();
2971                hasher.input(input);
2972                let result = self.arena.alloc(vec![0; hasher.output_bytes()]);
2973                hasher.result(result);
2974
2975                Ok(Value::byte_string(self.arena, result))
2976            }
2977            DefaultFunction::ExpModInteger => {
2978                let base = runtime.args[0].unwrap_integer()?;
2979                let exponent = runtime.args[1].unwrap_integer()?;
2980                let modulus = runtime.args[2].unwrap_integer()?;
2981
2982                let budget = self
2983                    .costs
2984                    .builtin_costs
2985                    .get_cost(
2986                        DefaultFunction::ExpModInteger,
2987                        &[
2988                            cost_model::integer_ex_mem(base),
2989                            cost_model::integer_ex_mem(exponent),
2990                            cost_model::integer_ex_mem(modulus),
2991                        ],
2992                    )
2993                    .ok_or(MachineError::NoCostForBuiltin(
2994                        DefaultFunction::ExpModInteger,
2995                    ))?;
2996                self.spend_budget(budget)?;
2997
2998                if modulus <= &Integer::ZERO {
2999                    return Err(MachineError::division_by_zero(base, modulus));
3000                }
3001
3002                let result = if exponent.is_negative() {
3003                    match base.modinv(modulus) {
3004                        Some(inv) => inv.modpow(&exponent.abs(), modulus),
3005                        None => return Err(MachineError::ExplicitErrorTerm),
3006                    }
3007                } else {
3008                    base.modpow(exponent, modulus)
3009                };
3010
3011                let value = Value::integer(self.arena, self.arena.alloc_integer(result));
3012                Ok(value)
3013            }
3014            DefaultFunction::DropList => {
3015                let elements_to_drop = runtime.args[0].unwrap_integer()?;
3016                let (list_type, list) = runtime.args[1].unwrap_list()?;
3017
3018                let arg0: i64 = u64::try_from(elements_to_drop.abs())
3019                    .unwrap()
3020                    .try_into()
3021                    .unwrap_or(i64::MAX);
3022
3023                let budget = self
3024                    .costs
3025                    .builtin_costs
3026                    .get_cost(
3027                        DefaultFunction::DropList,
3028                        &[arg0, cost_model::proto_list_ex_mem(list)],
3029                    )
3030                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::DropList))?;
3031
3032                self.spend_budget(budget)?;
3033
3034                if elements_to_drop.is_negative() {
3035                    let constant = Constant::proto_list(self.arena, list_type, list);
3036                    let value = Value::con(self.arena, constant);
3037                    return Ok(value);
3038                }
3039
3040                let elements_to_drop_usize = if *elements_to_drop > (usize::MAX as i128).into() {
3041                    list.len()
3042                } else {
3043                    usize::try_from(elements_to_drop).unwrap_or(0)
3044                };
3045
3046                let remaining_list = if elements_to_drop_usize >= list.len() {
3047                    &[]
3048                } else {
3049                    &list[elements_to_drop_usize..]
3050                };
3051
3052                let constant = Constant::proto_list(self.arena, list_type, remaining_list);
3053                let value = Value::con(self.arena, constant);
3054
3055                Ok(value)
3056            }
3057            DefaultFunction::LengthOfArray => {
3058                let (_, array) = runtime.args[0].unwrap_array()?;
3059
3060                let budget = self
3061                    .costs
3062                    .builtin_costs
3063                    .get_cost(
3064                        DefaultFunction::LengthOfArray,
3065                        &[cost_model::proto_list_ex_mem(array)],
3066                    )
3067                    .ok_or(MachineError::NoCostForBuiltin(
3068                        DefaultFunction::LengthOfArray,
3069                    ))?;
3070
3071                self.spend_budget(budget)?;
3072
3073                let result: Integer = array.len().into();
3074                let new = self.arena.alloc_integer(result);
3075                let value = Value::integer(self.arena, new);
3076
3077                Ok(value)
3078            }
3079            DefaultFunction::ListToArray => {
3080                let (list_type, list) = runtime.args[0].unwrap_list()?;
3081
3082                let budget = self
3083                    .costs
3084                    .builtin_costs
3085                    .get_cost(
3086                        DefaultFunction::ListToArray,
3087                        &[
3088                            cost_model::proto_list_ex_mem(list),
3089                            cost_model::proto_list_ex_mem(list),
3090                        ],
3091                    )
3092                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::ListToArray))?;
3093
3094                self.spend_budget(budget)?;
3095
3096                let constant = Constant::proto_array(self.arena, list_type, list);
3097
3098                let value = Value::con(self.arena, constant);
3099
3100                Ok(value)
3101            }
3102            DefaultFunction::IndexArray => {
3103                let (_, array) = runtime.args[0].unwrap_array()?;
3104                let arg1 = runtime.args[1].unwrap_integer()?;
3105
3106                let budget = self
3107                    .costs
3108                    .builtin_costs
3109                    .get_cost(
3110                        DefaultFunction::IndexArray,
3111                        &[
3112                            cost_model::proto_list_ex_mem(array),
3113                            cost_model::integer_ex_mem(arg1),
3114                        ],
3115                    )
3116                    .ok_or(MachineError::NoCostForBuiltin(DefaultFunction::IndexArray))?;
3117                self.spend_budget(budget)?;
3118
3119                let index: i128 = arg1.try_into().unwrap();
3120
3121                if 0 <= index && (index as usize) < array.len() {
3122                    let element = array[index as usize];
3123                    let value = Value::con(self.arena, element);
3124                    Ok(value)
3125                } else {
3126                    Err(MachineError::index_array_out_of_bounds(arg1, array.len()))
3127                }
3128            }
3129        }
3130    }
3131}
3132
3133fn integer_to_bytes<'a>(arena: &'a Arena, num: &'a Integer, big_endian: bool) -> BumpVec<'a, u8> {
3134    let bytes = if big_endian {
3135        num.magnitude().to_bytes_be()
3136    } else {
3137        num.magnitude().to_bytes_le()
3138    };
3139
3140    let mut result = BumpVec::with_capacity_in(bytes.len(), arena.as_bump());
3141    result.extend_from_slice(&bytes);
3142    result
3143}