你所不了解的以太坊交易:深度解析“全球计算机”

点击查看大图 via: tokenanalyst.io

翻译 | 王俊杰

编辑 | 波波

题图不是艺术效果,而是以太坊在 2019 年 1 月 1 日的所有智能合约交易的数据可视化图像。

上图每个节点代表一个地址,而且互相连接的边缘会有不同的颜色,这些代表着不同的函数调用。当天共发生 575,372 个函数调用,同时还有 1654 个功能在区块链中调用。其中大多数(32%)的函数调用是智能合约之间的转账函数,表现为图中央巨大的紫色部分与外围的其他颜色。

(好吧,鉴于以太币今天上涨超过 10%,我们就姑且听你一言。)

但是,你说这个有什么意义?

当人们在分析和比较区块链数据的时候,很多人都会去看交易数据。当然,这也没有什么问题。比如,通过比特币区块链的底层交易账本就可以追踪到相应比特币的所有者。

与比特币相反,以太坊并不追踪所有权,而是基于其去中心化计算架构来追踪交易数据(任何数据都可以看作关键值对)。从这个角度看,以太坊区块链是用来同步和存储系统的状态改变,而以太币则用以衡量和控制任意智能合约的执行费用。

作为以太坊区块链的原生数字货币,以太币可被视为换取以太坊“全球计算机”使用权的实用货币。

以太坊的转账流程

对于许多不熟悉以太坊的人来说,直接跟踪其转账路径可能更加直观一些,因为这能让你直接看到“全球计算机”处理过程。

接下来,我们会简单解释一下这个过程:

我们以 Jack 为例来说这事,Jack 是智能合约开发者,他想把自己的以太币转账到他所拥有的一个智能合约里面,交易流程如下图:

但在本次交易中,他并没有转出以太币,而只是向智能合约发送了一些额外的数据,以使其执行代码中的 distribute 函数。为了在区块链上运行这一函数,他需要支付一笔客观的 gas 费用——作为使用“全球计算机”的手续费。

智能合约收到 Jack 的指令后,就开始运行这一函数。运行的结果是,该函数(以“5”为参数)让第一个合约去调用其他三个相关的合约,从而把其中的代币分发到他们的前 5 大持有者(根据每个合约内部存储的记录)。

其他这三个合约必须要调用另一个内部的函数(getTop5),从而在内部存储中找出前 5 大代币持有者。分别找出各自的 5 个地址后,这三个合约最终会启动代币转移功能,从而可以把代币从自己的余额中转移到相应的地址(有些是其他相关合约本身)。

虽然这只是设想出来的情况,但人们可以从中理解到智能合约生态所固有的复杂性及其潜在的多米诺效应:一系列合约到合约的代码执行一旦启动,价值就会在这些地址之间不断流转(如上图所示)。

区块链:为机器而生

尽管只有外部账户(非智能合约,“普通”的地址)才可以发起转账,但智能合约却可以同所有这些交易及其数据进行交互,从而引发一个潜在的连锁反应。

事实上,我们可以看到,以太坊上智能合约所参与的交易数量要大于账户与账户之间的交易。

via: tokenanalyst.io

所以,智能合约不仅承担起了以太坊主链活跃度的很大一部分,并且还开始负责起以太坊上日益增长的新智能合约的创建工作。

简而言之,就是区块链上的一部分代码正在创造另一部分代码。

如果基于以太坊历史来了解智能合约的创建变迁,我们就能看出:尽管智能合约创建的速度在越来越快,但由非合约“外部拥有”账户(或 EOA)所创建的新合约数量并没有出现相应的增长,爆发是由智能合约所创建的新合约引起的。

根据上面图表的描述,随着今年初更复杂的智能合约开发及部署模式得到采用,这个数字的飙升尤为明显。

交易之下的真相

众所周知,以太坊“全球计算机”的核心是以太坊虚拟机(EVM)。它本质上就是以太坊节点的 CPU,用以处理区块和交易。如上所述,单个的以太坊交易所触发一系列计算过程,都需要通过 EVM 来进行处理。

需要注意的是,在检查区块链数据时,我们通常所观察到的只是表面上的初始交易信息。而它所触发的各种行为都是隐藏在表面之下的,通常在最常见的区块和交易查询中并不显示出来。

