Ethereum(以太坊)实践

比特币开创了去中心化密码货币的先河,五年多的时间充分检验了区块链技术的可行性和安全性。比特币的区块链事实上是一套分布式的数据库,如果再在其中加进一个符号——比特币,并规定一套协议使得这个符号可以在数据库上安全地转移,并且无需信任第三方,这些特征的组合完美地构造了一个货币传输体系——比特币网络。然而比特币作为一次密码货币的伟大尝试,她并不完美,其中,协议的扩展性是一项不足,例如比特币网络里只有一种符号——比特币,用户无法自定义另外的符号,这些符号可以是代表公司的股票,或者是债务凭证等,这就损失了一些功能。另外,比特币协议里使用了一套基于堆栈的脚本语言,这语言虽然具有一定灵活性,使得像多重签名这样的功能得以实现,然而却不足以构建更高级的应用,例如去中心化交易所等。

以太坊从设计上就是为了解决比特币扩展性不足的问题。总的来说,以太坊是一个平台,她上面提供各种模块让用户来搭建应用,如果将搭建应用比作造房子,那么以太坊就提供了墙面、屋顶、地板等模块,用户只需像搭积木一样把房子搭起来,因此在以太坊上建立应用的成本和速度都大大改善。具体来说,以太坊通过一套图灵完备的脚本语言(Ethereum Virtual Machine code,简称EVM语言)来建立应用,它类似于汇编语言,我们知道,直接用汇编语言编程是非常痛苦的,但以太坊里的编程并不需要直接使用EVM语言,而是类似C语言、Python、Lisp等高级语言,再通过编译器转成EVM语言。

比特币网络事实上是一套分布式的数据库,而以太坊则更进一步,她可以看作是一台分布式的计算机:区块链是计算机的ROM,合约是程序,而以太坊的矿工们则负责计算,担任CPU的角色。这台计算机不是、也不可能是免费使用的,不然任何人都可以往里面存储各种垃圾信息和执行各种鸡毛蒜皮的计算,白皮书有说明,使用它至少需要支付计算费和存储费,当然还有其它一些费用。

以太坊是下一代智能合约和去中心化应用平台。

基本概念

公钥加密系统

每个用户有一把公钥和一把私钥。每个人可以用他的私钥创建数字签名,而其他人可以用他的公钥来验证这个签名确实是他的私钥创建的。当你创建一个以太坊或者比特币帐户的时候,那长长的0xdf...5f地址实质上是个公钥,对应的私钥保存某处。类似于Coinbase的在线钱包可以帮你保管私钥,你也可以自己保管。如果你弄丢了存有资金的钱包的私钥,你就等于永远失去了那笔资金,因此你最好对私钥做好备份。

点对点网络

就像BitTorrent, 以太坊分布式网络中的所有节点都地位平等,没有中心服务器。(未来会有半中心化的混合型服务出现为用户和开发者提供方便,这我们后面会讲到。)

区块链

区块链就像是一个全球唯一的帐簿,或者说是数据库,记录了网络中所有交易历史。一个区块链整体来说是一种为数据通信网络特别设计的数据库类型。它可以保存任意数据,也能设定更新信息的规则,其首要特性是它可以在被称为“区块”的离散块内得到更新,这些“区块”通过前一区块内容的哈希散列“链接”在一起。一个区块链不仅包含当前存储在数据库的信息,也包括每一次对数据库的历史记录变更。通过状态和交易,区块链构造了一个不改变每个随后块就不进行完整更改历史的数据库。一个私钥总是对“交易”或者改变数据库状态的请求进行签名,并且签名也存储在区块链中。

以太坊虚拟机(EVM)

它让你能在以太坊上写出更强大的程序(比特币上也可以写脚本程序)。它有时也用来指以太坊区块链,负责执行智能合约以及一切。

节点

你可以运行节点,通过它读写以太坊区块链,也即使用以太坊虚拟机。完全节点需要下载整个区块链。轻节点仍在开发中。

矿工

挖矿,也就是处理区块链上的区块的节点。这个网页可以看到当前活跃的一部分以太坊矿工:https://ethstats.net/

工作量证明

矿工们总是在竞争解决一些数学问题。第一个解出答案的(算出下一个区块)将获得5个以太币作为奖励。然后所有节点都更新自己的区块链。所有想要算出下一个区块的矿工都有与其他节点保持同步,并且维护同一个区块链的动力,因此整个网络总是能达成共识。以太坊平均30秒可以产生一个区块(注意:以太坊正计划转向没有矿工的权益证明系统(POS),不过那不在本文讨论范围之内。)

以太币

缩写ETH。一种你可以购买和使用的真正的数字货币,它用来支付交易费用。在写这篇文章的时候,1个以太币价值85RMB。最近以太网络因The DAO项目进行硬分叉,由于有80%的算力支持,硬分叉成功,但一部分矿工维护了旧的区块链,市场上出现旧链上的数字货币ETC,http://www.etc-eth.com/这里有两个网络的算力对比。

Gas

在以太坊上执行程序以及保存数据都要消耗一定量的Gas,Gas数量是在智能合约完成时就已经确定了。在公有网络上Gas的价格是20G Wei。这个机制用来保证效率。

DApp

以太坊社区把基于智能合约的应用称为去中心化的应用程序(Decentralized App)。DApp的目标是(或者应该是)让你的智能合约有一个友好的界面,外加一些额外的东西,例如IPFS(可以存储和读取数据的去中心化网络,不是出自以太坊团队但有类似的精神)。DApp可以跑在一台能与以太坊节点交互的中心化服务器上,也可以跑在任意一个以太坊平等节点上。(花一分钟思考一下:与一般的网站不同,DApp不能跑在普通的服务器上。他们需要提交交易到区块链并且从区块链而不是中心化数据库读取重要数据。相对于典型的用户登录系统,用户有可能被表示成一个钱包地址而其它用户数据保存在本地。许多事情都会与目前的web应用有不同架构。)

