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 条评论
登录 后参与评论

相关文章

来自专栏IT派

10 个技巧,让你更专业地使用 console 进行 JS 调试

首先,我必须承认这一点,我将利用这个平台从我的开发环境中清理出骨架(轮廓)。有时候,我所做的“魔法”(有些人称之为“编码”),并不像我的同事在为他们展示这些宏伟...

830
来自专栏吾爱乐享

php学习之html的标签属性(二)

1102
来自专栏信安之路

利用彩虹表破解Hash

另一款相对比较实用的hash破解工具,其本质是基于事先生成好的对应的各种散列类型的彩虹表,支持GPU[amd/英伟达]加速,通常自己都是专门用来跑windows...

1080
来自专栏华仔的技术笔记

一个真实区块链项目的演练:以太坊Voting Dapp

4457
来自专栏jessetalks

一不小心写了个WEB服务器

开场   Web服务器是啥玩意? 是那个托管了我的网站的机器么? No,虽然那个也是服务器,但是我们今天要说的Web服务器主要是指像IIS这样一类的,用于处理r...

2945
来自专栏圆方圆学院精选

【许晓笛】 EOS 智能合约案例解析(3)

这次向大家介绍 eosio.token 智能合约的最后一个文件 —— abi文件。ABI 全称 Application Binary Interface,中文名...

524
来自专栏刘望舒

Android系统服务(一)解析ActivityManagerService(AMS)

相关文章 Android系统启动流程系列 Android应用进程系列 Android深入四大组件系列 前言 1.概述 AMS是系统的引导服务,应用进程的启动、...

2106
来自专栏walterlv - 吕毅的博客

WPF 跨应用程序域的 UI(Cross AppDomain UI)

发布于 2017-11-12 16:36 更新于 2017-11...

662
来自专栏杨建荣的学习笔记

结合EM快速解决复杂的配置问题(r4笔记第91天)

图形工具在学习中一般是不作为推荐工具使用的,很多时候可能工作环境都是字符界面,远程连接,基本没有可能接触到图形工具,图形工具的好处真是一把双刃剑,功能丰富全面而...

2696
来自专栏嵌入式程序猿

嵌入式系统开发过程中的常见问题和解决方法

1. Bootloader如何写入Flash ? 初学者一般都会遇到如何将程序写入处理器的问题。对于不同的处理器,可以采用不同的方法。例如Intel的Xscal...

3267

扫码关注云+社区