虽说 etherscan 的“内部交易”功能可以让你拼凑出一些相关的线索,但要获取可信任的、完整的交易数据,你就需要 EVM 在执行每次交易时的完整机状态记录。你可以把这些状态认为是能够及时捕获一次交易对于下游影响的快照。

https://etherscan.io/txsInternal

任何时候,虚拟机状态记录都是由虚拟机操作码组成,它与传统计算机的汇编代码类似。例如, 0x01 代表 ADD(或者说增加),0x60 代表 PUSH1(将 1 个字节压入堆栈)。

但是,我们可以从更加抽象的角度来看待状态的含义,这通常被称为痕迹结构的透镜——它是由 Parity 的一个节点模块所实现的功能。总的来说,每条痕迹都代表以某种方式来改变以太坊虚拟机的行为(这是对交易的反应)。

Parity 为我们描述了三种主要类型的痕迹:

  • Create trace(创建痕迹):代表着智能合约的创建,并且把以太币转到全新创建的智能合约。
  • Suicide trace(自杀痕迹):智能合约的代码永远不会改变,但智能合约本身却可以被“删除”。自杀痕迹意味着删除智能合约,把代码和最初的状态以及存储从智能合约地址删除,最终会留下一个空白的账户,不会有任何的代码,也不会执行任何的功能调用。
  • Call trace(调用痕迹):主要代表智能合约功能的调用,以及从一个帐户到另一个帐户的以太币转账。

目前来说,整个以太坊区块链拥有近 10 亿个痕迹。这些痕迹的子集可以是能够执行 ERC20 代币交易的函数调用,也可以是 CryptoKitty 交易。

这些痕迹中的每一个都有着数量不等的子痕迹,它们是由原始轨迹而进一步调用其他合约(或其本身)所形成的,这就是前面所介绍过的多米诺效应。

本文完成时,子痕迹数量大于 10 的痕迹共有 4,749,778 条。

这里可以注意一下:你无法仅仅通过加减某一地址转入和转出的以太币来计算其账户余额,因为子痕迹和函数调用过程中的以太币转手,最终会影响该交易本身。

通过追踪痕迹和子痕迹,可以获取到非常多的信息,这让我们可以从更高的抽象层面来理解真正发生的事情。

Solidity 是一门用来编写以太坊智能合约的高级编程语言。使用 Solidity 的应用程序二进制接口(ABI), 我们就可以将痕迹中的原始十六进制数据解码为它所代表的特定函数调用(Solidity 函数)。每个智能合约都有它自己的 ABI,并且都通过 ABI 来解码函数调用,我们能够跟踪整个合约运行时间中的每一个“动作”以及每分钟的所有“动作”。

下图是所有已分析函数调用的一个子集,按历史上每个函数的调用次数进行排列。从中可以看出,一些特定的函数,如 transfer 与 transferFrom,使用频率非常之高。这是因为这些函数都是 ERC20 标准的一部分。

via: tokenanalyst.io

在执行这些函数的时候,开发人员可以选择输出“事件(Event)”。事件是驻留在事务日志中的 Solidity 高级结构,表示某些操作已由智能合约执行。你可以把它视作程序的“输出”。尽管不是每个智能合约都有“事件”,但“事件”通常由轻客户端与 dApp 开发者来“观察”智能合约上所发生的特定活动,并在前端界面上进行响应。

下图是所有已分析事件的一个子集,以每种事件出现过的次数进行排列:再一次,我们看到了交易事件的横行,那是 ERC20 交易发生的信号机制。

via: tokenanalyst.io

小结

在分析链上数据的时候,特别是针对以太坊的数据,只看交易记录是远远不够的!

现在,每个去中心化交易所,去中心化自制组织,dapp 以及 Defi 项目都会有不同的智能合约,每个都有自己的函数和事件,所有这些都代表了每个项目和生态系统不同的事情。

深入分析之后,我们越来越意识到合约到合约价值转移及其多米诺效应所带来的巨大影响。在不远的将来,以太坊的使用者将不再是人类,而是活跃的代码。

以太坊的这一转变正在加速发生。

原文链接:

  • https://medium.com/tokenanalyst/under-the-hood-of-the-world-computer-caf957fb8a4c
  • https://wiki.parity.io/JSONRPC-trace-module