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_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
必须返回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 的以太坊支持 迁移而来,合约本身单独部署。