以太坊客户端,智能合约语言

  • 运行以太坊节点可用的客户端
    以太坊有许多不同语言的客户端实现(即多种与以太坊网络交互的方法),包括C++, Go, Python, Java, Haskell等等。为什么需要这么多实现?不同的实现能满足不同的需求(例如Haskell实现的目标是可以被数学验证),能使以太坊更加安全,能丰富整个生态系统。
  • 在写作本文时,我使用的是Go语言实现的客户端geth (go-ethereum),其他时候还会使用一个叫testrpc的工具, 它使用了Python客户端pyethereum。后面的例子会用到这些工具。
  • 交互式控制台。
    客户端运行起来后,你就可以同步区块链,建立钱包,收发以太币了。使用geth的一种方式是通过Javascript控制台。
    此外还可以使用类似cURL的命令通过JSON RPC来与客户端交互。本文的目标是带大家过一边DApp开发的流程,因此这块就不多说了。但是我们应该记住这些命令行工具是调试,配置节点,以及使用钱包的利器。
  • 在测试网络运行节点。 如果你在正式网络运行geth客户端,下载整个区块链与网络同步会需要相当时间。(你可以通过比较节点日志中打印的最后一个块号和https://ethstats.net/上列出的最新块来确定是否已经同步。) 另一个问题是在正式网络上跑智能合约需要实实在在的以太币。在测试网络上运行节点的话就没有这个问题。此时也不需要同步整个区块链,创建一个自己的私有链就勾了,对于开发来说更省时间。
  • testrpc
    用geth可以创建一个测试网络,另一种更快的创建测试网络的方法是使用testrpc. Testrpc可以在启动时帮你创建一堆存有资金的测试账户。它的运行速度也更快因此更适合开发和测试。

智能合约编写

智能合约是代码和数据的集合,寄存与Blockchain的具体的地址。智能合约更想是在Blockchain中的一个自动化的代理(或者说是机器人or NPC),智能合约有自己的账户,在时间或事件的驱动下能自动执行一些功能,如可以在相互之间传递信息,修改区块链的状态(账户信息等),以及图灵完备计算(可以用图灵机做到的所有事情,通俗来说就是一般编程语言可以做的所有事情)。以太坊的智能合约是以太坊特定的字节码,被叫做EVM字节码。

开发流程

  • 启动一个以太坊节点 (例如geth或者testrpc)。
  • 使用solc*编译*智能合约。 => 获得二进制代码。
  • 将编译好的合约部署到网络。(这一步会消耗以太币,还需要使用你的节点的默认地址或者指定地址来给合约签名。) => 获得合约的区块链地址和ABI(合约接口的JSON表示,包括变量,事件和可以调用的方法)。(译注:作者在这里把ABI与合约接口弄混了。ABI是合约接口的二进制表示。)
  • 用js提供的JavaScript API来调用合约。(根据调用的类型有可能会消耗以太币。)

开发环境

IDE

以太坊官方出品了用来编写智能合约的Mix IDE, 在ubuntu上可以通过

  1. sudo add-apt-repository ppa:ethereum/ethereum
  2. sudo apt-getupdate
  3. sudo apt-getinstall mix-ide

进行安装。它的主要功能如下:

  1. 可以进行合约开发测试,它可以标示出每行代码需要消耗的Gas,及二进制级别的代码调试。
  2. 使用者无需关心区块链节点的搭建,Mix内置了一个测试节点以便进行合约调试。
  3. 编写智能合约的调用场景(Scenario),可以对每个场景进行测试,并且可以直接将场景部署到区块链上。

Truffle框架

truffle 是一个非常传统的测试驱动开发框架,测试语言是javascript,利用了javascript Promise异步调用方法,因为智能合约的每个交易都需要写入区块,响应的时间比较长。对Nodejs有些了解的人非常容易上手。

  1. npm install -g truffle
  2. npm install -g ethereumjs-testrpc

使用truffle部署智能合约的步骤:
1. truffle init (在新目录中) => 创建truffle项目目录结构
2. 编写合约代码,保存到contracts/YourContractName.sol文件。
3. 把合约名字加到config/app.json的'contracts'部分。
4. 启动以太坊节点(例如在另一个终端里面运行testrpc)。
5. truffle deploy(在truffle项目目录中)

在开发过程中你随时可以使用truffle compile命令来确认你的合约可以正常编译(或者使用solc YourContract.sol),truffle deploy来编译和部署合约,最后是truffle test来运行智能合约的测试用例。

注:开发过程中,如果修改了合约一定要重新编译,部署,否则会出现莫名其妙的问题。

这里有一个conference示例, 可以参考其中合约与测试案例的编写方法, 具体的Solidity语法参见官方文档

积分联盟智能合约

问题描述

  • 要解决的问题:
    不同商家之间积分的兑换
  • 问题的简化描述:
    A商家通过智能合约向用户发行其积分a_coin, B商家通过智能合约向用户发行其积分b_coin, C平台发行积分兑换合约及积分c_coin,可以自动实现不同商家之间积分兑换
  • 智能合约实现:
    用户u在C平台的合约上发起兑换操作,C合约将u在A合约上积分减记及B合约上u的b_account增加之后,对该合约上A商家对应账户的积分增加,B商家对应账户的积分减少。

最终的结果:用户u的ua_account中值减少,ub_account中值增加,同时在C合约上,A帐户的c_score增加,B帐户的c_score减少。用户实现了积分兑换的过程,C合约则保存了A、B商家的balance,以便线下的结算。由于所有的交易均可以追溯,C平台无法作假,实现了价值的流通。

分享到: