Skip to content

Commit

Permalink
update doc of contract def
Browse files Browse the repository at this point in the history
  • Loading branch information
vita-dounai committed Sep 17, 2020
1 parent 8b29dd4 commit 92821f8
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 9 deletions.
29 changes: 29 additions & 0 deletions docs/in_depth/containers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# 状态变量及容器

## 状态变量

Liquid中使用结构体的语法封装状态变量定义,以`struct`关键字表示。为向Liquid表明该此结构体中包含了状态变量的定义,您需要在此`struct`上添加`liquid(storage)`属性:

```rust
#[liquid(storage)]
struct HelloWorld {
name: storage::Value<String>, // 状态变量
...
}
```

在状态变量的定义中,状态变量的名称位于左侧,其后紧跟一个英语冒号及状态变量类型。注意,虽然在设计上状态变量`name``String`类型,但是我们没有直接写为`name: String`,而是写为了`name: storage::Value<String>`,其中`storage::Value`是Liquid提供的一种容器模板类型,它用于将我们对状态变量的操作转换为对区块链存储操作。使用容器对定义状态变量至关重要,事实上,若您忘记在状态变量定义中使用容器封装,Liquid将会拒绝编译合约!为了使用容器,您可以在定义状态变量之前先使用下列程序语句引入`liquid_core::storage`模块:

```rust
use liquid_core::storage;
```

```eval_rst
.. admonition:: 注意
用于定义状态变量的结构体在Liquid合约中能且仅能出现一次,同时,Liquid不允许合约中不存在状态变量的定义。
```

