Scilla标准库

Scilla 标准库包含五个库:BoolUtils.scillaIntUtils.scillaListUtils.scillaNatUtils.scillaPairUtils.scilla。 顾名思义,这些合约分别为 BoolIntXListNatPair 类型实现了实用操作。

要在合约中使用标准库中的函数,必须使用 import 声明导入相关库文件。 以下代码片段显示了如何从 ListUtilsIntUtils 库中导入函数:

import ListUtils IntUtils

import 声明必须紧接在合约自己的库声明之前,例如:

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 *)

下面,我们介绍每个库中定义的函数。

BoolUtils

  • andb : Bool -> Bool -> Bool:计算两个 Bool 值的逻辑与。

  • orb : Bool -> Bool -> Bool:计算两个 Bool 值的逻辑或。

  • negb : Bool -> Bool:计算 Bool 值的逻辑否定。

  • bool_to_string : Bool -> String:将 Bool 值转换为 String 值。 True"True"False"False"

IntUtils

  • intX_eq :IntX -> IntX -> Bool:专用于 IntX 类型的相等运算符。

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:专用于 UintX 类型的相等运算符。

  • intX_lt :IntX -> IntX -> Bool:专用于 IntX 类型的小于运算符。

  • uintX_lt :UintX -> UintX -> Bool:专用于 UintX 类型的小于运算符。

  • intX_neq :IntX -> IntX -> Bool:专用于 IntX 类型的不等运算符。

  • uintX_neq : UintX -> UintX -> Bool: 专用于 UintX 类型的不等运算符。

  • intX_le : IntX -> IntX -> Bool: 小于或等于 IntX 类型的运算符。

  • uintX_le : UintX -> UintX -> Bool: 小于或等于 UintX 类型的运算符。

  • intX_gt :IntX -> IntX -> Bool:专用于 IntX 类型的大于运算符。

  • uintX_gt :UintX -> UintX -> Bool:专用于 UintX 类型的大于运算符。

  • intX_ge : IntX -> IntX -> Bool: 大于或等于 IntX 类型的运算符。

  • uintX_ge : UintX -> UintX -> Bool: 大于或等于 UintX 类型的运算符。

