深入理解Solidity——事件(Events)

事件(Events)

事件是使用EVM日志内置功能的方便工具,在dapp的接口中,它可以反过来调用Javascript的监听事件的回调。

事件在合约中可被继承。当被调用时,会使参数存储到交易的日志中——一种区块链上的特殊数据结构。这些日志与合约的地址关联,并合并到区块链中,只要区块可以访问就一直存在。日志和事件在合约内不可直接被访问,即使是创建日志的合约。

日志的简单支付验证(SPV)是可能的,如果一个外部的实体提供了一个这样证明的合约,它可以证明日志在区块链是否存在。但需要留意的是,由于合约中仅能访问最近的256个区块哈希,所以还需要提供区块头信息。

可以最多有三个参数被设置为indexed——是否被索引。设置为索引后,可以允许通过这个参数来查找日志,甚至可以按特定的值过滤。

如果数组(包括stringbytes)类型被标记为索引项,会用它对应的Keccak-256哈希值做为topic。

除非是匿名(anonymous) 事件,否则事件签名是其中一个topic,同时也意味着对于匿名事件无法通过名字来过滤。

所有未被索引的参数将被做为日志的一部分被保存起来。

注解
被索引的参数将不会保存它们自己,你可以搜索他们的值,但不能检索值本身。

下面是一个简单的例子:

pragma solidity ^0.4.0;

contract ClientReceipt {
    event Deposit(
        address indexed _from,
        bytes32 indexed _id,
        uint _value
    );

    function deposit(bytes32 _id) public payable {
        // 任何对该函数的调用都可以
        // 从JavaScript API中通过Deposit`调用
        // 被过滤从而被检测到 
        Deposit(msg.sender, _id, msg.value);
    }
}

下述是使用javascript来获取日志的例子:

var abi = /* abi 通过编译器生成 */;
var ClientReceipt = web3.eth.contract(abi);
var clientReceipt = ClientReceipt.at("0x1234...ab67" /* 地址 */);

var event = clientReceipt.Deposit();

// 观察变化
event.watch(function(error, result){
    //结果将包含`Deposit`调用给定的参数等各种信息
    if (!error)
        console.log(result);
});

// 或通过回调立即开始观察
var event = clientReceipt.Deposit(function(error, result) {
    if (!error)
        console.log(result);
});

底层的日志接口(Low-level Interface to Logs)

通过函数log0log1log2log3log4,可以直接访问底层的日志组件。logi表示总共有带i + 1个类型bytes32的参数(i表示的就是可带参数的数目,只是是从0开始计数的)。其中第一个参数会被用来做为日志的数据部分,其它的会做为topics。前面例子中的event 可改为如下:

pragma solidity ^0.4.10;

contract C {
    function f() public payable {
        bytes32 _id = 0x420042;
        log3(
            bytes32(msg.value),
            bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20),
            bytes32(msg.sender),
            _id
        );
    }
}

其中的长16进制串是事件的签名,相当于keccak256("Deposit(address,hash256,uint256)")

理解事件的其他资源

  • Javascript documentation
  • Example usage of events
  • How to access them in js

上一篇:深入理解Solidity——函数重载

下一篇:深入理解Solidity——继承

你可能感兴趣的:(Solidity文档翻译系列,以太坊去中心化应用开发)