以太坊(一)
以太坊提高交易处理能力的方式主要有两个,一个是分片技术(shard),另一个就是状态通道技术(state channels)。
雷电网络(Raiden Network)是状态通道技术在以太坊上的实现
最初以太坊程序是由一间位在瑞士的公司 Ethereum Switzerland GmbH 开发,之后转移至一个非营利机构“以太坊基金会”(Ethereum Foundation)。在平台开始发展的最初,有人称赞以太坊的科技创新,但也有人质疑其安全和可扩展性。
2、激活边境
以太坊的公共区块链在2015年7月30日引导。最初的以太坊版本称为边境(Frontier,也有“前锋”的意思),用的是工作量证明(proof-of-work)的算法,但未来预期会转换成权益证明(proof-of-stake)。
3、分叉
第一次分叉:挖矿
自最初版本以来,以太坊网络成功进行了数次硬分叉。第一次分叉调整了未来挖矿的难度,确保未来的用户会有转换至权益证明的动机。
第二次分叉:家园
2016年春季进行了第二次分叉,发布了第一个稳定版本,称作“家园”(Homestead)。
第三次分叉:DAO和区块链分叉
2016年六月,以太坊上的一个去中心化自治组织The DAO被骇,造成市值五千万美元的以太币被移动到只有该黑客可以控制的“分身DAO”。因为程序不允许黑客立即提取这些以太币,以太坊用户有时间讨论如何处理此事,考虑的方案包括取回以太币和关闭DAO,而DAO去中心化的本质也表示没有中央权力可以立即反应,而需要用户的共识。
最后在2016年7月20日,以太坊进行硬分叉,作出一个向后不兼容的改变,让所有的以太币(包括被移动的)回归原处,而不接受此改变的区块键则成为古典以太坊(Ethereum Classic)。这是第一次有主流区块键为了补偿投资人,而通过分叉来更动交易纪录。
在这次分叉之后,造成了在两个区块链之间进行重放攻击的可能,加上其他网络攻击,让以太坊和古典以太坊又各自进行了数次分叉来避免攻击。
第四次分叉:减重和防DDoS
2016年11月底进行了第四次的分叉。这次分叉为区块链减重(de-bloat),并加入一些避免网络攻击的设计。因为沟通疏失,这次分叉短暂造成以太坊的两个主要客户端程序 Parity 和 Geth 失去共识而产生意外的分叉,但问题在数小时内即被找出并修正。
相较于较大多数其他加密货币或区块链技术,以太坊的特点包括下列:
(1)智能合约(smart contract):存储在区块链上的程序,由各节点运行,需要运行程序的人支付手续费给节点的矿工或权益人。
(2)叔块(uncle block):将因为速度较慢而未及时被收入母链的较短区块链并入。使用的是有向无环图的相关技术。
(3)权益证明(proof-of-stake):相较于工作量证明,可节省大量在挖矿时浪费的电脑资源,并避免特殊应用集成电路造成网络中心化。(尚未实现)
(4)闪电网络(lightning network):可提升交易速度、降低区块链的负担,提高可扩展性。
(5)开发社区稳固,不断成长,勇于使用硬分叉(hard fork)。
以太坊是一个平台,它上面提供各种模块让用户来搭建应用,如果将搭建应用比作造房子,那么以太坊就提供了墙面、屋顶、地板等模块,用户只需像搭积木一样把房子搭起来,因此在以太坊上建立应用的成本和速度都大大改善。具体来说,以太坊通过一套图灵完备的脚本语言(EthereumVirtual Machinecode,简称EVM语言)来建立应用,它类似于汇编语言,我们知道,直接用汇编语言编程是非常痛苦的,但以太坊里的编程并不需要直接使用EVM语言,而是类似C语言、Python、Lisp等高级语言,再通过编译器转成EVM语言。
上面所说的平台之上的应用,其实就是合约,这是以太坊的核心。合约是一个活在以太坊系统里的自动代理人,他有一个自己的以太币地址,当用户向合约的地址里发送一笔交易后,该合约就被激活,然后根据交易中的额外信息,合约会运行自身的代码,最后返回一个结果,这个结果可能是从合约的地址发出另外一笔交易。需要指出的是,以太坊中的交易,不单只是发送以太币而已,它还可以嵌入相当多的额外信息。如果一笔交易是发送给合约的,那么这些信息就非常重要,因为合约将根据这些信息来完成自身的业务逻辑。
以太币比比特币更复杂。概要地说,以太币的数量以这种形式存在: Pre-mine(矿前) + Block rewards(区块奖励) + Uncle rewards(叔块奖励) + Uncle referencing rewards(叔块引用奖励)。总量无上限。以太币(ETH),作为推动以太坊平台上分布式应用的加密燃料,将会通过挖矿的形式每年以不变的数量发行。每年发行的数量是预售以太币总量的0.3倍。
(1)矿前
2014年7月/8月间,为众筹大约发行了7200万以太币。这些币有的时候被称之为“矿前”。众筹阶段之后,以太币每年的产量被限制在7200万以太币的25%(每年以太币的矿产量,不高于1800万,除了一次性为crowdsale而发行的7200万以太币)
(2)区块奖励
目前,每产生一个新区块就会产生5个新以太币。计算一下,如果每14秒挖出一个区块,一年有3150万秒(365x24x60x60),这意味着每年有225万个区块被挖出来。225万个区块,每个区块5个以太币,也就是每年会产出1130万个以太币。这个数字与低于1800万以太币产量的数字,吻合。
(3)叔块奖励
事实上,数量可能会比上述数字稍多一些。有些区块被挖得稍晚一些,因此不能称为主区块链的组成部分。比特币称这类区块为“孤块”,并且完全舍弃它们。但是,以太币称它们为“ uncles”,并且在之后的区块中,可以引用它们。如果uncles在之后的区块链中作为叔块被引用,每个叔块会为挖矿者产出大约4.375个以太币(5个以太币奖励的8分之7).这被称之为叔块奖励。目前每天有大约500个叔块被创建,为以太币的日产量链,额外加入2000个以太币(以这种速度,每年产量为70万以太币)
(4)叔块引用奖励
还有更多:矿工每引用一个叔块,就得到了大约0.15个以太币(最多引用两个叔块)
这种定义有效区块,奖励矿工的模式称为“幽灵协议”(Greedy Heaviest-Observed Sub-Tree )(GHOST是贪婪最被观察子树的字首)。
(5)以太币产量未来的变化
以太坊出块机制从工作量证明(PoW)(包括幽灵发行规则)转换为股权证明(PoS)后,以太币的发行会有什么变化尚未有定论。股权证明机制将使用一个称为Casper的协议(是的,作为友好的幽灵。谁说cryptonerds没有幽默感来着?)在Casper协议下,以太币的发行率将大大低于幽灵协议下的发行率。
一.概述
在以太坊中,数据的存储大致分为三个部分,分别是:状态数据、区块链和底层数据。
image其中,底层数据存放以太坊中全部数据,存储形式是[k,v]键值对,目前使用数据库是LevelDB;所有与交易,操作相关的数据,都存储在链上;StateDB 是用来管理账户的,每个账户都是一个 stateObject。
源码分析见http://wangxiaoming.com/
UTXO模型为了避免double spending(双花),发起者不诚实
账户余额模型天然防御双花攻击,面临reply attack(重放攻击),接收者不诚实。账户交易包含nounce(次数,计数器)避免
交易只能由外部账户发起,外部账户包含balance,nounce,合约账户还包含code,storage
以太坊地址是160位(20 bytes),40位十六进制数
比特币的sorted tree可以证明 non-Merkle Tree(不在梅克尔树)
状态树:modified MPT(Merkle Patricia Tree,或者Trie)路径压缩。合约账户维护一个小的MPT
以太坊有三棵树:状态树,交易树,收据树。保存在全节点的本地数据结构。数据结构:modified MPT,支持查找操作
状态树的value经过RLP(Recursive Length Prefix,递归长度前缀) 编码后存储。RLP只支持nested array of bytes(字节数组,可以嵌套)
状态树包含系统中所有账户的状态,无论账户是否参与当前区块的交易
交易树和收据树引入了bloom filter数据结构
数据结构bloom filter可能出现false positive(误报),不会出现漏报。不支持删除操作
这三个Merkle Tree对应的第一个是表示状态数据
的哈希值;第二个是交易的哈希值构成的根哈希值(交易数据
);第三个是交易执行完毕后产生的回执数据
的哈希值
二.solidity语言
不支持hash表的直接遍历,需要自己定义类型实现,如数组
算术运算使用SafeMath库,防溢出
合约调用的区别:
直接调用会引发连环出错
address.call()方法,如果出错,可以继续往下执行
2.0 代理调用 delegatecall()
使用方法与call()相同,只是不能使用.value()
区别在于是否切换上下文
• call()切换到被调用的智能合约上下文中
• delegatecall()只使用给定地址的代码,其它属性(存储,余额等)都取自当前合约。delegatecall 的目的是使用存储在另外一个合约中的库代码
2.1 fallback()函数
function() public [payable]{
……
}
匿名函数,没有参数也没有返回值。
在两种情况下会被调用:
• 直接向一个合约地址转账而不加任何data
• 被调用的函数不存在
如果转账金额不是0,同样需要声明payable,否则会抛出异常
2.2 错误处理
智能合约中不存在自定义的try-catch结构
一旦遇到异常,除特殊情况外,本次执行操作全部回滚
可以抛出错误的语句:
• assert(bool condition):如果条件不满足就抛出—用于内部错误。
• require(bool condition):如果条件不满足就抛掉—用于输入或者外部组件引起的错误。
• revert():终止运行并回滚状态变动
所有智能合约均可显式地转换成地址类型
2.3三种发送ETH的方式
<address>.transfer(uint256 amount) 失败抛出异常
<address>.send(uint256 amount) returns (bool) 失败返回false
<address>.call.value(uint256 amount)() 发送所有可用gas
前2种方式发送2300gas的矿工费,不可调节。
transfer交易失败会造成连锁回滚。
Uncle Block
at most 7 Generation(叔块奖励2/8~~7/8)。只检查叔块创建是否符合挖矿难度(只检查header),其包含的交易不执行
挖矿算法
16M的cache(轻节点使用),1G的dataset,DAG。初始大小,数据集定期增长,每隔30000个block增长128/1i
ghost协议,判断最长链