以太坊(Ethereum)支持图灵完备的应用,按照智能合约的约定逻辑自动执行,理解情况下将不存在故障停机,审查,欺诈以及第三方干预等问题。
智能合约开发者使用官方提供的工具和以太坊专用应用开发语言Solidity,可以很容易地开发出运行在以太坊网络上的“去中心化”应用(Decentralized Application, DApp)。将这些应用运行在以太坊的虚拟机(Ethereum Virtual Machine,EVM)里。用户通过以太币(Ether)来购买燃料,维持所部属应用的运行。
以太坊区块链底层也是一个类似比特币网络的P2P网络平台,智能合约运行在网络中的以太坊虚拟机里。网络自身是公开可接入的,任何人都可以接入并参与网络中数据的维护,提供运行以太坊虚拟机的资源。
与比特币项目比,以太坊区块链的结束特点主要包括:
支持图灵完备的智能合约,设计了编程语言Solidity和虚拟机EVM
选用了内存需求较高的哈希函数,避免出现强算力矿机,矿池的攻击
叔块(uncle block)激励机制,降低矿池的优势,并减少了区块产生间隔(15s左右)
采用账户系统和世界状态,而不是UTXO,容易支持更复杂的逻辑
通过Gas限制代码执行指令数,避免循环执行攻击
支持PoW共识算法,并计划支持效率更高的PoS算法
此外开发团队还计划通过分片(sharding)方式来解决网络扩展问题
智能合约
智能合约(Smart Contract)即以计算机程序方式来缔结和运行各种合约。以太坊通过图灵完备的高级语言等来开发智能合约。智能合约作为运行在以太坊虚拟机中的应用,可以接受来自外部的交易请求和事件,通过触发运行提前编写好的代码逻辑,进一步生成新的交易和事件,可以进一步调用其他智能合约。智能合约的执行解雇可能对以太坊网络上的账本状态进行更新。这些修改由于经过了以太坊网络中的共识,一旦确认后无法被伪造和篡改
账户
以太坊直接采用账户来记录系统状态。每个账户存储余额信息,智能合约代码和内部数据存储等。以太坊支持在不同的账户之间转移数据,以实现更为复杂的逻辑。以太坊账户分为两种类型:合约账户(Contracts Accounts)和外部账户(Externally Owned Accounts, EOA)。
合约账户:存储执行的智能合约代码,只能被外部账户来调用激活
外部账户:以太坊拥有者账户,对应到某公钥。账户包括nonce,balance,storageRoot,codeHash等字段,由个人来控制
当合约账户被调用时,存储其中的智能合约会在矿工处的虚拟机中自动执行,并消耗一定的燃料。燃料通过外部账户中的以太币进行购买。
交易
交易在以太坊中是指从一个账户到另一个账户的消息数据。消息数据可以是以太币或合约执行参数。
以太坊采用交易作为执行操作的最小单位。每个交易包括如下字段:
to:目标账户地址
value:可以指定转移的以太币数量
nonce:交易相关的字串
gasPrice:执行交易需要消耗的Gas价格
startgas:交易消耗的最大Gas值
signature:签名信息
以太币
以太币是以太坊网络中的货币。主要用于购买燃料,支付给矿工,以维护以太坊网络运行智能合约的费用。以太坊最小单位是wei,一个以太坊为10的18次方个wei。
以太币同样可以通过挖矿来生成,成功生成新区块的以太坊矿工可以获得5个以太币的奖励以及包含在区块内交易的燃料费用。
燃料
燃料(Gas)控制某次交易执行指令的上限。每执行一条合约指令会消耗固定的燃料。当某个交易还未执行结束,而燃料消耗完成时,合约执行终止并回滚状态。
交易模型对比
特性 | UXTO模型 | 账户模型 |
状态查询和变更 | 需要回溯历史 | 直接访问 |
存储空间 | 较大 | 较小 |
易用性 | 较难处理 | 易于理解和编程 |
安全性 | 较好 | 需要处理好重放攻击等情况 |
可追溯性 | 支持历史 | 不支持追溯历史 |
共识
以太坊采用了基于成熟的PoW共识的变种算法Ethash协议作为共识机制。Ethash在执行时需要消耗大量内存,反而跟计算效率关系不大。
降低攻击
所有交易都需要提供交易费用,避免DDos攻击
程序运行指令通过Gas来限制,所消耗的费用超过设定上限时就会被取消,避免出现恶意合约
提高扩展性
可拓展性是以太坊网络承接更多业务量的最大制约。以太坊项目未来希望通过分片机制来提高整个网络的扩展性。分片是一组维护和执行同一批智能合约的节点组成的子网络,是整个网络的子集。
支持分片功能前,以太坊整个网络中的每个节点都需要处理所有的智能合约,这就造成了网络的最大处理能力会受限于单个节点的处理能力。
分片后,同一片内的合约处理是同步的,彼此达成共识的,不同分片之间则可以是异步的,可以提高网路的可扩展性。
智能合约
所有的Solidity源码都必须冠以“version pragma”表明Solidity编译期的版本,以避免将来新的编译期可能破坏你的代码。
状态变量是被永久地保存在合约中。即它们被写入以太币区块链中。
无符号整数:uint。其值不能使负数。对于有符号的整数存在名为int的数据类型。(在Solidity中,unit实际上是unit245代名词,一个256位的无符号整数,也可以定义位数少的uints:uint8,uint16,uint32等)
Solidity提供了结构体来表示更复杂的数据类型(struct)。结构体允许你生成一个更复杂的数据类型,它有多个属性。
Solidity支持两种数组:静态数组和动态数组。Solidity会自动为public创建getter方法。
Solidity中函数定义的语句如下 function funcName(parameters){},习惯上函数的变量是以_开头以区别全局变量。Solidity定义的函数的属性为公共。也可以把函数名字后面使用关键字private。私有函数名以_起始。函数定义里可以包含返回值的数据类型。
array.push()在数组的尾部加入新元素,所以元素在数组中的顺序就是添加的顺序。
可以把函数定义为view,意味着它只能读取数据不能更改数据
function funcname() public view returns (string) {}
Solidity的pure函数表明这个函数甚至都不访问应用里的数据。这个函数不读取应用里的状态,他的返回值完全取决于它的参数。
Ethereum内部有一个散列函数keccak256,它用了SHA3版本。一个散列函数基本上就是把一个字符串转换为1个256位的16进制数字。
事件是合约和区块链通讯的一种机制。使用event作为关键字。
映射(Mapping)和地址(Address)。以太坊区块由account组成。每个账户都有一个“地址”。mapping(address => uint) public accountBalance;
在Solidity中,msg.sender指的是当前调用者的address。