区块链之以太坊初体验——以太坊平台学习总结

96
点融黑帮
2016.10.21 17:04* 字数 3274

引言:随着比特币的火爆,作为比特币底层实现的核心支撑技术,区块链技术逐渐被人们所熟知。

各类媒体和技术专家也对该技术的应用前景、对应用领域颠覆性的意义进行了大量的报道和描述,区块链技术会像互联网技术一样改变现有传统领域。业界也不乏技术实践的先行者,像R3区块链联盟、以太坊等,在平台实现、技术应用方面已经有了很多的尝试。

近期,因为工作需要,对以太坊、区块链等技术和概念进行了学习和研究。本文是作者对前一段时间学习、工作实践和同事交流的一个知识整理。

区块链

区块链是一种基于点对点(peer-to-peer)网络、分布式的共享账簿技术。

通俗地理解,区块链就是一个公共的、去中心化的数据库,每个节点(full node)上都保存有一份全量的一模一样的数据,在一笔交易数据提交到区块链网络时,各个节点(node,也叫矿工)开始基于该交易信息进行数据块的计算,只有第一个被计算出并按照某种共识机制得其他的节点确认的数据块胜出,从而被添加到链上,该过程也叫算力竞争。后续数据块的计算都会基于前一个块的数据的hash值进行。

而区块链技术被寄予厚望的原因正是,该技术的应用可以改变目前中心化的交易机制(目前,个人和组织的交易行为都是基于一个可信任的、中心化的机构来开展的,比如跨境结算,需要通过国际清算银行等中间机构才能完成交易),帮助人们构建一种可信任的、去中心化的交易机制,交易当事方不需要经过第三方机构而直接完成交易。

这样降低交易的复杂度和中间费用,提高商业效率。同时,区块链通过分布式存储、公私钥加密等技术保证了交易数据的安全、可追溯、不可篡改性。

以太坊

以太坊是一个基于区块链技术的开源平台,通过它可以非常容易地构建去中心化的应用(Dapp)。在底层,以太坊基于区块链技术,实现了数据的去中心化、分布式存储和信息交换的信任问题。同时,以太坊实现了一个叫Ethereum Virtual Machine(EVM)的运行时环境,类似JVM,它的主要工作是执行智能合约(该概念下面会介绍)的字节码。

在以太坊中也有挖矿的概念,每一笔交易只有通过网络中的矿工进行挖矿才能提交到以太坊区块链中。

以太币:类似比特币,以太坊平台上的数字货币,英文缩写ETH。

Gas:用户提交给EVM执行交易或智能合约时,需要支付的费用,由以太币按一定的比例转而来,当用户中的以太币不足以支付Gas时,EVM会停止执行提交的交易或者智能合约。

账户:在以太坊中有两类账户:

外部账户(externally owned account,EOA):用户可以通过地址和私钥对账户进行操作。EOA可以在以太坊控制台中通过命令来创建,或者通过IPC方式由外部调用api来创建;

智能合约(smart contract)

它在以太坊中的作用有:

1)维护数据存储

2)实现复杂的访问控制策略

3)为其他合约提供方法调用。

但是智能合约无法自己执行其中的逻辑或者方法,只能由EOA或者其他合约发起调用。

在以太坊平台,智能合约的编程语言有Solidity(文件扩展名以.sol结尾)和Serpent(文件扩展名以.se结尾),但目前现在最流行而且最稳定的要算是Solidity。

账户在区块链中的存储结构

以太坊账户的所有信息也存储在在区块链的结构中,如下图:

不同于比特币,在以太坊的区块链结构中,不仅包含了对前一个区块的引用信息、区块号、交易和时间戳等信息,它还包含了所有以太坊账户的信息,存储在以“STATE_ROOT”为根节点的一棵Patricia树(“a specialized kind of Merkle tree”)上。该根节点的值是对整棵数上保存的数据进行hash计算得出。

从图中可以看出,每个账户节点中包含四类信息:

NONCE--记录从该账户发起的交易数;

BALANCE--记录该账户余额;

CODEHASH--智能合约账户的代码hash值并指向合约代码,如果为EOA则该值为空;

STORAGE_ROOT--另一棵Patricia树的根节点,智能合约账户的内部数据存储空间,当合约账户调用suicide()方法时,该值将被置为null。

智能合约开发环境搭建

为了便于智能合约的开发和测试,需要在本地电脑搭建一个以太坊开发环境。本文接下来将介绍如何使用Truffle+Testrpc来搭建环境。

Testrpc的介绍和使用

Testrpc是基于node.js开发的以太坊客户端,整个blockchain的数据驻留在内存空间,testrpc可以模拟一个geth客户端的行为,包括所有的RPC api,发送给testrpc的交易会被马上处理而不需要等待挖矿时间,让基于以太坊的开发测试工作更加方便快速。

Testrpc安装。在命令行终端输入“npm install -g ethereumjs-testrpc”,等待完成即可。

启动Testrpc。输入命令”testrpc”即可,启动完成后,出现下图信息:

从中我们可以看到,testrpc在启动时默认创建了多个账号,并开放了rpc端口8545。

Truffle介绍

