Scilla标准库¶
Scilla 标准库包含五个库:BoolUtils.scilla、IntUtils.scilla、ListUtils.scilla、NatUtils.scilla 和 PairUtils.scilla。 顾名思义,这些合约分别为 Bool、IntX、List、Nat 和 Pair 类型实现了实用操作。
要在合约中使用标准库中的函数,必须使用 import 声明导入相关库文件。 以下代码片段显示了如何从 ListUtils 和 IntUtils 库中导入函数:
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 thatlist_reversehas 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必须返回True。list_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个元素,并且元素编号n为x,则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 'T、z : `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 的以太坊支持 迁移而来,合约本身单独部署。