UNPKG

namillum

Version:
416 lines (333 loc) 16.5 kB
--- title: The Scilla Standard Library --- ::: {#stdlib} The Scilla standard library contains five libraries: `BoolUtils.scilla`, `IntUtils.scilla`, `ListUtils.scilla`, `NatUtils.scilla` and `PairUtils.scilla`. As the names suggests these contracts implement utility operations for the `Bool`, `IntX`, `List`, `Nat` and `Pair` types, respectively. ::: To use functions from the standard library in a contract, the relevant library file must be imported using the `import` declaration. The following code snippet shows how to import the functions from the `ListUtils` and `IntUtils` libraries: ```ocaml import ListUtils IntUtils ``` The `import` declaration must occur immediately before the contract\'s own library declaration, e.g.: ```ocaml import ListUtils IntUtils library WalletLib ... (* The declarations of the contract's own library values and functions *) contract Wallet ( ... ) ... (* The transitions and procedures of the contract *) ``` Below, we present the functions defined in each of the library. ## BoolUtils - `andb : Bool -> Bool -> Bool`: Computes the logical AND of two `Bool` values. - `orb : Bool -> Bool -> Bool`: Computes the logical OR of two `Bool` values. - `negb : Bool -> Bool`: Computes the logical negation of a `Bool` value. - `bool_to_string : Bool -> String`: Transforms a `Bool` value into a `String` value. `True` is transformed into `"True"`, and `False` is transformed into `"False"`. ## IntUtils - `intX_eq : IntX -> IntX -> Bool`: Equality operator specialised for each `IntX` type. ```ocaml let int_list_eq = @list_eq Int64 in let one = Int64 1 in let two = Int64 2 in let ten = Int64 10 in let eleven = Int64 11 in let nil = Nil {Int64} in let l1 = Cons {Int64} eleven nil in let l2 = Cons {Int64} ten l1 in let l3 = Cons {Int64} two l2 in let l4 = Cons {Int64} one l3 in let f = int64_eq in (* See if [2,10,11] = [1,2,10,11] *) int_list_eq f l3 l4 ``` - `uintX_eq : UintX -> UintX -> Bool`: Equality operator specialised for each `UintX` type. - `intX_lt : IntX -> IntX -> Bool`: Less-than operator specialised for each `IntX` type. - `uintX_lt : UintX -> UintX -> Bool`: Less-than operator specialised for each `UintX` type. - `intX_neq : IntX -> IntX -> Bool`: Not-equal operator specialised for each `IntX` type. - `uintX_neq : UintX -> UintX -> Bool`: Not-equal operator specialised for each `UintX` type. - `intX_le : IntX -> IntX -> Bool`: Less-than-or-equal operator specialised for each `IntX` type. - `uintX_le : UintX -> UintX -> Bool`: Less-than-or-equal operator specialised for each `UintX` type. - `intX_gt : IntX -> IntX -> Bool`: Greater-than operator specialised for each `IntX` type. - `uintX_gt : UintX -> UintX -> Bool`: Greater-than operator specialised for each `UintX` type. - `intX_ge : IntX -> IntX -> Bool`: Greater-than-or-equal operator specialised for each `IntX` type. - `uintX_ge : UintX -> UintX -> Bool`: Greater-than-or-equal operator specialised for each `UintX` type. ## ListUtils - `list_map : ('A -> 'B) -> List 'A -> : List 'B`. | Apply `f : 'A -> 'B` to every element of `l : List 'A`, constructing a list (of type `List 'B`) of the results. ```ocaml (* Library *) let f = fun (a : Int32) => builtin sha256hash a (* Contract transition *) (* Assume input is the list [ 1 ; 2 ; 3 ] *) (* Apply f to all values in input *) hash_list_int32 = @list_map Int32 ByStr32; hashed_list = hash_list_int32 f input; (* hashed_list is now [ sha256hash 1 ; sha256hash 2 ; sha256hash 3 ] *) ``` - `list_filter : ('A -> Bool) -> List 'A -> List 'A`. | Filter out elements on the list based on the predicate `f : 'A -> Bool`. If an element satisfies `f`, it will be in the resultant list, otherwise it is removed. The order of the elements is preserved. ```ocaml (*Library*) let f = fun (a : Int32) => let ten = Int32 10 in builtin lt a ten (* Contract transition *) (* Assume input is the list [ 1 ; 42 ; 2 ; 11 ; 12 ] *) less_ten_int32 = @list_filter Int32; less_ten_list = less_ten_int32 f l (* less_ten_list is now [ 1 ; 2 ]*) ``` - `list_head : (List 'A) -> (Option 'A)`. | Return the head element of a list `l : List 'A` as an optional value. If `l` is not empty with the first element `h`, the result is `Some h`. If `l` is empty, then the result is `None`. - `list_tail : (List 'A) -> (Option List 'A)`. | Return the tail of a list `l : List 'A` as an optional value. If `l` is a non-empty list of the form `Cons h t`, then the result is `Some t`. If `l` is empty, then the result is `None`. - `list_foldl_while : ('B -> 'A -> Option 'B) -> 'B -> List 'A -> 'B` | Given a function `f : 'B -> 'A -> Option 'B`, accumulator `z : 'B` and list `ls : List 'A` execute a left fold when our given function returns `Some x : Option 'B` using `f z x : 'B` or list is empty but in the case of `None : Option 'B` terminate early, returning `z`. ```ocaml (* assume zero = 0, one = 1, negb is in scope and ls = [10,12,9,7] given a max and list with elements a_0, a_1, ..., a_m find largest n s.t. sum of i from 0 to (n-1) a_i <= max *) let prefix_step = fun (len_limit : Pair Uint32 Uint32) => fun (x : Uint32) => match len_limit with | Pair len limit => let limit_lt_x = builtin lt limit x in let x_leq_limit = negb limit_lt_x in match x_leq_limit with | True => let len_succ = builtin add len one in let l_sub_x = builtin sub limit x in let res = Pair {Uint32 Uint32} len_succ l_sub_x in Some {(Pair Uint32 Uint32)} res | False => None {(Pair Uint32 Uint32)} end end in let fold_while = @list_foldl_while Uint32 (Pair Uint32 Uint32) in let max = Uint32 31 in let init = Pair {Uint32 Uint32} zero max in let prefix_length = fold_while prefix_step init ls in match prefix_length with | Pair length _ => length end ``` - `list_append : (List 'A -> List 'A -> List 'A)`. | Append the first list to the front of the second list, keeping the order of the elements in both lists. Note that `list_append` has linear time complexity in the length of the first argument list. - `list_reverse : (List 'A -> List 'A)`. | Return the reverse of the input list. Note that `list_reverse` has linear time complexity in the length of the argument list. - `list_flatten : (List List 'A) -> List 'A`. | Construct a list of all the elements in a list of lists. Each element (which has type `List 'A`) of the input list (which has type `List List 'A`) are all concatenated together, keeping the order of the input list. Note that `list_flatten` has linear time complexity in the total number of elements in all of the lists. - `list_length : List 'A -> Uint32` | Count the number of elements in a list. Note that `list_length` has linear time complexity in the number of elements in the list. - `list_eq : ('A -> 'A -> Bool) -> List 'A -> List 'A -> Bool`. | Compare two lists element by element, using a predicate function `f : 'A -> 'A -> Bool`. If `f` returns `True` for every pair of elements, then `list_eq` returns `True`. If `f` returns `False` for at least one pair of elements, or if the lists have different lengths, then `list_eq` returns `False`. - `list_mem : ('A -> 'A -> Bool) -> 'A -> List 'A -> Bool`. | Checks whether an element `a : 'A` is an element in the list `l : List'A`. `f : 'A -> 'A -> Bool` should be provided for equality comparison. ```ocaml (* Library *) let f = fun (a : Int32) => fun (b : Int32) => builtin eq a b (* Contract transition *) (* Assume input is the list [ 1 ; 2 ; 3 ; 4 ] *) keynumber = Int32 5; list_mem_int32 = @list_mem Int32; check_result = list_mem_int32 f keynumber input; (* check_result is now False *) ``` - `list_forall : ('A -> Bool) -> List 'A -> Bool`. | Check whether all elements of list `l : List 'A` satisfy the predicate `f : 'A -> Bool`. `list_forall` returns `True` if all elements satisfy `f`, and `False` if at least one element does not satisfy `f`. - `list_exists : ('A -> Bool) -> List 'A -> Bool`. | Check whether at least one element of list `l : List 'A` satisfies the predicate `f : 'A -> Bool`. `list_exists` returns `True` if at least one element satisfies `f`, and `False` if none of the elements satisfy `f`. - `list_sort : ('A -> 'A -> Bool) -> List 'A -> List 'A`. | Sort the input list `l : List 'A` using insertion sort. The comparison function `flt : 'A -> 'A -> Bool` provided must return `True` if its first argument is less than its second argument. `list_sort` has quadratic time complexity. ```ocaml let int_sort = @list_sort Uint64 in let flt = fun (a : Uint64) => fun (b : Uint64) => builtin lt a b let zero = Uint64 0 in let one = Uint64 1 in let two = Uint64 2 in let three = Uint64 3 in let four = Uint64 4 in (* l6 = [ 3 ; 2 ; 1 ; 2 ; 3 ; 4 ; 2 ] *) let l6 = let nil = Nil {Uint64} in let l0 = Cons {Uint64} two nil in let l1 = Cons {Uint64} four l0 in let l2 = Cons {Uint64} three l1 in let l3 = Cons {Uint64} two l2 in let l4 = Cons {Uint64} one l3 in let l5 = Cons {Uint64} two l4 in Cons {Uint64} three l5 (* res1 = [ 1 ; 2 ; 2 ; 2 ; 3 ; 3 ; 4 ] *) let res1 = int_sort flt l6 ``` - `list_find : ('A -> Bool) -> List 'A -> Option 'A`. | Return the first element in a list `l : List 'A` satisfying the predicate `f : 'A -> Bool`. If at least one element in the list satisfies the predicate, and the first one of those elements is `x`, then the result is `Some x`. If no element satisfies the predicate, the result is `None`. - `list_zip : List 'A -> List 'B -> List (Pair 'A 'B)`. | Combine two lists element by element, resulting in a list of pairs. If the lists have different lengths, the trailing elements of the longest list are ignored. - `list_zip_with : ('A -> 'B -> 'C) -> List 'A -> List 'B -> List 'C )`. | Combine two lists element by element using a combining function `f : 'A -> 'B -> 'C`. The result of `list_zip_with` is a list of the results of applying `f` to the elements of the two lists. If the lists have different lengths, the trailing elements of the longest list are ignored. - `list_unzip : List (Pair 'A 'B) -> Pair (List 'A) (List 'B)`. | Split a list of pairs into a pair of lists consisting of the elements of the pairs of the original list. - `list_nth : Uint32 -> List 'A -> Option 'A`. | Return the element number `n` from a list. If the list has at least `n` elements, and the element number `n` is `x`, `list_nth` returns `Some x`. If the list has fewer than `n` elements, `list_nth` returns `None`. ## NatUtils - `nat_prev : Nat -> Option Nat`: Return the Peano number one less than the current one. If the current number is `Zero`, the result is `None`. If the current number is `Succ x`, then the result is `Some x`. - `nat_fold_while : ('T -> Nat -> Option 'T) -> 'T -> Nat -> 'T`: Takes arguments `f : 'T -> Nat -> Option 'T`, `` z : `T `` and `m : Nat`. This is `nat_fold` with early termination. Continues recursing so long as `f` returns `Some y` with new accumulator `y`. Once `f` returns `None`, the recursion terminates. - `is_some_zero : Nat -> Bool`: Zero check for Peano numbers. - `nat_eq : Nat -> Nat -> Bool`: Equality check specialised for the `Nat` type. - `nat_to_int : Nat -> Uint32`: Convert a Peano number to its equivalent `Uint32` integer. - `uintX_to_nat : UintX -> Nat`: Convert a `UintX` integer to its equivalent Peano number. The integer must be small enough to fit into a `Uint32`. If it is not, then an overflow error will occur. - `intX_to_nat : IntX -> Nat`: Convert an `IntX` integer to its equivalent Peano number. The integer must be non-negative, and must be small enough to fit into a `Uint32`. If it is not, then an underflow or overflow error will occur. ## PairUtils - `fst : Pair 'A 'B -> 'A`: Extract the first element of a Pair. ```ocaml let fst_strings = @fst String String in let nick_name = "toby" in let dog = "dog" in let tobias = Pair {String String} nick_name dog in fst_strings tobias ``` - `snd : Pair 'A 'B -> 'B`: Extract the second element of a Pair. ## Conversions This library provides conversions b/w Scilla types, particularly between integers and byte strings. To enable specifying the encoding of integer arguments to these functions, a type is defined for endianness. ```ocaml type IntegerEncoding = | LittleEndian | BigEndian ``` The functions below, along with their primary result, also return `next_pos : Uint32` which indicates the position from which any further data extraction from the input `ByStr` value can proceed. This is useful when deserializing a byte stream. In other words, `next_pos` indicates where this function stopped reading bytes from the input byte string. - `substr_safe : ByStr -> Uint32 -> Uint32 -> Option ByStr` While Scilla provides a builtin to extract substrings of byte strings (`ByStr`), it is not exception safe. When provided incorrect arguments, it throws exceptions. This library function is provided as an exception safe function to extract, from a string `s : ByStr`, a substring starting at position `pos : Uint32` and of length `len : Uint32`. It returns `Some ByStr` on success and `None` on failure. - `extract_uint32 : IntegerEncoding -> ByStr -> Uint32 -> Option (Pair Uint32 Uint32)` Extracts a `Uint32` value from `bs : ByStr`, starting at position `pos : Uint32`. On success, `Some extracted_uint32_value next_pos` is returned. `None` otherwise. - `extract_uint64 : IntegerEncoding -> ByStr -> Uint32 -> Option (Pair Uint64 Uint32)` Extracts a `Uint64` value from `bs : ByStr`, starting at position `pos : Uint32`. On success, `Some extracted_uint64_value next_pos` is returned. `None` otherwise. - `extract_uint128 : IntegerEncoding -> ByStr -> Uint32 -> Option (Pair Uint128 Uint32)` Extracts a Uint128 value from `bs : ByStr`, starting at position `pos : Uint32`. On success, `Some extracted_uint128_value next_pos` is returned. `None` otherwise. - `extract_uint256 : IntegerEncoding -> ByStr -> Uint32 -> Option (Pair Uint256 Uint32)` Extracts a `Uint256` value from `bs : ByStr`, starting at position `pos : Uint32`. On success, `Some extracted_uint256_value next_pos` is returned. `None` otherwise. - `extract_bystr1 : ByStr -> Uint32 -> Option (Pair ByStr1 Uint32)` Extracts a `ByStr1` value from `bs : ByStr`, starting at position `pos : Uint32`. On success, `Some extracted_bystr1_value next_pos` is returned. `None` otherwise. - `extract_bystr2 : ByStr -> Uint32 -> Option (Pair ByStr2 Uint32)` Extracts a `ByStr2` value from `bs : ByStr`, starting at position `pos : Uint32`. On success, `Some extracted_bystr2_value next_pos` is returned. `None` otherwise. - `extract_bystr20 : ByStr -> Uint32 -> Option (Pair ByStr20 Uint32)` Extracts a `ByStr2` value from `bs : ByStr`, starting at position `pos : Uint32`. On success, `Some extracted_bystr20_value next_pos` is returned. `None` otherwise. - `extract_bystr32 : ByStr -> Uint32 -> Option (Pair ByStr32 Uint32)` Extracts a `ByStr2` value from `bs : ByStr`, starting at position `pos : Uint32`. On success, `Some extracted_bystr32_value next_pos` is returned. `None` otherwise. - `append_uint32 : IntegerEncoding -> ByStr -> Uint32 -> ByStr` Serialize a `Uint32` value (with the specified encoding) and append it to the provided `ByStr` and return the result `ByStr`. - `append_uint64 : IntegerEncoding -> ByStr -> Uint32 -> ByStr` Serialize a `Uint64` value (with the specified encoding) and append it to the provided `ByStr` and return the result `ByStr`. - `append_uint128 : IntegerEncoding -> ByStr -> Uint32 -> ByStr` Serialize a `Uint128` value (with the specified encoding) and append it to the provided `ByStr` and return the result `ByStr`. - `append_uint256 : IntegerEncoding -> ByStr -> Uint32 -> ByStr` Serialize a `Uint256` value (with the specified encoding) and append it to the provided `ByStr` and return the result `ByStr`. ## Polynetwork Support Library This library provides utility functions used in building the Zilliqa Polynetwork bridge. These functions are migrated from [Polynetwork\'s ethereum support](https://github.com/polynetwork/eth-contracts/tree/master/contracts/core/cross_chain_manager), with the contract itself separately deployed.