Truffle是一个基于以太坊的智能合约开发工具,支持对合约代码的单元测试,非常适合TDD。同时它内置了智能合约编译器,只要使用脚本命令就可以轻松完成合约的编译、动态库链接、部署、测试等工作,大大简化了智能合约的开发生命周期。

Truffle的安装非常简单,只要在终端输入命令“sudo npm install -g truffle”,等待安装完成即可。

使用Truffle开发智能合约的过程如下(如何编写合约及solidity语法不在本文范围):

使用testrpc开启一个以太坊节点

创建一个工程目录,并初始化

mkdir myProject

cd myProject

truffle init

初始化完成后,Truffle在工程目录下默认会生成一个叫MetaCoin的智能合约demo及其测试文件,目录结构如下:

各目录含义:

app/:存放前端javascript文件和stylesheets文件,在开发Dapps时使用;

contracts/:智能合约文件的存放目录;

migrations/:存放部署脚本;

test/:存放智能合约测试文件;

truffle.js:truffle的主配置文件,在该文件中可以指定以太坊客户端地址和rpc端口,network_id等;

1. 编写智能合约文件并编译,比如有个Multiply.sol,将其放入contracts目录下,执行命令“truffle complie”,代码片段如下:

2. 部署合约,执行命令“truffle deploy”,或者发布合约到以太坊客户端,在migrations目录下增加部署文件,比如3_deploy_multiply.js 文件,修改truffle.js中相关rpc的配置,执行命令“truffle migrate”,终端打印如下信息,表示成功发布;

3. 编写测试文件,保存为multiply.js,并放入test目录下(代码如下),执行命令“truffle test”:

执行结果如下:

智能合约的外部调用

在某些应用场景下,为了接入以太坊区块链,业务系统需要调用以太坊客户端的api,将用户的交易数据发送给以太坊平台。以太坊客户端已经为外部系统提供了RPC和IPC两种api调用方式。

以RPC方式为例,使用curl命令请求的格式如下:

调用客户端命令:

假设我们要调用客户端命令eth.getBalance(),查询地址为0x407的账号的余额,命令如下:

curl --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x407", "latest"],"id":1}' localhost:8123

其中:jsonrpc字段指定JSON-RPC版本号,method字段指定需要调用的api方法名,params字段为传送的参数,id为消息标识字段;

调用合约方法:

假设目前有部署的智能合约,地址为0x6ff93,我们要调用的合约方法签名为multiply(uint256),传入的参数值为6,那么调用命令的格式如下:

其中,from为扣除GAS的账户地址,to为智能合约部署的地址,data为调用方法的签名和传入参数,编码方式为:

“0x”+sha3(“multiply(uint256)”).substring(0,8)+to_32bit_Hex_str(6)

to_32bit_Hex_str()方法的实现会依据不同的变量类型而有不同,具体规则可以参考Ethereum Contract ABI 文档(HERE)。

从上面的示例可以看出,从外部对智能合约的调用需要进行复杂的编码。万幸,目前以太坊官方提供了使用javascript语言实现的web3.js模块,对RPC和IPC两种调用方式d都进行了封装,对外提供了简洁的接口,使用非常方便。

下面本文将使用web3.js模块在nodejs环境下实现对智能合约的调用,并向外提供RESTful的api。详情如下:

系统环境:

Ubuntu14.04.4+Node V5.1.1;

需要引入的Node模块

express、web3、net,可以使用npm命令安装依赖;

主要代码片段

引入模块依赖

设置RPC和IPC连接对象

调用以太坊客户端方法,查询指定账户的余额

新建以太坊账户,该方法必须使用IPC api的调用方式

新建合约对象,其中contractData为合约代码编译后的16进制字符串

调用智能合约方法

开启http server

最后使用node启动服务,看到“Example app listening at http://:::9090”服务就启动成功了。这样用户便可通过RESTful的http请求来与以太坊客户端进行交互,并调用智能合约。

结束语

本篇文章是我对最近一段时间学习的以太坊平台和区块链技术的总结,主要介绍了以太坊平台的一些基本概念、智能合约本地开发环境的搭建和外部系统调用智能合约api开发介绍3个方面的内容,即当是一次以太坊区块链知识的归纳梳理,也当是一次知识的分享交流。

由于学习的时间有限,文中难免有理解不到位得地方,还请大家指正!同时,非常感谢公司其他同事对我在学习以太坊平台中的帮助,让我受益匪浅!最后,文中也引用和参考了很多官网的资料和网友的文章,在此献上真挚的谢意!

参考资料:

https://blog.ethereum.org/2015/06/26/state-tree-pruning/

https://blog.ethereum.org/2014/02/18/ethereum-scalability-and-decentralization-updates/

http://gavwood.com/Paper.pdf

http://truffle.readthedocs.org/en/latest/

https://github.com/ethereumjs/testrpc

http://www.ethdocs.org/en/latest/

https://solidity.readthedocs.io/en/latest/

本文作者:邬晨烨(点融黑帮),目前就职于点融Fintech Solution团队,有多年的金融IT系统开发建设经验,对互联网技术在金融行业的应用有浓厚的兴趣。业余时间喜欢打桌球、游泳。

技术干货