-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cf1f700
commit 5bfbf05
Showing
3 changed files
with
124 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# 事件 | ||
|
||
事件是区块链底层虚拟机日志基础设施提供的一个便利接口。当触发事件时,事件中的参数存储到交易收据的日志字段中,日志时一种特殊的数据结构,这些日志与合约地址关联,并随交易收据记录到区块链中。每条交易收据中可以包含0条或多条日志记录,其代表了智能合约出发的事件。在DApp应用中,如果监听了某事件,则当该事件发生时,便会触发应用的回调。 | ||
|
||
## 创建事件 | ||
|
||
Liquid中使用结构体语法定义事件,以`struct`关键字表示。结构体中的每一个字段便是事件的参数,为向Liquid表明该此结构体定义了事件,您需要为此结构体添加`#[liquid(event)]`属性: | ||
|
||
```rust | ||
#[liquid(event)] | ||
struct Foo { | ||
s: String, | ||
i: i32, | ||
} | ||
``` | ||
|
||
如上述代码所示,我们定义了一个名为Foo的事件,事件中包含两个参数,分别为`String`及`i32`。更进一步,您还可以使用`#[liquid(indexed)]`属性将事件参数指定为可被索引: | ||
|
||
```rust | ||
#[liquid(event)] | ||
struct Foo { | ||
#[liquid(indexed)] | ||
s: String, | ||
i: i32, | ||
} | ||
``` | ||
|
||
被索引的参数本身不会被保存,但是Dapp应用可以通过被索引参数的值来对事件进行检索。在Liquid中,一个事件最多可有四个值用于被索引,但是第一个索引值恒定为事件签名(事件名及其参数类型)的哈希值,因此在事件定义中,您最多可以将三个参数被标注为`#[liquid(indexed)]`。 | ||
|
||
与状态变量定义类似,不能为定义事件的结构体添加可见性声明或模板参数,但和状态变量定义不同的时,其内部每个字段也不允许添加可见性声明。事件参数及索引参数的类型均受到限制,具体的限制可参考[类型](../types.html)一节。 | ||
|
||
## 触发事件 | ||
|
||
在Liquid中,通过环境对象触发事件。环境对象由Liquid自动为您生成,您可以在合约方法中通过调用`self.env()`来获取环境对象。获取环境对象后,您可以调用环境对象的`emit`方法来触发我们在上面定义的事件: | ||
|
||
```rust | ||
self.env().emit(Foo { | ||
s: String::from("hello"), | ||
i: 42, | ||
}) | ||
``` | ||
|
||
如上述代码所示,`emit`方法以事件实例为参数,而事件实例可通过结构体初始化语法直接进行构造。提供给`emit`方法的参数的类型一定需要是事件类型(即存在`#[liquid(event)]`属性标注),否则在编译会抛出类型不匹配的错误。触发事件后,对应交易的回执中会多出一条日志记录: | ||
|
||
```json | ||
"logs": [ | ||
{ | ||
"address": "0x6119432a43a2a5da27f31fa4912f1c43400b1690", | ||
"data": "0x00000000000000000000000000000000000000000000000000000000000002a", | ||
"topics": [ | ||
"0x1be2d150ed559c350b05f7dfa5a74669ec8d2ce63bb14c134730ffa02d2d111c", | ||
"0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8" | ||
] | ||
} | ||
] | ||
``` | ||
|
||
其中,`address`字段是合约地址;`data`字段中保存了非索引参数的[ABI编解码](https://solidity.readthedocs.io/en/v0.7.1/abi-spec.html#formal-specification-of-the-encoding),此处因为我们只有一个非索引参数`i`,因此`data`字段中只保存了它的值42;`topics`字段包含了两个可用于索引该事件的值,其中第一个是事件签名的哈希值,而第二个值则是事件中索引参数`s`的值的哈希值。对于`String`这类动态对象,Liquid会将它们的哈希值作为索引值,以提高检索效率及减少存储空间占用。因此若您需要在应用中按照字符串检索事件,您需要在本地计算待检索字符串的哈希值。 | ||
|
||
```eval_rst | ||
.. admonition:: 注意 | ||
Liquid目前支持两种哈希计算方式(`keccak256`及`sm3`,见`创建合约模块`一章),若您在应用中需要使用动态对象索引事件,请确保您所用的哈希计算方式与Liquid合约一致。 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters