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
124impl DefaultFunction {
125    pub fn force_count(&self) -> usize {
126        match self {
127            DefaultFunction::AddInteger => 0,
128            DefaultFunction::SubtractInteger => 0,
129            DefaultFunction::MultiplyInteger => 0,
130            DefaultFunction::DivideInteger => 0,
131            DefaultFunction::QuotientInteger => 0,
132            DefaultFunction::RemainderInteger => 0,
133            DefaultFunction::ModInteger => 0,
134            DefaultFunction::EqualsInteger => 0,
135            DefaultFunction::LessThanInteger => 0,
136            DefaultFunction::LessThanEqualsInteger => 0,
137            DefaultFunction::AppendByteString => 0,
138            DefaultFunction::ConsByteString => 0,
139            DefaultFunction::SliceByteString => 0,
140            DefaultFunction::LengthOfByteString => 0,
141            DefaultFunction::IndexByteString => 0,
142            DefaultFunction::EqualsByteString => 0,
143            DefaultFunction::LessThanByteString => 0,
144            DefaultFunction::LessThanEqualsByteString => 0,
145            DefaultFunction::Sha2_256 => 0,
146            DefaultFunction::Sha3_256 => 0,
147            DefaultFunction::Blake2b_224 => 0,
148            DefaultFunction::Blake2b_256 => 0,
149            DefaultFunction::Keccak_256 => 0,
150            DefaultFunction::VerifyEd25519Signature => 0,
151            DefaultFunction::VerifyEcdsaSecp256k1Signature => 0,
152            DefaultFunction::VerifySchnorrSecp256k1Signature => 0,
153            DefaultFunction::AppendString => 0,
154            DefaultFunction::EqualsString => 0,
155            DefaultFunction::EncodeUtf8 => 0,
156            DefaultFunction::DecodeUtf8 => 0,
157            DefaultFunction::IfThenElse => 1,
158            DefaultFunction::ChooseUnit => 1,
159            DefaultFunction::Trace => 1,
160            DefaultFunction::FstPair => 2,
161            DefaultFunction::SndPair => 2,
162            DefaultFunction::ChooseList => 2,
163            DefaultFunction::MkCons => 1,
164            DefaultFunction::HeadList => 1,
165            DefaultFunction::TailList => 1,
166            DefaultFunction::NullList => 1,
167            DefaultFunction::ChooseData => 1,
168            DefaultFunction::ConstrData => 0,
169            DefaultFunction::MapData => 0,
170            DefaultFunction::ListData => 0,
171            DefaultFunction::IData => 0,
172            DefaultFunction::BData => 0,
173            DefaultFunction::UnConstrData => 0,
174            DefaultFunction::UnMapData => 0,
175            DefaultFunction::UnListData => 0,
176            DefaultFunction::UnIData => 0,
177            DefaultFunction::UnBData => 0,
178            DefaultFunction::EqualsData => 0,
179            DefaultFunction::SerialiseData => 0,
180            DefaultFunction::MkPairData => 0,
181            DefaultFunction::MkNilData => 0,
182            DefaultFunction::MkNilPairData => 0,
183            DefaultFunction::Bls12_381_G1_Add => 0,
184            DefaultFunction::Bls12_381_G1_Neg => 0,
185            DefaultFunction::Bls12_381_G1_ScalarMul => 0,
186            DefaultFunction::Bls12_381_G1_Equal => 0,
187            DefaultFunction::Bls12_381_G1_Compress => 0,
188            DefaultFunction::Bls12_381_G1_Uncompress => 0,
189            DefaultFunction::Bls12_381_G1_HashToGroup => 0,
190            DefaultFunction::Bls12_381_G2_Add => 0,
191            DefaultFunction::Bls12_381_G2_Neg => 0,
192            DefaultFunction::Bls12_381_G2_ScalarMul => 0,
193            DefaultFunction::Bls12_381_G2_Equal => 0,
194            DefaultFunction::Bls12_381_G2_Compress => 0,
195            DefaultFunction::Bls12_381_G2_Uncompress => 0,
196            DefaultFunction::Bls12_381_G2_HashToGroup => 0,
197            DefaultFunction::Bls12_381_MillerLoop => 0,
198            DefaultFunction::Bls12_381_MulMlResult => 0,
199            DefaultFunction::Bls12_381_FinalVerify => 0,
200            DefaultFunction::IntegerToByteString => 0,
201            DefaultFunction::ByteStringToInteger => 0,
202            DefaultFunction::AndByteString => 0,
203            DefaultFunction::OrByteString => 0,
204            DefaultFunction::XorByteString => 0,
205            DefaultFunction::ComplementByteString => 0,
206            DefaultFunction::ReadBit => 0,
207            DefaultFunction::WriteBits => 0,
208            DefaultFunction::ReplicateByte => 0,
209            DefaultFunction::ShiftByteString => 0,
210            DefaultFunction::RotateByteString => 0,
211            DefaultFunction::CountSetBits => 0,
212            DefaultFunction::FindFirstSetBit => 0,
213            DefaultFunction::Ripemd_160 => 0,
214            DefaultFunction::ExpModInteger => 0,
215            DefaultFunction::DropList => 1,
216            DefaultFunction::LengthOfArray => 1,
217            DefaultFunction::ListToArray => 1,
218            DefaultFunction::IndexArray => 1,
219        }
220    }
221
222    pub fn arity(&self) -> usize {
223        match self {
224            DefaultFunction::AddInteger => 2,
225            DefaultFunction::SubtractInteger => 2,
226            DefaultFunction::MultiplyInteger => 2,
227            DefaultFunction::DivideInteger => 2,
228            DefaultFunction::QuotientInteger => 2,
229            DefaultFunction::RemainderInteger => 2,
230            DefaultFunction::ModInteger => 2,
231            DefaultFunction::EqualsInteger => 2,
232            DefaultFunction::LessThanInteger => 2,
233            DefaultFunction::LessThanEqualsInteger => 2,
234            DefaultFunction::AppendByteString => 2,
235            DefaultFunction::ConsByteString => 2,
236            DefaultFunction::SliceByteString => 3,
237            DefaultFunction::LengthOfByteString => 1,
238            DefaultFunction::IndexByteString => 2,
239            DefaultFunction::EqualsByteString => 2,
240            DefaultFunction::LessThanByteString => 2,
241            DefaultFunction::LessThanEqualsByteString => 2,
242            DefaultFunction::Sha2_256 => 1,
243            DefaultFunction::Sha3_256 => 1,
244            DefaultFunction::Blake2b_224 => 1,
245            DefaultFunction::Blake2b_256 => 1,
246            DefaultFunction::Keccak_256 => 1,
247            DefaultFunction::VerifyEd25519Signature => 3,
248            DefaultFunction::VerifyEcdsaSecp256k1Signature => 3,
249            DefaultFunction::VerifySchnorrSecp256k1Signature => 3,
250            DefaultFunction::AppendString => 2,
251            DefaultFunction::EqualsString => 2,
252            DefaultFunction::EncodeUtf8 => 1,
253            DefaultFunction::DecodeUtf8 => 1,
254            DefaultFunction::IfThenElse => 3,
255            DefaultFunction::ChooseUnit => 2,
256            DefaultFunction::Trace => 2,
257            DefaultFunction::FstPair => 1,
258            DefaultFunction::SndPair => 1,
259            DefaultFunction::ChooseList => 3,
260            DefaultFunction::MkCons => 2,
261            DefaultFunction::HeadList => 1,
262            DefaultFunction::TailList => 1,
263            DefaultFunction::NullList => 1,
264            DefaultFunction::ChooseData => 6,
265            DefaultFunction::ConstrData => 2,
266            DefaultFunction::MapData => 1,
267            DefaultFunction::ListData => 1,
268            DefaultFunction::IData => 1,
269            DefaultFunction::BData => 1,
270            DefaultFunction::UnConstrData => 1,
271            DefaultFunction::UnMapData => 1,
272            DefaultFunction::UnListData => 1,
273            DefaultFunction::UnIData => 1,
274            DefaultFunction::UnBData => 1,
275            DefaultFunction::EqualsData => 2,
276            DefaultFunction::SerialiseData => 1,
277            DefaultFunction::MkPairData => 2,
278            DefaultFunction::MkNilData => 1,
279            DefaultFunction::MkNilPairData => 1,
280            DefaultFunction::Bls12_381_G1_Add => 2,
281            DefaultFunction::Bls12_381_G1_Neg => 1,
282            DefaultFunction::Bls12_381_G1_ScalarMul => 2,
283            DefaultFunction::Bls12_381_G1_Equal => 2,
284            DefaultFunction::Bls12_381_G1_Compress => 1,
285            DefaultFunction::Bls12_381_G1_Uncompress => 1,
286            DefaultFunction::Bls12_381_G1_HashToGroup => 2,
287            DefaultFunction::Bls12_381_G2_Add => 2,
288            DefaultFunction::Bls12_381_G2_Neg => 1,
289            DefaultFunction::Bls12_381_G2_ScalarMul => 2,
290            DefaultFunction::Bls12_381_G2_Equal => 2,
291            DefaultFunction::Bls12_381_G2_Compress => 1,
292            DefaultFunction::Bls12_381_G2_Uncompress => 1,
293            DefaultFunction::Bls12_381_G2_HashToGroup => 2,
294            DefaultFunction::Bls12_381_MillerLoop => 2,
295            DefaultFunction::Bls12_381_MulMlResult => 2,
296            DefaultFunction::Bls12_381_FinalVerify => 2,
297            DefaultFunction::IntegerToByteString => 3,
298            DefaultFunction::ByteStringToInteger => 2,
299            DefaultFunction::AndByteString => 3,
300            DefaultFunction::OrByteString => 3,
301            DefaultFunction::XorByteString => 3,
302            DefaultFunction::ComplementByteString => 1,
303            DefaultFunction::ReadBit => 2,
304            DefaultFunction::WriteBits => 3,
305            DefaultFunction::ReplicateByte => 2,
306            DefaultFunction::ShiftByteString => 2,
307            DefaultFunction::RotateByteString => 2,
308            DefaultFunction::CountSetBits => 1,
309            DefaultFunction::FindFirstSetBit => 1,
310            DefaultFunction::Ripemd_160 => 1,
311            DefaultFunction::ExpModInteger => 3,
312            DefaultFunction::DropList => 2,
313            DefaultFunction::LengthOfArray => 1,
314            DefaultFunction::ListToArray => 1,
315            DefaultFunction::IndexArray => 2,
316        }
317    }
318
319    /// Check whether this builtin is available for a given Plutus ledger language
320    /// and major protocol version.
321    ///
322    /// Follows the Haskell's `builtinsIntroducedIn` mapping from plutus-ledger-api:
323    /// <https://github.com/IntersectMBO/plutus/blob/master/plutus-ledger-api/src/PlutusLedgerApi/Common/Versions.hs>
324    pub fn is_available_in(&self, plutus_version: PlutusVersion, pv: u32) -> bool {
325        use DefaultFunction::*;
326
327        // batch1: the original 51 builtins from Alonzo (PV 5)
328        let batch1 = matches!(
329            self,
330            AddInteger
331                | SubtractInteger
332                | MultiplyInteger
333                | DivideInteger
334                | QuotientInteger
335                | RemainderInteger
336                | ModInteger
337                | EqualsInteger
338                | LessThanInteger
339                | LessThanEqualsInteger
340                | AppendByteString
341                | ConsByteString
342                | SliceByteString
343                | LengthOfByteString
344                | IndexByteString
345                | EqualsByteString
346                | LessThanByteString
347                | LessThanEqualsByteString
348                | Sha2_256
349                | Sha3_256
350                | Blake2b_256
351                | VerifyEd25519Signature
352                | AppendString
353                | EqualsString
354                | EncodeUtf8
355                | DecodeUtf8
356                | IfThenElse
357                | ChooseUnit
358                | Trace
359                | FstPair
360                | SndPair
361                | ChooseList
362                | MkCons
363                | HeadList
364                | TailList
365                | NullList
366                | ChooseData
367                | ConstrData
368                | MapData
369                | ListData
370                | IData
371                | BData
372                | UnConstrData
373                | UnMapData
374                | UnListData
375                | UnIData
376                | UnBData
377                | EqualsData
378                | MkPairData
379                | MkNilData
380                | MkNilPairData
381        );
382
383        // batch2: SerialiseData (Vasil, PV 7)
384        let batch2 = matches!(self, SerialiseData);
385
386        // batch3: secp256k1 (Valentine, PV 8)
387        let batch3 = matches!(
388            self,
389            VerifyEcdsaSecp256k1Signature | VerifySchnorrSecp256k1Signature
390        );
391
392        // batch4a: BLS + Keccak + Blake2b_224 (Chang, PV 9 for V3; van Rossem, PV 11 for V1/V2)
393        let batch4a = matches!(
394            self,
395            Bls12_381_G1_Add
396                | Bls12_381_G1_Neg
397                | Bls12_381_G1_ScalarMul
398                | Bls12_381_G1_Equal
399                | Bls12_381_G1_Compress
400                | Bls12_381_G1_Uncompress
401                | Bls12_381_G1_HashToGroup
402                | Bls12_381_G2_Add
403                | Bls12_381_G2_Neg
404                | Bls12_381_G2_ScalarMul
405                | Bls12_381_G2_Equal
406                | Bls12_381_G2_Compress
407                | Bls12_381_G2_Uncompress
408                | Bls12_381_G2_HashToGroup
409                | Bls12_381_MillerLoop
410                | Bls12_381_MulMlResult
411                | Bls12_381_FinalVerify
412                | Keccak_256
413                | Blake2b_224
414        );
415
416        // batch4b: integer-bytestring conversions (Chang, PV 9 for V3; Plomin, PV 10 for V2)
417        let batch4b = matches!(self, IntegerToByteString | ByteStringToInteger);
418
419        // batch5: bitwise operations + Ripemd_160 (Plomin, PV 10 for V3)
420        let batch5 = matches!(
421            self,
422            AndByteString
423                | OrByteString
424                | XorByteString
425                | ComplementByteString
426                | ReadBit
427                | WriteBits
428                | ReplicateByte
429                | ShiftByteString
430                | RotateByteString
431                | CountSetBits
432                | FindFirstSetBit
433                | Ripemd_160
434        );
435
436        // batch6: van Rossem (PV 11) — ExpModInteger, DropList, LengthOfArray, ListToArray, IndexArray
437        // Not explicitly matched because PV >= 11 returns true for all builtins.
438
439        match plutus_version {
440            PlutusVersion::V1 => {
441                if pv >= 11 {
442                    true
443                } else {
444                    batch1
445                }
446            }
447            PlutusVersion::V2 => {
448                if pv >= 11 {
449                    true
450                } else if pv >= 10 {
451                    batch1 || batch2 || batch3 || batch4b
452                } else if pv >= 8 {
453                    batch1 || batch2 || batch3
454                } else {
455                    // PV 7
456                    batch1 || batch2
457                }
458            }
459            PlutusVersion::V3 => {
460                if pv >= 11 {
461                    true
462                } else if pv >= 10 {
463                    batch1 || batch2 || batch3 || batch4a || batch4b || batch5
464                } else {
465                    // PV 9
466                    batch1 || batch2 || batch3 || batch4a || batch4b
467                }
468            }
469        }
470    }
471}