80%开发者都不知道的以太坊骚操作:「事件」和「日志」还可以这么玩!

作者 | 蔡一 志顶科技技术总监

4月6日,Daniel Larimer发布了一篇文章《EOSIO Dawn 3.0 Now Available》(译:EOSIO Dawn 3.0来啦),在章节「Simplified Contract Development」(译:更简单的合约开发)中,举了个「Hello,World」的智能合约的例子来说明合约开发的简单。

https://gist.githubusercontent.com/bytemaster/

58d45d13dbf8732c8d467b6415a44df9/raw/ba460c2aff29c7f60ecdef7dc082a0190b5af418/

hello.cpp

然而值得注意的是,示例的合约就执行了一条语句:print( "Hello, ", user);

那么问题来了:在智能合约中print的内容会出现在哪里呢?

我没实际运行过这段代码,但我知道,print的内容只会出现在每个区块链节点的日志文件或终端(Console)上。 实际上,传统的print日志打印对智能合约的开发和跟踪不存在任何意义。

那么,以太坊怎么解决这个问题的呢?以太坊引入了事件(Events)和日志(Logs)

这里说的「事件」和「日志」这两个术语可能会引起混淆,本质上来说,智能合约通过「事件」来产生「日志」本文会介绍以太坊的「事件」和「日志」系统常用的3种场景,供以太坊开发者参考

事件和日志的用途

「事件」和「日志」对于以太坊是非常重要的,因为它们使智能合约与用户界面之间的通信变得容易。在传统的Web开发中,一个服务器响应会提供回调给前端。在以太坊中,当一个交易被打包,智能合约能发送事件以及写日志到区块链上以便前端处理。有三种情况需要使用事件和日志。

1. 智能合约给用户界面返回值

我们还是以EOS的例子来看,鉴于Solidity拼接字符串比较麻烦,我就直接返回一个字符串。

如果你用Web3.JS来调用HelloWorld这个智能合约的函数「hi()」,你可能会认为是这样:

那么,这句调用的result会是「hello, World」呢? 其实不是,不管函数返回什么值,Web3.JS都会返回一个Transaction Hash(交易哈希)。

那要怎么做呢?现在就轮到事件上场了。

修改后的智能合约代码如下:

而Web3.JS则需要这样写:

当交易被打包时,回调函数将被触发, 前端将获得智能合约函数的返回值。

2. 异步数据通知

使用返回值返回给用户界面其实很少用到。大部分时间,我们是使用事件给用户界面发送数据。当智能合约想把某些数据通知用户界面时,可以发送事件,用户界面对这些时间进行监听,就可以进行不同的操作。

3. 相对便宜的数据存储

还有这一种使用方式是把日志作为数据存储。在EVM规范和黄皮书中说明,事件将产生日志,而日志是会被存储都区块链的。日志存储的Gas费用要比合约的存储便宜很多(日志每个字节花费8个Gas,而合约存储是每32个字节20,000个Gas)。因此,当你有存证等应用的时候,可以考虑使用日志来存储,而不是在合约中使用Mapping来存储。

日志的存储结构

上面说了时间和日志的三种用法,最后我们来看看日志的大致结构。

你可以通过「remix」查看日志的接口。Topic指向特定的事件,但值是16进制的,这是个什么呢?其实这是事件的签名。图中的288d740d3b11a36c8526119855345e3ba2aee438370d264289ea6dfb76294fd0其实是sha3(Hi(string))的执行结果。下面的「event」和「args」是「remix」从区块链的「收据」(Receipt)数据的Logs项中解码出来的。

实际数据为:

那是怎么解码的呢?

前文中提到过,Topics实际上是事件的「sha3」签名,示例合约中只有一个事件,可以直接对应,如果合约中有多个事件,需要通过ABI找出对应的event,逐一签名,最后与Topics中的签名进行对应即可找到对应的事件。

事件的名称找到了,对应的参数就相对简单,示例合约的ABI如下:

