Annchain深度-以太坊调用智能合约的原理深入解析

作者:Annchain

(本文一切著作权归annchain技术团队所有,未经许可,不得转载。若需转载请联系页尾二维码。)

 

区块链技术蓬勃发展,各项新技术层出不穷。我们平时能接触到的文章,大多浮于表面,虽然对技术有很笼统的介绍(有些甚至是机器翻译的),但对底层的技术关注不多。不夸张地说, 整个行业内能够有机会潜入底层的技术人员可谓凤毛菱角。之所以把这个系列命名为潜水艇系列,就是希望带着各位不满足于表面的技术人员深入区块链的海底,真正理解区块链的底层开发技术。

 

以太坊的智能合约相信大家一定了解。然而以太坊是如何对合约进行调用的呢?如果不通过web3.js,我们该如何与链进行通信,从而能够调用目标合约?本文将进行详细介绍。

 

我们先从一个最简单的合约讲起:


Annchain深度-以太坊调用智能合约的原理深入解析

我们将回答以下几个问题:

 

1.这个合约存储在什么地方?

 

一般来说,合约存储在该合约地址所对应的StateDB中。合约在部署的过程中会根据合约的创建者地址,以及创建者的Nonce进行RLP编码,再通过SHA3 Keccak256哈希后取后20个字节形成合约地址。

 

2.如何调用这个合约?

 

调用合约分为两种:只读调用和可写调用。前者只在本地运行,且运行完毕之后状态更改不会进行全网共识,大多数查询操作都可以通过直接向全节点发送API请求的方式进行调用。可写操作由于需要对数据库和账户的状态进行更改,需要通过发送调用合约交易的方式得到全网的共识,否则这个更改即使在某一个全节点上调用成功,也无法影响全节点的存储,更无法影响链上所有节点的存储。

 

具体来说,我们会在一个普通交易的基础上,将合约地址填在“To”里,再加上愿意为此合约支付的GasPrice和GasLimit。一般来说,我们调用的是合约中的某一个函数(方法),他的函数地址的生成规则是:

 

(1)先取得该函数的签名字符串,其中包括函数名、参数类型。例如sendMessage(string,address)

(2)对这个字符串进行SHA3 Keccak256哈希

(3)取哈希值前4个字节

 

 

当然,如果这个合约是自己编译的话,也可以通过Solc自动生成的签名列表查看:

./solc --hashes hello.sol

 

Annchain深度-以太坊调用智能合约的原理深入解析

 

取得了函数的哈希值后,我们将构造这个函数调用的参数列表。如果有具体需要被调用的函数,则需要在交易的Data字段先填入该函数的哈希值,如上例中的“c60j5f76c”。因为HelloWorld函数不需要其它参数,所以调用时只要传入4个字节就可以了。

 

如果有其它参数,则需要根据该类型的特定编码方式将值转变成32倍数的字节数组后附加在Data字段上。具体的参数生成规则参见第5问。

 

生成了参数之后,就可以进行调用啦。如果是只读的话,只需要通过JSON-RPC发送eth_call请求到全节点上即可。

 

Annchain深度-以太坊调用智能合约的原理深入解析

如果是可写调用,生成交易、签名、广播之后就可以被处理了。

3.这个合约会执行什么操作?

我们来看一下合约生成的字节码:

Annchain深度-以太坊调用智能合约的原理深入解析

合约代码首先检查了调用合约时传入的Data的长度,如果小于4个字节,则不满足调用规则,回滚。随即,对传入Data的前4个字节对比,如果与“0xc605f76c”相等(也就是helloWorld的哈希值),则跳转到tag_2处。

 

Tag_2进一步检查了函数剩余的参数是否是0。如果不是,则违反函数签名规则,回滚。检查通过后接着跳转到tag_3和tag_5

 

Annchain深度-以太坊调用智能合约的原理深入解析

 

返回一段字符串其实就是在内存中写入这段字符串所对应的编码后的值。这段指令在构建一个字符串数据结构。值得吐槽的是,以太坊对于字符串的编码方式非常低效,一个简单的“HelloWorld”返回值其实是一个身处于数组里的字符数组,需要应用数组套数组的编码方式,大小达到了惊人的96字节。

 