[HelloWorld合约](../quick_start/introduction.html#hello-world)中,我们能够容器是Liquid合约访问区块链存储的关键桥接者。

## 容器
48 changes: 48 additions & 0 deletions docs/in_depth/contract_definition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# 合约定义

您需要首先使用`use`关键字引入`liquid_lang`模块,`liquid_lang`模块中包含了用于定义合约各个组成部分的属性的实现:

```rust
use liquid_lang as liquid;
```

在引入的过程中,我们使用了`as`关键字将`liquid_lang`模块重命名为`liquid`,此后您便可以使用这个较短的名字引用`liquid_lang`模块中提供的所有功能。

Liquid使用Rust语言中的模块来定义合约,以`mod`关键字表示。您需要在定义合约的`mod`上添加`#[liquid::contract(...)]`向Liquid表明此模块包含了合约各个组成部分的定义,其中`...`是合约属性信息:

```rust
#[liquid::contract(version = "0.1.0", hash_type = "keccak256")]
mod hello_world {
// ...
}
```

您可以自行决定该模块的名字(在`mod`关键字之后),但是建议按照Rust语言代码风格为该模块取名,以防编译器向您发出抱怨。您需要向Liquid提供两种合约属性信息:

- `version`:指定所使用的Liquid版本。在未来,随着Liquid不断迭代,可能会引入不兼容的功能特性,在这种情况下,您所指定的Liquid版本将会影响Liquid所使用的合约解析方式。`version`必须以[语义化版本](https://semver.org/lang/zh-CN/)的格式给出,即版本是以英语句号`.`分割的主版本号、次版本号即及修订号。

- `hash_type`:Liquid需要在某些场合使用到哈希函数(如计算合约方法选择器、参数编码等)。`hash_type`提供了两个选项:`keccak256``sm3`,用于在不同的场景下,指定Liquid使用的哈希函数类型。当您的合约需要部署至非国密FISCO BCOS区块链平台时,您需要指定`hash_type``keccak256`以启用Keccak-256哈希算法;反之,若您的合约需要部署至国密FISCO BCOS区块链平台,则您需要指定`hash_type``sm3`以启用国密SM3哈希算法。`hash_type`属性是可选的,当您没有提供时,Liquid默认将`hash_type`设置为`keccak256`

```eval_rst
.. admonition:: 注意
为保证合约能够正常被部署、调用,请务必确认您在hash_type中所指定的哈希函数类型符合合约运行环境的要求。
```

Rust语言中的模块可见性声明主要用于控制当前模块能否被其他模块使用,但是对于Liquid合约,这种语义并无意义。为避免Liquid合约的表现与您所预期的可见性存在差异,Liquid不允许您为定义合约的`mod`添加任何可见性声明。例如,下列试图将定义合约的模块声明为公开的代码是非法的:

```rust
#[liquid::contract(version = "0.1.0", hash_type = "keccak256")]
pub mod hello_world {
// ...
}
```

除此之外,定义合约的`mod`必须是内联的,即只能使用`mod m { ... }`的形式定义,而其他方式是非法的:

```rust
#[liquid::contract(version = "0.1.0", hash_type = "keccak256")]
mod hello_world;
```

这种形式要求您必须在同一份源代码文件中提供合约的完整定义,从而保证Liquid能够立即解析您的合约。在合约定义模块的花括号间,您可以开始着手定义其他的合约组成部分,包括状态变量、合约方法、事件及自定义数据结构。
Empty file added docs/in_depth/event.md
Empty file.
3 changes: 3 additions & 0 deletions docs/in_depth/method.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
合约的所有方法需要被封装于一个由`liquid(methods)`属性标注的`impl`块中,且`impl`块的标识符需要与封装合约状态变量的`struct`的标识符相同(此合约中标识符都为"HelloWorld")

,但不能被用户或外部合约调用
10 changes: 10 additions & 0 deletions docs/in_depth/state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# 状态变量

状态变量用于在区块链存储上永久存储状态值。

## 状态合约



## 访问器

Empty file added docs/in_depth/types.md
Empty file.
18 changes: 9 additions & 9 deletions docs/quick_start/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,28 +90,28 @@ Liquid是一种[嵌入式领域特定语言](http://wiki.haskell.org/Embedded_do
51 }
```

### 合约代码剖析
### 合约代码浅析

第1行用于向编译器表明,当以非std模式(即编译为Wasm字节码)编译时,启用`no_std`属性。出于安全性的考虑,Wasm对Rust标准包的支持较为有限,因此需要启用该属性以保证您的合约能够运行在Wasm虚拟机上。

第3行用于导入`liquid_lang`包,Liquid诸多特性的实现均位于该包中。

第5~6行用于声明`alloc`包,由于我们在拼接字符串时使用了`format!`宏,而`format!`宏需要从Rust语言的基础包`alloc`中导入。

第8~51行是合约主体。本质上,合约就是一系列函数(合约方法)与数据(状态变量)的集合在Liquid中,合约方法及状态变量封装于一个由`contract`属性标注的`mod`中,其中`contract`属性的定义位于`liquid_lang`
第8~51行是合约主体。本质上,合约就是一系列函数(合约方法)与数据(状态变量)的集合在Liquid中,合约方法及状态变量封装于一个由`contract`属性标注的模块中

- 第8行声明合约了的元数据,元数据通过`contract`属性的参数传递给Liquid,主要包括要使用的Liquid版本等
- 第8行用于向Liquid表明其后跟随的`mod`中的内容是合约主体,同时,通过`contract`属性的参数将合约属性传递给Liquid,合约属性主要包括要使用的Liquid版本等

- 第12~15行定义了合约的状态变量,合约的所有状态变量需要被封装于一个由`liquid(storage)`属性标注的`struct`。在`Hello World`合约中,声明了一个名为`name`的状态变量,其类型为`Value<String>`。此处`String`是状态变量的实际类型,即字符串;而`Value`则是一种状态变量容器。读写状态变量时需要对链上持久化的状态进行访问,而`Value`容器对这些操作进行了封装,因此可以使得您像使用普通变量那样使用状态变量。在**深入学习**一章中,我们还将学习到更多容器的使用;
- 第12~15行定义了合约的状态变量。在`Hello World`合约中,声明了一个名为`name`、类型为`String`的状态变量。但是我们可以注意到,`name`的类型并没有直接写为`String`,而是写为`storage::Value<String>`。此处的`Value`一种状态变量容器,用于帮助我们访问区块链存储。

- 第17~30行定义了合约方法,合约的所有方法需要被封装于一个由`liquid(methods)`属性标注的`impl`块中,且`impl`块的标识符需要与封装合约状态变量的`struct`的标识符相同(此合约中标识符都为"HelloWorld")。在HelloWorld合约中,我们为合约定义了三个合约方法
- `new`:构造函数。在Liquid中,每个合约有且仅能有一个构造函数,且构造函数的名称必须为`new`。构造函数会在合约部署时自动执行,但不能被用户或外部合约调用。此处的构造函数用于将合约状态变量`name`初始化为"Alice";
- 第17~30行定义了合约方法。在HelloWorld合约中,我们定义了三个合约方法
- `new`:构造函数。在Liquid合约中,名称为`new`的合约方法会被认为是合约构造函数。构造函数会在合约部署时自动执行。此处的构造函数用于将合约状态变量`name`初始化为"Alice";

- `get`:法会将状态变量`name`的值拼接至字符串`"Hello, "`尾部,并将拼接后的新字符串返回给调用者;
- `get`:方法会将状态变量`name`的值拼接至字符串"Hello, "尾部,并将拼接后的新字符串返回给调用者;

- `set`方法允许调用者向其传递一个字符串参数,并使用该参数修改状态变量`name`的值。
- `set`方法允许调用者向其传递一个字符串参数,并使用该参数修改状态变量`name`的值。

第32~50行定义了一个专用于单元测试的mod。单元测试并不是合约的的一部分,而是用于在本机运行以检查合约方法实现逻辑的正确性。第32行是一个编译开关,意为只有当`test`编译标志启用时,其后跟随的`mod`才会参与编译,否则直接从代码中剔除。当将Liquid编译为Wasm字节码时, `test`编译标志不会启用,因此最后的合约字节码中不会包含任何测试。由于`mod`会进行命名空间隔离,因此我们需要在第34行从外部导入我们刚刚定义的合约符号,以方便在单元测试中使用。在`tests`模块中,我们编写了2个单元测试,分别用于测试`get`函数和`set`函数的正确性。
第32~50行定义了一个专用于单元测试的模块。单元测试并不是合约的的一部分,而是用于在本机运行,以检查合约方法实现逻辑的正确性。第32行是一个编译开关,意为只有当`test`编译标志启用时,其后跟随的模块才会参与编译,否则直接从代码中剔除。当将Liquid编译为Wasm字节码时, `test`编译标志不会启用,因此最后的合约字节码中不会包含任何测试。由于模块会进行命名空间隔离,因此我们需要在第34行从外部导入我们刚刚定义的合约符号,以方便在单元测试中使用。在`tests`模块中,我们编写了2个单元测试,分别用于测试`get`函数和`set`函数的正确性。

## Let's Liquid!

Expand Down
1 change: 1 addition & 0 deletions index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ Liquid是一种专用于为区块链底层平台[FISCO BCOS](https://fisco-bcos-
:caption: 深入学习
docs/in_depth/architecture.md
docs/in_depth/contract_definition.md
```

0 comments on commit 92821f8

Please sign in to comment.