可以看到,type为event的事件,「输入」(inputs)只有一个,那就是「say」,类型是「string」。

我们使用eth-abi工具(https://github.com/ethereum/eth-abi)可以进行解码。(eth-abi是一个用Python编写的Ethereum ABI工具)。命令如下:

在web3.js 1.0-beta版本中,可以直接通过以下函数进行日志解码:

结束语

「事件」(Events)是以太坊中很有意思的设计,对智能合约运行时与外部交互,特别是DApp的设计具有重要意义。大家在开发DApp和智能合约时可以根据实际情况灵活应用以上所介绍的3种方式,进行与前端的交互和日志的调试。也欢迎大家发掘更多的应用场景。

作者简介:蔡一,区块链技术专家,长期研究并实践区块链技术与应用,精通以太坊智能合约开发。现为志顶科技技术总监,负责公司核心产品TokenPOS通证宝设计与研发。

原文发布于微信公众号 - 区块链大本营(blockchain_camp)

原文发表时间:2018-05-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏区块链

200行代码构建一个区块链

我将介绍一个我用200行 Javascript 代码完成的超级简单的区块链:NaiveChain 。

92519
来自专栏区块链大本营

“危机四伏”的以太转账操作|以太转账安全风险——漏洞分析连载之八期

Solidity语言的默认存储规则和引用未初始化变量带来的特殊性共同导致了未初始化变量将原有状态变量覆盖,占用了状态变量在Storage中的位置,重演了最近“高...

952
来自专栏区块链入门

第十六课 不用编程,如何把长文章记录到以太坊区块链上?

【本文目标】 通过本文学习,以太坊学习者可以把中文长文章记录到区块链上,不会被删除。

1025
来自专栏Seebug漏洞平台

以太坊智能合约 Owner 相关 CVE 漏洞分析

最近学习了下以太坊的智能合约,而且也看到挺多厂家pr智能合约相关的漏洞,其中《ERC20智能合约整数溢出系列漏洞披露》文章中披露了6个CVE编号的漏洞,而这些漏...

1673
来自专栏区块链入门

第二十一课 如何通过Solidity的智能合约函数把长文章记录到以太坊区块链上?

辉哥的文章《第十六课 不用编程,如何把长文章记录到以太坊区块链上?》 是通过MetaMask的交易形式把数据写到链上。 本文提供另外一个方式,通过智能合约函数...

762
来自专栏SAP最佳业务实践

SAP最佳业务实践:FI–资产会计(162)-5 ABAVN 资产处置

4.4 资产处置 固定资产清理是指从资产组合中移除某项资产或部分资产。复杂固定资产(或部分复杂固定资产)的移除是从帐面上将其作为资产清理过帐。 在中国资产会计中...

3878
来自专栏蜉蝣禅修之道

以太坊DApp系列(二)---从入门到出家

以太坊自2013年V神提出后,被无数人赋予美好的愿景,甚至被称为区块链2.0,其代币发行量更是达到了全球第二,仅次于比特币,而其带来的智能合约概念颠覆了人们对区...

1.1K18
来自专栏liuchengxu

Tendermint: 什么是 ABCI (应用区块链接口)

区块链应用接口(Application BlockChain Interface,ABCI)允许应用的拜占庭容错复制可以由任意一种编程语言编写。

903
来自专栏区块链大本营

以太坊再爆高危漏洞!黑客增发ATN 1100万枚token事件始末

事情发生在5月中旬,ATN技术人员发现Token合约由于存在漏洞受到攻击。不过ATN基金会随后透露,将销毁1100万个ATN,并恢复ATN总量,同时将在主链上线...

491
来自专栏极客编程

JavaScript实现简单区块链

用JavaScript来实现一个简单的区块链。通过实现过程,你将理解区块链是什么:区块链就是一个分布式数据库,存储结构是一个不断增长的链表,链表中包含着许多有序...

1441

扫码关注云+社区