自2008年比特币出现以来,数字货币已经渐渐被接受。随着应用的扩展,人们发现比特币的设计只适合虚拟场景,由于存在着非图灵备性,缺少保护状态的账户概念,以及Pow挖矿机制所带来的资源浪费和效率问题,在很多区块链应用场景下并不适用。人们需要一个新的基于区块链的具有图灵完备性,高效共识机制,支持更多应用场景的智能合约开发平台。以太坊在这种情况下应运而生。
以太坊的目的是对脚本,竞争币和链上元协议(on-chains meta-protocol)等概念进行整合和提高,使得开发者能够创建任意的基于共识的,可扩展的,标准化的,图灵完备的,易于开发和协同的应用。
以太坊是一个通用的全球性区块链,可以管理金融和非金融类型应用状态。以太坊的新颖在于其神奇的计算机网络,它促成了一种新型的软件应用,真正的去中心化应用。将信任逻辑嵌入小程序里,运行在区块链上。而与比特币相比,以太坊建立了一种新的密码学技术基础框架,在其上开发应用更加容易,并对轻客户端友好,同时允许应用共享一个可行的经济环境和可靠的区块链安全。
以太坊是个平台和编程语言,包括数字货币以太币(Ether),以及用来构建和发布分布式应用的以太脚本(EtherScript)。
以太币和著名的数字货币比特币有非常多的相似之处。两者均为数字货币且无法伪造,都以去中心化的方式运行来保证货币供应不被某一方所控制。以太坊的另一半重要特性是提供一个完整的编程语言环境,有时也被叫作以太脚本。计算机如何执行一段代码是没有二义性的。在同样的条件下,一段代码总是会按照既定的步骤执行。这种特性正是人类现行法律与合约所缺失的。有了以太脚本后,我们就可以制定没有二义性的合约了。
从最底层角度看,以太坊是也多层的,基于密码学的开源技术协议。它的不同功能模块通过设计进行了全面的整合,作为一个整体,它是一个创建和部署去中心化应用的综合平台。同时,以太坊也是区块链与智能合约的完美结合,是智能合约的完整解决方案,被设计成了一个通用的去中心化平台,拥有一套完整的,可以扩展其功能的工具,在P2P网络、加密、HttpClient等技术的支持下实现了一个类似于比特币的区块链。它通过工作量证明机制实现共识,由矿工挖矿,通过对新的网络协议的制定实现对区块链的同步等操作。不同于比特币的是,以太坊上可以任意编写智能合约,通过智能合约实现强大功能,实现去中心化应用的开发。在以太坊上部署的智能合约运行在以太坊特有的虚拟机上,通过以太坊虚拟机和RPC接口与底层区块链进行交互。
以太坊的总体架构
1、 DApp 、 DAO
2、 智能合约
3、Solidity/Serpent/LLL 、 账户管理 、 区块链管理 、 校验模块
4、EVM、 密码模块、 共识模块、 挖矿模块
5、网络管理 、 P2P网络、 数据库、 RPC服务端
#以太坊核心概念
1、以太坊虚拟机
以太坊虚拟机(EVM)是以太坊中智能合约的运行环境。它是以太坊项目中的另一个主要创新。有人说EVM“位于区块链之上”,实际上它是由许多互相连接的计算机组成的。任何人都可以上传程序,并让这些程序自动执行,同时保证现在和所有以前的每个程序的状态总是被公开可见的。这些程序运行在区块链上,严格地按照EVM定义的方式继续执行。所以任何人都可以为所有权、交易格式和状态转换函数创建商业逻辑。
2、账户
以太坊有两类账户,它们共用同一个地址空间。外部账户,该类账户被公钥-私钥对控制。合约账户,该类账户被存储在账户中的代码控制。外部账户的地址是由公钥决定的,合约账户的地址是在创建合约时由合约创建者的地址和该地址发出过的交易数量计算得到。两类账户的唯一区别是:外部账户没有代码,人们可以通过创建和签名一笔交易从一个外部账户发送消息。每当合约账户收到一条消息,合约内部的代码就会被激活,允许它对内部存储进行读取、写入、发送其他消息和创建合约。
以太坊的账户包含4个部分:
1、随机数,用于确定每笔交易只能被处理一次的计数器;
2、账户目前的以太币余额;
3、账户的合约代码(如果有的话);
4、账户的存储(默认为空)。
3、消息
以太坊的消息在某种程度上类似于比特币的交易,但两者之间存在3点重要的不同。
1)、以太坊的消息可以由外部实体或者合约创建,然而比特币的交易只能从外部创建。
2)、以太坊消息可以选择包含数据。
3)、如果以太坊消息的接受者是合约账户,可以选择进行回应,这意味着以太坊消息也包含函数概念。
4、交易
以太坊中“交易”是指存储从外部账户发出的消息的签名数据包。交易包含消息的接受者、用于确认发送者的签名、以太币账户余额、要发送的数据和被成为STARTGAS和GASPRICE的两个数值。为了防止代码出现指数型爆炸和无限循环,每笔交易需要对执行代码所发出的计算步骤做出限制。STARTGAS就是通过需要支付的燃料来对计算步骤进行限制,GASPRICE是每一个计算步骤需要支付矿工的燃料的价格。
5、Gas
以太坊上的每笔交易都会被收取一定数量的燃料Gas,设置Gas的目的是限制交易执行所需的工作量,同时为交易的执行支付费用。当EVM执行交易时,Gas将按照特定规则被逐渐消耗。Gas价格由交易创建者设置
发送账户需要预付的交易费用=GASPRICE * Gas amount。
如果执行结束还有Gas剩余,这些Gas将被返还给发送账户。无论执行到什么位置,一旦Gas被耗尽就会触发一个out-of-gas异常。同时,当前调用帧所做的所有状态修改都将被回滚。
6、存储、主存和栈
每个账户都有一块永久的内存区域,被成为存储,其形式为key-value,key和value的长度均为256为。在合约里,不能遍历账户的存储。相对于主存和栈,存储的读操作开销较大 ,修改存储甚至更多。一个合约只能对它自己的存储进行读写。
第二个内存区被称为主存。合约执行每次消息调用时都有一块新的被清除过的主存。主存可以按字节寻址,但是读写的最小单位为32字节。操作主存的开销随着主存的增长而变大。
EVM不是基于寄存器的,而是基于栈的虚拟机。因此所有的计算都在一个成为栈的区域内执行。栈最大由1024个元素,每个元素有256位。对栈的访问只限于其顶端,允许复制最顶端的16个元素中的一个到栈顶,或者是交换栈顶元素和下面16个元素中的一个。所有其他操作都只能取到最顶的一个或几个元素,并把结果压在栈顶。当然可以把栈里的元素放到存储或者主存中。但是无法只访问栈里指定深度的那个元素,在那之前必须把指定深度之上的所有元素都在栈中移除才行。
7、指令集
EVM的指令集被刻意保持在最小规模,以尽可能避免可能导致共识问题的错误。所有指令都是针对256位这个基本的数据单位进行的操作,具备常用的算术、位、逻辑和比较操作,也可以进行条件和无条件跳转。此外,合约可以访问当前区块的相关属性,比如它的编号和时间戳。
8、消息调用
合约可以通过消息调用的方式来调用其他合约,或者发送以太币到非合约账户。消息调用和交易非常类似,它们都有一个源,一个目标,数据负载,以太币,Gas和返回数据。事实上每个交易都可以被认为是一个顶层消息调用,这个消息调用会一次产生更多的消息调用。
一个合约可以决定剩余Gas的分配。比如内部消息调用时使用多少Gas,或者期望保留多少Gas。如果在内部消息调用时发生了out-of-gas异常或者其他异常,合约将会得到通知,一个错误码被压入栈中。这种情况只是内部消息调用的Gas耗尽。在solidity中,这种情况下发起调用的合约默认会触发一个人工异常,这个异常会打印出调用栈。
就像之前说过的,被调用的合约(发起调用的合约也一样)会拥有崭新的主存,并能够访问调用的负载。调用负载被存储在一个单独的被称为calldata的区域。调用执行结束后,返回数据将被存放在调用方预先分配好的一块内存中。调用层数被限制为1024。因此对于更加复杂的操作,我们应该使用循环而不是递归。
9、代码调用和库
以太坊中存在一种特殊类型的消息调用,被成为calldata。它跟消息调用几乎完全一样,只是加载来自目标地址的代码将在发起调用的合约上下文中运行。这意味着一个合约可以在运行从另外一个地址动态加载代码。存储,当前地址和余额都指向发起调用的合约,只有代码是从被调用地址获取的。这使得Solidity可以实现“库”。可复用的库代码可以应用在一个合约的存储上,可以用来实现复杂的数据结构,从而使智能合约更加的强大。
以太坊的状态转换是指在一个交易(TX)发生时,以太坊从一个正确状态(S)转变到下一个正确状态(S’)的转换过程。对于交易而言,为了防止代码的指数型爆炸和无线循环,每笔交易需要对执行代码所引发的计算步骤做出限制。STARTGAS就是限制,GASPRICE是每一步计算步骤需要支付矿工的费用价格。
以太坊的状态转换函数为APPLY(S,TX)---->S’,可以定义如下:
1)检查交易的格式是否正确,签名是否有效,以及随机数是否与发送者账户的随机数匹配。如否,返回错误。
2)计算交易费用fee = STARTGAS * GASPRICE,并从签名中确定发送者的地址。从发送者的账户中减去交易费用和增加发送者的随机数。如果账户余额不足,返回错误。
3)设定初值Gas = STARTGAS,并根据交易中的字节数减去一定量的燃料值。
4)从发送者的账户转移价值到接受者账户。如果接收账户还不存在,创建此账户。如果接收账户是一个合约,运行合约的代码,知道代码运行结束或者燃料用完。
5)如果因为发送者账户没有足够的费用或者代码执行耗尽燃料导致价值转移失败,恢复原来的状态,但是还需要支付交易费用,交易费用加至矿工账户。
6)若代码执行成功,将所有剩余的燃料归还给发送者,消耗掉的燃料作为交易费用发送给矿工。
例如,假设一个合约的代码如下:
if ! contract.storage[msg.data[0]]:contract.storage[msg.data[0]]=msg.data[1]
需要注意的是,在现实中合约代码是用底层以太坊虚拟机(EVM)代码写成的。上面的合约是用高级语言Serpent语言写成的,可以被编译成EVM代码。
假设合约存储器开始是空的,一个值为10以太,燃料为2000、燃料价格为0.001以太并且两个数据字段值为[2,‘CHARLIE’]的交易发送后,状态转换函数的处理过程如下:
1)检查交易是否有效,格式是否正确。
2)检查交易发送者是否至少由2000x0.001=2个以太币。如果有,从发送者账户中减去2个以太币。
3)初始设定Gas=2000,假设交易长为170字节,每字节的费用是5,减去850,所以还剩1150.
4)从发送者账户减去10个以太币,为合约账户增加10个以太币。
5)运行代码。在这个合约中,运行代码很简单:它检查合约存储器索引为2处是否已使用,注意到它未被使用,然后将其值设置为CHARLIE。假设者消耗了187单位的燃料,于是剩余的燃料为1150-187 = 963.
6)向发送者的账户增加963x0.001=0.963个以太币,返回最终状态。
如果没有合约接收交易,那么所有的交易费用就 = GASPRICE x 交易的字节长度,交易的数据与交易费用就无关了。
合约发起的消息可以对它们产生的计算分配燃料限额,如果子计算的燃料用完了,它只恢复到消息发出时的状态。因此,就像交易一样,合约也可以通过对它产生的自己算设置严格的限制,保护它们的计算资源。
4种语言编写的以太坊的客户端
1.用Go语言实现的客户端Geth;
2.用C++实现的客户端Eth;
3.用Python实现的客户端Pyethapp;
4.用java实现的客户段EthereumJ。
#智能合约
以太坊是内置有图灵完备编程语言的区块链,通过建立抽象的基础层,使得任何人都能够创建合约和去中心化应用,并在其中设立它们自由定义的所有权规则、交易方式和状态转换函数。建立一个代币的主体框架只需要两行代码就可以实现,诸如货币和信誉系统等其他协议只需要不到20行代码就可以实现。智能合约就像能在以太坊的平台上创建的包含价值而且只有满足某些条件才能打开的加密箱子,并且因为图灵完备性、价值意识(value-awareness)、区块链意识(blockchain-awareness)和记录多状态所增加的功能而比比特币脚本所能提供的智能合约强大得多。
#开发语言
以太坊的软件开发语言是其最大特性之一,因为对去魁岸了进行编程是一项首要目标。以太坊具有4中专用语言:Serpent(受Python启发)、Solidity(受JavaScript启发)、Mutant(受Go启发)和LLL(受Lisp启发),都是为面向合约编程而从底层开始设计的语言。
Serpent被设计为最大可能地简洁和简单,将低级语言的高效优势与编程风格中的易用性相结合。
Solidity是以太坊的首选语言,它内置了Serpent的所有特性,但是语法类似于JavaScript。Solidity充分利用了现有数以百万程序已掌握JavaScript这一现状,降低了学习门槛,易于被掌握和使用。
以太坊区块链的另一个关键特征是它的“图灵完备性”。保证了以太坊可以解决所有的计算机问题。更加准确地说,它是“半”图灵完备的,因为它是通过对计算量设置上限,它避免了完全图灵完备语言存在的无法停机问题。此外,以太坊有账户的概念,使得它在交易的可视化和查询账户状态方面提供了实时性。
在比特币上,由于只有UTXO而没有账户的概念,我们需要导入区块链数据库,解析所有的交易,并为了抽取出在区块链上的某个用户的交易情况而查询交易。而以太坊,可以在实时的区块链上,根据一个地址情况实时查看当前账户情况和交易状态。
#代码执行
以太坊合约的代码是使用低级的基于堆栈的字节码的语言写成的,被称为“以太坊虚拟机代码”或者“EVM代码”。代码由一系列字节构成,每一个字节代表一种操作。
一般而言,代码执行是无限循环,程序计数器每增加一(初始值为零)就执行一次操作,知道代码执行完毕或者遇到错误、STOP或者RETURN指令。操作可以访问3中存储数据的空间:
1、堆栈,一种后进先出的数据存储,入栈、出栈的基本单位为32位;
2、内存,可无限扩展的字节队列‘
3、合约的长期存储,一个密钥/数值的存储,其中密钥和数值都是32字节大小。
与计算结束即重置的堆栈和内存不同,存储内容将长期保持。
代码可以像访问区块头数据一样访问数值、发送和接收到的消息中的数据,代码可以返回数据的字节队列作为输出。EVM代码的正式执行模型非常简单。当以太坊虚拟机运行时,它的完整的计算机状态可以由元组(block_state,transaction,message,code,memory,stack,pc,gas)来定义,这里的block_state是包含所有账户余额和存储的全局状态。每轮执行时,通过调出代码的第pc(程序计数器)个字节,每个指令如何影响元组都有定义。例如,ADD将2个元素出栈并将它们的和入栈,将Gas减1并将pc加1;stack将顶部的两个元素出栈,并将第2个元素出入由第1个元素定义的合约存储位置,同样减少最多200的Gas值,并将pc加1.
#什么是DApp
一个DApp是由智能合约和客户端代码构成的。智能合约就像加密的包含价值的箱子。只有当特定条件被满足时它才能被打开,它封装了一些逻辑、规则、处理步骤或者双方间的协议。
从架构角度而言,DApp非常类似于传统的Web应用。主要区别是:在传统Web应用中,客户段由JavaScript代码,由用户在自己的浏览器中执行;服务器端的代码由主机运行。但是在一个DApp中,它的智能逻辑运行在区块链上,客户端代码运行在特殊浏览器Mist里面。
#应用举例
Augur:(www.augur.net)一个去中心化预测系统。
Maker:(www.makerdao.com)一个金融类去中心化自治组织。
WeiFund:一个正在开发的去中心化众筹平台。
Boardroom:一个正在开发中的DAO管理平台。
。。。。。。。。。。。。。。