Annchain深度-以太坊调用智能合约的原理深入解析

 

4.如何获取到返回值?

 

JSON-RPC返回值会在JSON中直接体现。真实交易的返回值在收据中。编码方式同样参见第5问

 

5.参数和返回值的构造方式是怎样的?

 

以太坊EVM对于参数和返回值的编码方式是相同的,都是基于ABI编码的格式。其中规定:

 

(1)如果数据是简单类型,则存放一个Big-Endian转成32位或32位的倍数。

(2)如果数据是复杂类型(如数组等),则存放一个复杂类型的偏移地址,数组的实际内容附在最后。

(3)对于数组的实际内容,先存放一个数组的长度,再依次存放数组的项。

(4)如果数组的项中存在复杂类型,则递归进行前述步骤。

 

拿字符串举个简单的例子:

 

Annchain深度-以太坊调用智能合约的原理深入解析

 

当然返回值的类型是通过ABI预先确定的,即string。如果不确定返回值的类型,将无法解释返回的数据究竟代表了什么。

 

其中,第一个32 Bytes(0x20)表示了第一个参数是个复杂类型,内容从0x20开始。从0x20开始进入真实的字符串内容。0x20开始的32 Bytes(0x0A)表示该字符数组有10个元素。从0x40开始数10个字符,正好是“HelloWorld”。

 

我们再举一个比较复杂的例子(为了防止眼花,所有不重要的0都以下划线代替):

 

Annchain深度-以太坊调用智能合约的原理深入解析

 

ABI:(String, Address, Address[], String)

 

Annchain深度-以太坊调用智能合约的原理深入解析

 

因此根据ABI解析出,这个参数列表为:

 

[“Annchain”, 0xABCDEF88, [10000,20000], “OG”]

 

 

 

Annchain是由众安科技、众安-复旦区块链与信息安全联合实验室研发, 支持智能合约的高性能通用区块链协议。作为工信部指导的中国区块链技术和产业发展论坛两大开源项目之一,Annchain立足于中国,致力于助力中国抢占区块链全球话语权。

Annchain专注于解决扩展性、去中心化、安全三者平衡问题,做通用的分布式应用计算平台。目前已在数十家生态伙伴的商业场景中落地,场景涵盖农业溯源、珠宝溯源、资产通证化、公益、数据开放计算、广告分发平台和供应链金融等,开发者可基于Annchain高效构建适合自身的区块链应用。

Annchain当前包含两个子项目Annchain.Genesis和Annchain.OG。

Annchain.Genesis作为基于链表式结构的第一代区块链基础协议,其主要特征是模块化、高可靠、易用,支持多种智能合约引擎,开发者可根据具体业务需求选用共识与合约引擎,达到企业级使用需求。

Annchain.OG作为基于DAG账本结构的第二代区块链基础协议,其拥有DAG高效,强扩展特点的同时,又通过基于贡献的多维共识解决其安全可靠问题,同时Annchain.OG支持多种智能合约引擎及计算引擎,具有了更强计算和存储能力。

 

众安科技

众安信息技术服务有限公司(简称“众安科技”)成立于2016年11月2日,是由蚂蚁金服、腾讯、中国平安发起设立的众安保险旗下的全资科技子公司,专注于区块链、人工智能、密码学、物联网等前沿技术研究。众安科技汇聚了行业内的顶尖科研人才,其中区块链团队规模近200人,多数来自于各顶尖区块链团队。

 

众安-复旦区块链与信息安全联合实验室

众安-复旦区块链与信息安全联合实验室是国内首个高校与企业联合组建的区块链与信息安全实验室,专注于区块链核心技术研究,探索应用落地。

 

上海市区块链工程技术研究中心

上海市区块链工程技术研究中心由科委主导,依托复旦大学,联合众安在线财产保险股份有限公司,上海众人信息技术有限公司共同设立。专注分布式账本前沿共性技术与成果转化研究,推动工程落地。

 

更多关于Annchain:

官网: www.annchain.io

Github: http://Github: github.com/annchain

Facebook: https://www.facebook.com/Annchain-295110641341258

                        

                        

扫码备注昵称+研发方向

加入annchain技术社群

 

 

Annchain深度-以太坊调用智能合约的原理深入解析