Skip to main content

amaru_uplc/builtin/
default_function.rs

1use crate::machine::PlutusVersion;
2
3#[repr(u8)]
4#[allow(non_camel_case_types)]
5#[derive(Copy, Clone, Debug, PartialEq)]
6pub enum DefaultFunction {
7    // Integer functions
8    AddInteger = 0,
9    SubtractInteger = 1,
10    MultiplyInteger = 2,
11    DivideInteger = 3,
12    QuotientInteger = 4,
13    RemainderInteger = 5,
14    ModInteger = 6,
15    EqualsInteger = 7,
16    LessThanInteger = 8,
17    LessThanEqualsInteger = 9,
18    // ByteString functions
19    AppendByteString = 10,
20    ConsByteString = 11,
21    SliceByteString = 12,
22    LengthOfByteString = 13,
23    IndexByteString = 14,
24    EqualsByteString = 15,
25    LessThanByteString = 16,
26    LessThanEqualsByteString = 17,
27    // Cryptography and hash functions
28    Sha2_256 = 18,
29    Sha3_256 = 19,
30    Blake2b_256 = 20,
31    Keccak_256 = 71,
32    Blake2b_224 = 72,
33    VerifyEd25519Signature = 21,
34    VerifyEcdsaSecp256k1Signature = 52,
35    VerifySchnorrSecp256k1Signature = 53,
36    // String functions
37    AppendString = 22,
38    EqualsString = 23,
39    EncodeUtf8 = 24,
40    DecodeUtf8 = 25,
41    // Bool function
42    IfThenElse = 26,
43    // Unit function
44    ChooseUnit = 27,
45    // Tracing function
46    Trace = 28,
47    // Pairs functions
48    FstPair = 29,
49    SndPair = 30,
50    // List functions
51    ChooseList = 31,
52    MkCons = 32,
53    HeadList = 33,
54    TailList = 34,
55    NullList = 35,
56    // Data functions
57    // It is convenient to have a "choosing" function for a data type that has more than two
58    // constructors to get pattern matching over it and we may end up having multiple such data
59    // types, hence we include the name of the data type as a suffix.
60    ChooseData = 36,
61    ConstrData = 37,
62    MapData = 38,
63    ListData = 39,
64    IData = 40,
65    BData = 41,
66    UnConstrData = 42,
67    UnMapData = 43,
68    UnListData = 44,
69    UnIData = 45,
70    UnBData = 46,
71    EqualsData = 47,
72    SerialiseData = 51,
73    // Misc constructors
74    // Constructors that we need for constructing e.g. Data. Polymorphic builtin
75    // constructors are often problematic (See note [Representable built-in
76    // functions over polymorphic built-in types])
77    MkPairData = 48,
78    MkNilData = 49,
79    MkNilPairData = 50,
80
81    // BLS Builtins
82    Bls12_381_G1_Add = 54,
83    Bls12_381_G1_Neg = 55,
84    Bls12_381_G1_ScalarMul = 56,
85    Bls12_381_G1_Equal = 57,
86    Bls12_381_G1_Compress = 58,
87    Bls12_381_G1_Uncompress = 59,
88    Bls12_381_G1_HashToGroup = 60,
89    Bls12_381_G2_Add = 61,
90    Bls12_381_G2_Neg = 62,
91    Bls12_381_G2_ScalarMul = 63,
92    Bls12_381_G2_Equal = 64,
93    Bls12_381_G2_Compress = 65,
94    Bls12_381_G2_Uncompress = 66,
95    Bls12_381_G2_HashToGroup = 67,
96    Bls12_381_MillerLoop = 68,
97    Bls12_381_MulMlResult = 69,
98    Bls12_381_FinalVerify = 70,
99
100    // Bitwise
101    IntegerToByteString = 73,
102    ByteStringToInteger = 74,
103
104    AndByteString = 75,
105    OrByteString = 76,
106    XorByteString = 77,
107    ComplementByteString = 78,
108    ReadBit = 79,
109    WriteBits = 80,
110    ReplicateByte = 81,
111    ShiftByteString = 82,
112    RotateByteString = 83,
113    CountSetBits = 84,
114    FindFirstSetBit = 85,
115    Ripemd_160 = 86,
116
117    ExpModInteger = 87,
118    DropList = 88,
119    LengthOfArray = 89,
120    ListToArray = 90,
121    IndexArray = 91,
122
123    // BLS Multi-Scalar Multiplication
124    Bls12_381_G1_MultiScalarMul = 92,
125    Bls12_381_G2_MultiScalarMul = 93,
126
127    // Value builtins
128    InsertCoin = 94,
129    LookupCoin = 95,
130    UnionValue = 96,
131    ValueContains = 97,
132    ValueData = 98,
133    UnValueData = 99,
134    ScaleValue = 100,
135}
136
137impl DefaultFunction {
138    pub fn force_count(&self) -> usize {
139        match self {
140            DefaultFunction::AddInteger => 0,
141            DefaultFunction::SubtractInteger => 0,
142            DefaultFunction::MultiplyInteger => 0,
143            DefaultFunction::DivideInteger => 0,
144            DefaultFunction::QuotientInteger => 0,
145            DefaultFunction::RemainderInteger => 0,
146            DefaultFunction::ModInteger => 0,
147            DefaultFunction::EqualsInteger => 0,
148            DefaultFunction::LessThanInteger => 0,
149            DefaultFunction::LessThanEqualsInteger => 0,
150            DefaultFunction::AppendByteString => 0,
151            DefaultFunction::ConsByteString => 0,
152            DefaultFunction::SliceByteString => 0,
153            DefaultFunction::LengthOfByteString => 0,
154            DefaultFunction::IndexByteString => 0,
155            DefaultFunction::EqualsByteString => 0,
156            DefaultFunction::LessThanByteString => 0,
157            DefaultFunction::LessThanEqualsByteString => 0,
158            DefaultFunction::Sha2_256 => 0,
159            DefaultFunction::Sha3_256 => 0,
160            DefaultFunction::Blake2b_224 => 0,
161            DefaultFunction::Blake2b_256 => 0,
162            DefaultFunction::Keccak_256 => 0,
163            DefaultFunction::VerifyEd25519Signature => 0,
164            DefaultFunction::VerifyEcdsaSecp256k1Signature => 0,
165            DefaultFunction::VerifySchnorrSecp256k1Signature => 0,
166            DefaultFunction::AppendString => 0,
167            DefaultFunction::EqualsString => 0,
168            DefaultFunction::EncodeUtf8 => 0,
169            DefaultFunction::DecodeUtf8 => 0,
170            DefaultFunction::IfThenElse => 1,
171            DefaultFunction::ChooseUnit => 1,
172            DefaultFunction::Trace => 1,
173            DefaultFunction::FstPair => 2,
174            DefaultFunction::SndPair => 2,
175            DefaultFunction::ChooseList => 2,
176            DefaultFunction::MkCons => 1,
177            DefaultFunction::HeadList => 1,
178            DefaultFunction::TailList => 1,
179            DefaultFunction::NullList => 1,
180            DefaultFunction::ChooseData => 1,
181            DefaultFunction::ConstrData => 0,
182            DefaultFunction::MapData => 0,
183            DefaultFunction::ListData => 0,
184            DefaultFunction::IData => 0,
185            DefaultFunction::BData => 0,
186            DefaultFunction::UnConstrData => 0,
187            DefaultFunction::UnMapData => 0,
188            DefaultFunction::UnListData => 0,
189            DefaultFunction::UnIData => 0,
190            DefaultFunction::UnBData => 0,
191            DefaultFunction::EqualsData => 0,
192            DefaultFunction::SerialiseData => 0,
193            DefaultFunction::MkPairData => 0,
194            DefaultFunction::MkNilData => 0,
195            DefaultFunction::MkNilPairData => 0,
196            DefaultFunction::Bls12_381_G1_Add => 0,
197            DefaultFunction::Bls12_381_G1_Neg => 0,
198            DefaultFunction::Bls12_381_G1_ScalarMul => 0,
199            DefaultFunction::Bls12_381_G1_Equal => 0,
200            DefaultFunction::Bls12_381_G1_Compress => 0,
201            DefaultFunction::Bls12_381_G1_Uncompress => 0,
202            DefaultFunction::Bls12_381_G1_HashToGroup => 0,
203            DefaultFunction::Bls12_381_G2_Add => 0,
204            DefaultFunction::Bls12_381_G2_Neg => 0,
205            DefaultFunction::Bls12_381_G2_ScalarMul => 0,
206            DefaultFunction::Bls12_381_G2_Equal => 0,
207            DefaultFunction::Bls12_381_G2_Compress => 0,
208            DefaultFunction::Bls12_381_G2_Uncompress => 0,
209            DefaultFunction::Bls12_381_G2_HashToGroup => 0,
210            DefaultFunction::Bls12_381_MillerLoop => 0,
211            DefaultFunction::Bls12_381_MulMlResult => 0,
212            DefaultFunction::Bls12_381_FinalVerify => 0,
213            DefaultFunction::IntegerToByteString => 0,
214            DefaultFunction::ByteStringToInteger => 0,
215            DefaultFunction::AndByteString => 0,
216            DefaultFunction::OrByteString => 0,
217            DefaultFunction::XorByteString => 0,
218            DefaultFunction::ComplementByteString => 0,
219            DefaultFunction::ReadBit => 0,
220            DefaultFunction::WriteBits => 0,
221            DefaultFunction::ReplicateByte => 0,
222            DefaultFunction::ShiftByteString => 0,
223            DefaultFunction::RotateByteString => 0,
224            DefaultFunction::CountSetBits => 0,
225            DefaultFunction::FindFirstSetBit => 0,
226            DefaultFunction::Ripemd_160 => 0,
227            DefaultFunction::ExpModInteger => 0,
228            DefaultFunction::DropList => 1,
229            DefaultFunction::LengthOfArray => 1,
230            DefaultFunction::ListToArray => 1,
231            DefaultFunction::IndexArray => 1,
232            DefaultFunction::Bls12_381_G1_MultiScalarMul => 0,
233            DefaultFunction::Bls12_381_G2_MultiScalarMul => 0,
234            DefaultFunction::InsertCoin => 0,
235            DefaultFunction::LookupCoin => 0,
236            DefaultFunction::UnionValue => 0,
237            DefaultFunction::ValueContains => 0,
238            DefaultFunction::ValueData => 0,
239            DefaultFunction::UnValueData => 0,
240            DefaultFunction::ScaleValue => 0,
241        }
242    }
243
244    pub fn arity(&self) -> usize {
245        match self {
246            DefaultFunction::AddInteger => 2,
247            DefaultFunction::SubtractInteger => 2,
248            DefaultFunction::MultiplyInteger => 2,
249            DefaultFunction::DivideInteger => 2,
250            DefaultFunction::QuotientInteger => 2,
251            DefaultFunction::RemainderInteger => 2,
252            DefaultFunction::ModInteger => 2,
253            DefaultFunction::EqualsInteger => 2,
254            DefaultFunction::LessThanInteger => 2,
255            DefaultFunction::LessThanEqualsInteger => 2,
256            DefaultFunction::AppendByteString => 2,
257            DefaultFunction::ConsByteString => 2,
258            DefaultFunction::SliceByteString => 3,
259            DefaultFunction::LengthOfByteString => 1,
260            DefaultFunction::IndexByteString => 2,
261            DefaultFunction::EqualsByteString => 2,
262            DefaultFunction::LessThanByteString => 2,
263            DefaultFunction::LessThanEqualsByteString => 2,
264            DefaultFunction::Sha2_256 => 1,
265            DefaultFunction::Sha3_256 => 1,
266            DefaultFunction::Blake2b_224 => 1,
267            DefaultFunction::Blake2b_256 => 1,
268            DefaultFunction::Keccak_256 => 1,
269            DefaultFunction::VerifyEd25519Signature => 3,
270            DefaultFunction::VerifyEcdsaSecp256k1Signature => 3,
271            DefaultFunction::VerifySchnorrSecp256k1Signature => 3,
272            DefaultFunction::AppendString => 2,
273            DefaultFunction::EqualsString => 2,
274            DefaultFunction::EncodeUtf8 => 1,
275            DefaultFunction::DecodeUtf8 => 1,
276            DefaultFunction::IfThenElse => 3,
277            DefaultFunction::ChooseUnit => 2,
278            DefaultFunction::Trace => 2,
279            DefaultFunction::FstPair => 1,
280            DefaultFunction::SndPair => 1,
281            DefaultFunction::ChooseList => 3,
282            DefaultFunction::MkCons => 2,
283            DefaultFunction::HeadList => 1,
284            DefaultFunction::TailList => 1,
285            DefaultFunction::NullList => 1,
286            DefaultFunction::ChooseData => 6,
287            DefaultFunction::ConstrData => 2,
288            DefaultFunction::MapData => 1,
289            DefaultFunction::ListData => 1,
290            DefaultFunction::IData => 1,
291            DefaultFunction::BData => 1,
292            DefaultFunction::UnConstrData => 1,
293            DefaultFunction::UnMapData => 1,
294            DefaultFunction::UnListData => 1,
295            DefaultFunction::UnIData => 1,
296            DefaultFunction::UnBData => 1,
297            DefaultFunction::EqualsData => 2,
298            DefaultFunction::SerialiseData => 1,
299            DefaultFunction::MkPairData => 2,
300            DefaultFunction::MkNilData => 1,
301            DefaultFunction::MkNilPairData => 1,
302            DefaultFunction::Bls12_381_G1_Add => 2,
303            DefaultFunction::Bls12_381_G1_Neg => 1,
304            DefaultFunction::Bls12_381_G1_ScalarMul => 2,
305            DefaultFunction::Bls12_381_G1_Equal => 2,
306            DefaultFunction::Bls12_381_G1_Compress => 1,
307            DefaultFunction::Bls12_381_G1_Uncompress => 1,
308            DefaultFunction::Bls12_381_G1_HashToGroup => 2,
309            DefaultFunction::Bls12_381_G2_Add => 2,
310            DefaultFunction::Bls12_381_G2_Neg => 1,
311            DefaultFunction::Bls12_381_G2_ScalarMul => 2,
312            DefaultFunction::Bls12_381_G2_Equal => 2,
313            DefaultFunction::Bls12_381_G2_Compress => 1,
314            DefaultFunction::Bls12_381_G2_Uncompress => 1,
315            DefaultFunction::Bls12_381_G2_HashToGroup => 2,
316            DefaultFunction::Bls12_381_MillerLoop => 2,
317            DefaultFunction::Bls12_381_MulMlResult => 2,
318            DefaultFunction::Bls12_381_FinalVerify => 2,
319            DefaultFunction::IntegerToByteString => 3,
320            DefaultFunction::ByteStringToInteger => 2,
321            DefaultFunction::AndByteString => 3,
322            DefaultFunction::OrByteString => 3,
323            DefaultFunction::XorByteString => 3,
324            DefaultFunction::ComplementByteString => 1,
325            DefaultFunction::ReadBit => 2,
326            DefaultFunction::WriteBits => 3,
327            DefaultFunction::ReplicateByte => 2,
328            DefaultFunction::ShiftByteString => 2,
329            DefaultFunction::RotateByteString => 2,
330            DefaultFunction::CountSetBits => 1,
331            DefaultFunction::FindFirstSetBit => 1,
332            DefaultFunction::Ripemd_160 => 1,
333            DefaultFunction::ExpModInteger => 3,
334            DefaultFunction::DropList => 2,
335            DefaultFunction::LengthOfArray => 1,
336            DefaultFunction::ListToArray => 1,
337            DefaultFunction::IndexArray => 2,
338            DefaultFunction::Bls12_381_G1_MultiScalarMul => 2,
339            DefaultFunction::Bls12_381_G2_MultiScalarMul => 2,
340            DefaultFunction::InsertCoin => 4,
341            DefaultFunction::LookupCoin => 3,
342            DefaultFunction::UnionValue => 2,
343            DefaultFunction::ValueContains => 2,
344            DefaultFunction::ValueData => 1,
345            DefaultFunction::UnValueData => 1,
346            DefaultFunction::ScaleValue => 2,
347        }
348    }
349
350    /// Check whether this builtin is available for a given Plutus ledger language
351    /// and major protocol version.
352    ///
353    /// Follows the Haskell's `builtinsIntroducedIn` mapping from plutus-ledger-api:
354    /// <https://github.com/IntersectMBO/plutus/blob/master/plutus-ledger-api/src/PlutusLedgerApi/Common/Versions.hs>
355    pub fn is_available_in(&self, plutus_version: PlutusVersion, pv: u32) -> bool {
356        use DefaultFunction::*;
357
358        // batch1: the original 51 builtins from Alonzo (PV 5)
359        let batch1 = matches!(
360            self,
361            AddInteger
362                | SubtractInteger
363                | MultiplyInteger
364                | DivideInteger
365                | QuotientInteger
366                | RemainderInteger
367                | ModInteger
368                | EqualsInteger
369                | LessThanInteger
370                | LessThanEqualsInteger
371                | AppendByteString
372                | ConsByteString
373                | SliceByteString
374                | LengthOfByteString
375                | IndexByteString
376                | EqualsByteString
377                | LessThanByteString
378                | LessThanEqualsByteString
379                | Sha2_256
380                | Sha3_256
381                | Blake2b_256
382                | VerifyEd25519Signature
383                | AppendString
384                | EqualsString
385                | EncodeUtf8
386                | DecodeUtf8
387                | IfThenElse
388                | ChooseUnit
389                | Trace
390                | FstPair
391                | SndPair
392                | ChooseList
393                | MkCons
394                | HeadList
395                | TailList
396                | NullList
397                | ChooseData
398                | ConstrData
399                | MapData
400                | ListData
401                | IData
402                | BData
403                | UnConstrData
404                | UnMapData
405                | UnListData
406                | UnIData
407                | UnBData
408                | EqualsData
409                | MkPairData
410                | MkNilData
411                | MkNilPairData
412        );
413
414        // batch2: SerialiseData (Vasil, PV 7)
415        let batch2 = matches!(self, SerialiseData);
416
417        // batch3: secp256k1 (Valentine, PV 8)
418        let batch3 = matches!(
419            self,
420            VerifyEcdsaSecp256k1Signature | VerifySchnorrSecp256k1Signature
421        );
422
423        // batch4a: BLS + Keccak + Blake2b_224 (Chang, PV 9 for V3; van Rossem, PV 11 for V1/V2)
424        let batch4a = matches!(
425            self,
426            Bls12_381_G1_Add
427                | Bls12_381_G1_Neg
428                | Bls12_381_G1_ScalarMul
429                | Bls12_381_G1_Equal
430                | Bls12_381_G1_Compress
431                | Bls12_381_G1_Uncompress
432                | Bls12_381_G1_HashToGroup
433                | Bls12_381_G2_Add
434                | Bls12_381_G2_Neg
435                | Bls12_381_G2_ScalarMul
436                | Bls12_381_G2_Equal
437                | Bls12_381_G2_Compress
438                | Bls12_381_G2_Uncompress
439                | Bls12_381_G2_HashToGroup
440                | Bls12_381_MillerLoop
441                | Bls12_381_MulMlResult
442                | Bls12_381_FinalVerify
443                | Keccak_256
444                | Blake2b_224
445        );
446
447        // batch4b: integer-bytestring conversions (Chang, PV 9 for V3; Plomin, PV 10 for V2)
448        let batch4b = matches!(self, IntegerToByteString | ByteStringToInteger);
449
450        // batch5: bitwise operations + Ripemd_160 (Plomin, PV 10 for V3)
451        let batch5 = matches!(
452            self,
453            AndByteString
454                | OrByteString
455                | XorByteString
456                | ComplementByteString
457                | ReadBit
458                | WriteBits
459                | ReplicateByte
460                | ShiftByteString
461                | RotateByteString
462                | CountSetBits
463                | FindFirstSetBit
464                | Ripemd_160
465        );
466
467        match plutus_version {
468            PlutusVersion::V1 => {
469                if pv >= 11 {
470                    true
471                } else {
472                    batch1
473                }
474            }
475            PlutusVersion::V2 => {
476                if pv >= 11 {
477                    true
478                } else if pv >= 10 {
479                    batch1 || batch2 || batch3 || batch4b
480                } else if pv >= 8 {
481                    batch1 || batch2 || batch3
482                } else {
483                    // PV 7
484                    batch1 || batch2
485                }
486            }
487            PlutusVersion::V3 => {
488                if pv >= 11 {
489                    true
490                } else if pv >= 10 {
491                    batch1 || batch2 || batch3 || batch4a || batch4b || batch5
492                } else {
493                    // PV 9
494                    batch1 || batch2 || batch3 || batch4a || batch4b
495                }
496            }
497        }
498    }
499}