ListUtils

  • list_map : ('A -> 'B) -> List 'A -> : List 'B

    f : 'A -> 'B 应用于 l : List 'A 的每个元素,构造结果的列表(类型为 List 'B)。
    (* 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

    根据谓词 f 'A -> Bool 过滤掉列表中的元素。 如果一个元素满足 f,它将在结果列表中,否则将被删除。 元素的顺序被保留。
    (*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)

    返回列表 l List 'A 的头元素作为可选值。 如果 l 的第一个元素 h 不为空,则结果为 Some h。 如果 l 为空,则结果为 None
  • list_tail : (List 'A) -> (Option List 'A)

    返回列表 l : List 'A 的尾部作为可选值。 如果 l 是形式为 Cons h t 的非空列表,则结果为 Some t。 如果 l 为空,则结果为 None
  • list_foldl_while : ('B -> 'A -> Option 'B) -> 'B -> List 'A -> 'B

    给定一个函数 f : 'B -> 'A -> Option 'B,累加器 z : 'B 以及列表 ls : List 'A ,当我们给定的函数使用 f z x : 'B 返回 Some x : Option 'B 或者列表为空,但在 None : Option 'B 的情况下提前终止,并返回 z,来执行左折叠。
(* 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)

    将第一个列表附加到第二个列表的前面,保持两个列表中元素的顺序。 请注意, list_append 在第一个参数列表的长度上具有线性时间复杂度。
  • 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

    构造一个所有元素都在一个列表中的列表。 输入列表(类型为 List List 'A)的每个元素(类型为 List 'A)都连接在一起,并保持输入列表的顺序。 请注意, list_flatten 在所有列表中的元素总数中具有线性时间复杂度。
  • list_length : List 'A -> Uint32

    计算列表中元素的数量。 请注意, list_length 在列表中的元素数量方面具有线性时间复杂度。
  • list_eq : ('A -> 'A -> Bool) -> List 'A -> List 'A -> Bool

    使用谓词函数 f : 'A -> 'A -> Bool 逐个元素比较两个列表。 如果 f 对于每对元素都返回 True,则 list_eq 返回 True。 如果 f 至少对一对元素返回 False,或者如果列表具有不同的长度,则 list_eq 返回 False
  • list_mem : ('A -> 'A -> Bool) -> 'A -> List 'A -> Bool

    检查元素 a : 'A 是否是列表 l : List'A 中的元素。 f : 'A -> 'A -> Bool 应该提供等式比较。
    (* 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

    检查列表 l : List 'A 的所有元素是否满足谓词 f : 'A -> Bool。 如果所有元素都满足 f,则 list_forall 返回 True,如果至少有一个元素不满足 f,则返回 False
  • list_exists : ('A -> Bool) -> List 'A -> Bool

    检查列表 l : List 'A 的至少一个元素是否满足谓词 f : 'A -> Bool。 如果至少有一个元素满足 f,则 list_exists 返回 True,如果没有一个元素满足 f,则返回 False
  • list_sort : ('A -> 'A -> Bool) -> List 'A -> List 'A

    使用插入排序对输入列表 l : List 'A 进行排序。 如果第一个参数小于第二个参数,则提供的比较函数 flt : 'A -> 'A -> Bool 必须返回 Truelist_sort 具有二次时间复杂度。
    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

    返回列表 l : List 'A 中满足谓词 f : 'A -> Bool 的第一个元素。 如果列表中至少有一个元素满足谓词,并且这些元素中的第一个元素是 x,则结果是 Some x。 如果没有元素满足谓词,则结果为 None
  • list_zip : List 'A -> List 'B -> List (Pair 'A 'B)

    将两个列表逐个元素组合在一起,产生一个对列表。 如果列表具有不同的长度,则最长列表的尾随元素将被忽略。
  • list_zip_with : ('A -> 'B -> 'C) -> List 'A -> List 'B -> List 'C )

    使用组合函数 f :'A -> 'B -> 'C 逐个元素地组合两个列表。 list_zip_with 的结果是将 f 应用于两个列表的元素的结果列表。 如果列表具有不同的长度,则最长列表的尾随元素将被忽略。
  • list_unzip : List (Pair 'A 'B) -> Pair (List 'A) (List 'B)

    将一个对列表拆分为一对列表,这些列表由原始列表对的元素组成。
  • list_nth : Uint32 -> List 'A -> Option 'A

    从列表中返回元素编号 n。 如果列表至少有 n 个元素,并且元素编号 nx,则 list_nth 返回 Some x。 如果列表少于 n 个元素,则 list_nth 返回 None

NatUtils

  • nat_prev : Nat -> Option Nat: 返回比当前小 1 的 Peano 数字。 如果当前数字为 Zero,则结果为 None。 如果当前数字是 Succ x,则结果是 Some x

  • nat_fold_while : ('T -> Nat -> Option 'T) -> 'T -> Nat -> 'T: 接受参数 f : 'T -> Nat -> Option 'Tz : `T 以及 m : Nat。 这是提前终止的 nat_fold。 只要 f 用新的累加器 y 返回 Some y,就继续递归。 一旦 f 返回 None,递归终止。

  • is_some_zero : Nat -> Bool:Peano 数字的零检查。

  • nat_eq : Nat -> Nat -> Bool: 专门用于 Nat 类型的相等检查。

  • nat_to_int : Nat -> Uint32: 将 Peano 数转换为其等效的 Uint32 整数。

  • uintX_to_nat : UintX -> Nat:将 UintX 整数转换为其等效的 Peano 数。该整数必须足够小,以适应 Uint32。如果不是,那么就会发生溢出错误。

  • intX_to_nat : IntX -> Nat:将 IntX 整数转换为其等效的 Peano 数。 该整数必须是非负数,并且必须足够小以适合 Uint32。 如果不是,则会发生下溢或上溢错误。

PairUtils

  • fst : Pair 'A 'B -> 'A: 提取 Pair 的第一个元素。

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: 提取 Pair 的第二个元素。

Conversions

该库提供了 b/w Scilla 类型的转换,特别是整数和字节字符串之间的转换。

为了能够为这些函数指定整数参数的编码,因此为字节序定义了一个类型。

type IntegerEncoding =
  | LittleEndian
  | BigEndian

下面的函数连同它们的主要结果,也返回 next_pos : Uint32,它指可以从输入 ByStr 值中提取任何进一步数据的位置。 这在反序列化字节流时很有用。 换句话说,next_pos 指此函数停止从输入字节字符串读取字节的位置。

  • substr_safe : ByStr -> Uint32 -> Uint32 -> Option ByStr 虽然 Scilla 提供了一个内置函数来提取字节字符串的子字符串 (ByStr),但它并不是异常安全的。 当提供不正确的参数时,它会抛出异常。 此库函数作为异常安全函数提供,用于从字符串 s : ByStr 中提取从位置 pos : Uint32 开始且长度为 len : Uint32 的子字符串。 它在成功时返回 Some ByStr,在失败时返回 None

  • extract_uint32 : IntegerEncoding -> ByStr -> Uint32 -> Option (Pair Uint32 Uint32) 从位置 pos : Uint32 开始,在 bs : ByStr 中提取一个 Uint32 的值。 成功时,返回 Some extract_uint32_value next_pos,否则返回 None

  • extract_uint64 : IntegerEncoding -> ByStr -> Uint32 -> Option (Pair Uint64 Uint32) 从位置 pos : Uint32 开始,在 bs : ByStr 中提取一个 Uint64 的值。 成功返回 Some extract_uint64_value next_pos,否则返回 None

  • extract_uint128 : IntegerEncoding -> ByStr -> Uint32 -> Option (Pair Uint128 Uint32) 从位置 pos : Uint32 开始,在 bs : ByStr 中提取一个 Uint128 的值。 成功后,会返回 Some extract_uint128_value next_pos,否则返回 None

  • extract_uint256 : IntegerEncoding -> ByStr -> Uint32 -> Option (Pair Uint256 Uint32) 从位置 pos : Uint32 开始,在 bs : ByStr 中提取一个 Uint256 的值。 成功时,返回 Some extract_uint256_value next_pos,否则返回 None

  • extract_bystr1 : ByStr -> Uint32 -> Option (Pair ByStr1 Uint32) 从位置 pos : Uint32 开始,在 bs : ByStr 中提取一个 ByStr1 的值。 成功后,会返回 Some extract_bystr1_value next_pos,否则返回 None

  • extract_bystr2 : ByStr -> Uint32 -> Option (Pair ByStr2 Uint32) 从位置 pos : Uint32 开始,在 bs : ByStr 中提取一个 ByStr2 的值。 成功时,返回 Some extract_bystr2_value next_pos,否则返回 None

  • extract_bystr20 : ByStr -> Uint32 -> Option (Pair ByStr20 Uint32) 从位置 pos : Uint32 开始,在 bs : ByStr 中提取一个 ByStr2 的值。 成功后,会返回 Some extract_bystr20_value next_pos,否则返回 None

  • extract_bystr32 : ByStr -> Uint32 -> Option (Pair ByStr32 Uint32) 从位置 pos : Uint32 开始,在 bs : ByStr 中提取一个 ByStr2 的值。 成功后,会返回 Some extract_bystr32_value next_pos,否则返回 None

  • append_uint32 : IntegerEncoding -> ByStr -> Uint32 -> ByStr 序列化一个 Uint32 的值(使用指定的编码)并将其附加到提供的 ByStr 并返回结果 ByStr

  • append_uint64 : IntegerEncoding -> ByStr -> Uint32 -> ByStr 序列化一个 Uint64 的值(使用指定的编码)并将其附加到提供的 ByStr 并返回结果 ByStr

  • append_uint128 : IntegerEncoding -> ByStr -> Uint32 -> ByStr 序列化一个 Uint128 的值(使用指定的编码)并将其附加到提供的 ByStr 并返回结果 ByStr

  • append_uint256 : IntegerEncoding -> ByStr -> Uint32 -> ByStr 序列化一个 Uint256 的值(使用指定的编码)并将其附加到提供的 ByStr 并返回结果 ByStr

Polynetwork 支持库

该库提供了用于构建 Zilliqa Polynetwork 网桥的实用函数。 这些功能从 Polynetwork 的以太坊支持 迁移而来,合约本身单独部署。