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 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 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 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 let copy_len = length - bit_shift;
2772 result[..copy_len].copy_from_slice(&bytes[byte_shift..]);
2775 } else {
2776 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 if bit_shift == 0 {
2810 let copy_len = length - byte_shift;
2811 result[byte_shift..].copy_from_slice(&bytes[..copy_len]);
2812 } else {
2813 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 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 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}