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