共识算法用于解决点对点网络节点之间账本的一致性
区块保存了三颗Merkle树的根:状态树、交易树、收据树。
以太坊出块时间大概为15s
账户以地址为索引,地址由公钥的最后20字节产生
分为两种账户:外部账户与合约账户。外部账户由人创建,可存储以太币,由公私钥控制的账户,合约账户是由外部账户创建的账户。外部账户存储以太币余额状态,而合约账户除了余额还有智能合约及其变量的状态。
一个以太坊的账户包含四部分:
(1)外部账户
EOA(externally owned account)外部账户由私钥来控制,是由用户实际控制的账户。外部账户不能包含以太坊虚拟机(EVM)代码。
一个外部账户有以下特性:一定的账户余额、可以发送交易、通过私钥控制、没有相关代码。
可以使用以太坊客户端创建一个外部账户,生成一个账户地址的过程有以下三步:
1)设置账户私钥,即账户密码
2)使用加密算法(secp256k1,椭圆曲线密码算法)由私钥生成对应公钥
3)根据公钥得出相应的账户地址
以太坊使用SHA3由公钥得到账户地址。
以太坊没有让用户重置或者找回密钥的功能。
在以太坊节点之间传输整个目录或者密钥文件是安全的
(2)合约账户
合约账户是一个包含合约代码的账户,由合约代码控制而不是由私钥控制。地址是由合约创建时合约创建者的地址,以及该地址发出的交易共同计算得出的。
具有以下特性:拥有一定的以太币余额,相关联的代码、代码通过交易或者其他合约发送的调用来激活;合约执行时,只能操作合约账户拥有的特定存储。
合约账户与普通账户最大的不同就是它还存有智能合约。
每当合约账户收到一条交易信息时,合约代码将被交易输入的参数调用执行。而合约代码将会在参与到网络中的每一个节点上执行,并且将执行结果作为新块验证的一部分
公钥加密是发送者先用公钥加密,接收者再用私钥解密;而公钥认证是发送者先用私钥加密,接受者再用公钥解密以验证。
钥匙文件是json文本文件。钥匙文件可以在以太坊节点数据目录的keystore子目录下找到。
把管理数字密钥的软件称为钱包。备份钱包其实就是备份账户的私钥文件。
以太坊钱包分类:
保管私钥的目的是为了防盗(分离备份)、防丢(多处备份)、分散危险 (将资金适当地分散开,同时采取多重签名方式,提取超过事先预定的金额时需要多个密钥授权)
钱包备份有两种方式:
以太坊针对三种对象设计了三颗Merkle树(Merkle Patrcia树),分别是状态树、交易树与收据树。
区块、交易等数据最终都是存储在LevelDB数据库中。LevelDB数据库是一个键值对(key-value)数据库,key一般与散列相关,value是存储内容的RLP编码。
以太坊使用了Merkle Patricia树(简称MPT),作为数据组织形式,用来管理用户的账户状态、交易信息等重要数据。MPT融合了Merkle树和Trie树(前缀树)两种数据类型的优点。
Merkle树具有以下特性:
Trie树:
Trie树也叫做Radix树。在Radix树中,key代表的是从树根到对应value的一条真实路径。即从根节点开始,key中的每个字符都代表从根节点出发寻找对应value所要经过的子节点。value存储在叶节点中,是每条路径的最终节点。若key中的每个字符都来自一个容量为N且所包含的字母都互不相同的字母表,那么树中的每个节点最多会有N个孩子,树的最大深度为key的最大长度。
Trie树的优点:若有两个value,且拥有基于相同前缀的key,它们相同前缀的长度占自身比例越大,则代表这两个value在树中的位置越靠近,并且Trie树不会有像散列表一样的冲突,即一个key仅仅对应一个value。
Trie树的缺陷:存储不平衡,即给定一个长度较长的key,在树中无其他key与它有相同的前缀,那么在遍历或存储key所代表的value时,将会遍历或存储相当多的节点,因此树是不平衡的。
Merkle Patricia树:
为了保证树的加密安全,每个节点通过它的散列值被引用,用于在LevelDB数据库中的查询。对于存储在LevelDB数据库中的非叶节点,其在数据库中的表现形式为:key代表着节点的RLP编码的SHA3散列值,value是节点的RLP编码。要想获得一个节点的内容,只需要根据该节点的散列值访问数据库以获得节点的RLP编码,然后解码即可。
MPT中的节点:
MPT还有一个重要的概念:用于对key进行编码的特殊十六进制前缀编码(HP)。因为字母表中的字符都是十六进制表示的,故每个节点最多只能有16个“孩子”。因为键值对有两种表示形式的节点(叶节点和扩展节点),故需引用一种特殊的终止符标识,用于标识key所对应的值是真实的值还是其他节点的散列值。通过对终止符标识进行赋值,可以区分key所对应的节点的种类,无论key的长度是奇数还是偶数,HP都可以对其进行编码。
以太坊区块链系统中使用了MPT树结构,每个区块头为三种对象设计了三棵树,分别是交易树(Transaction Tree)、状态树(State Tree)、收据树(Receipt Tree)。利用三棵树,可以查询:
计算前4项任务简单,只需要服务器根据查询需求找到对象,获得对应的Merkle树分支,即可得到结果并且返回给客户端。对于第五种查询,由状态数来处理。若在根为S的状态树上执行一笔交易T,其结果状态树将是根为S‘,输出为O’‘。服务器会在本地创造一个假的区块,将其状态设为S,并且假装是一个轻客户端,请求执行这笔交易并将执行结果返回给客户端。
以太坊中的状态树包含键值映射,其中键为地址,而值包括账户的声明、账户余额、nonce、代码以及每一个账户的存储。由于账户余额和账户的nonce经常改变,新的账户会频繁插入,存储的键也经常被插入以及删除,所以状态树需要经常更新。
状态树中的每个节点由16个孩子节点,每一个叶子节点表示一个账户,这些叶子节点的父节点由叶节点的散列值组成,而这些父节点在组成更高一层的父节点,直至形成根节点。状态树包含一个键值映射,其中键是账户地址,值是账户内容,主要是{nonce, balance,codeHash,storageRoot}。nonce是账户余额,codeHash是代码的散列值,storageRoot是另一棵树的根节点。状态树代表访问区块后的整个状态。
以太坊是一个以账户为基础的区块链应用平台,所有的账户状态都是以“状态数据”的形式存储在以太坊的节点中。区块链中的全局状态是账户地址(160位标识符)和账户状态(经过RLP编码序列化的一种数据结构)之间的映射。
状态数据是一种隐式数据,即需要从实际的区块链数据中计算出来,交易包含决定新状态数据的所有字段内容,以太坊区块包含了整个状态树的Merkle树根散列和交易列表。状态树是用来记录各个账户的状态的树,需要经常更新。
每个区块都有一个独立的交易树。不过矿工一般会根据交易的GasPrice和nonce对交易进行排序。首先会将交易列表中的交易划分到各个发送账户,每个账户的交易根据这些交易的nonce排序。每个账户的交易排序完成后,再通过比较每一个账户的第一笔交易,选出最高价格的交易,这是通过一个堆(heap)来实现的。每挖出一个新块,更新一次交易树。
在交易树包含的键值对中,其中每个键是交易的编号,值是交易内容。
每个区块都有自己的收据树,不需要更新,代表每笔交易的收据。其键值映射中的键是索引编号,用来指引这条收据相关交易的位置,值是收据的内容。交易的数据是一个RLP编码的数据结构:[medstate, Gas_used, logbloom, logs]。其中,medstate是交易处理后树根的状态;Gas_used是交易处理后Gas的使用量;logs是表格[address, [topic1, topic2, ···], data]元素的列表,表格由交易执行期间调用的操作码LOG0···LOG4生成(包含主调用和子调用),address是生成日志的合约地址,topicn是最多4个32字节的值,data是任意字节大小的数组;logbloom是交易中所有logs的address和topic组成的布隆过滤器(是一个二进制向量数据结构,具有很好的空间和时间效率,可以检测一个元素是不是集合中的一个成员)。区块头也存在一个布隆过滤器,可以减少查询的工作量,使得以太坊协议对轻客户端尽可能的友好。
LevelDB是一个高效的键值对数据库,键值都是二进制的。以太坊有三个LevelDB数据库,分别是BlockDB(保存区块的主体内容,包含区块头和交易)、StateDB(保存账户的状态数据)、ExtrasDB(保存收据信息和其他辅助信息)。
LevelDB的接口很简单,包括put(k, v)、get(k, v)和delete(k, v)。除此之外还有以下特性:
除此之外还存在一定的限制:
共识机制是区块链事务达成分布式共识的算法。用于P2P网络中存在延迟,故各节点收到事务的顺序可能不一样,所以有必要设置一种机制让节点对在差不多时间内发生的事务顺序实现共识,这就是共识机制。
哈希函数特征:
免碰撞,不同输入一定对应不同输出
隐匿性,不能逆推输入值
除了穷举,别无他法
比特币的PoW算法:节点打包经过验证的交易,通过不断地更换随机数来探寻合适的散列值(指该值小于系统提供的某一散列值),当节点最先算出合适的散列值,所打包的快如果通过其他共识节点的验证则会被加入到区块链中。
以太坊的PoW算法——Ethash算法,使用后者替换前者是为了解决挖矿中心化问题。现在的情况是一些硬件公司和挖矿机构通过挖矿资源的集中,获得了可以操纵现有网络内经济力量的优势,并获得高利润(如比特币和莱特币)。这些组织可以生产具有超高散列计算性能的ASIC(Application Specific Integrated Circuit,特殊应用的集成电路),为自己赚取利润,打破了区块链的高度去中心化优势。为了抵制ASIC、轻客户端可快速验证,希望减少中心化挖矿在以太坊中获得经济奖励,这就是Ethash算法。
以太坊让挖矿者从区块链状态中获取随机数据,计算从区块链的最后N个区块中随机选择的交易,返回结果散列。好处:1)以太坊合约能包含任意种类的方式,以太坊的ASIC本质是一个提供普通计算的专门集成电路,可视为很好的CPU。2)挖矿需要访问整个区块链,这迫使挖矿者保存完整的区块链。
Ethash算法的特点是挖矿的效率基本与CPU无关,与内存大小、带宽正相关,目的是去除专用硬件的优势,抵抗ASIC。流程如下:
缓存和DAG中每增加30000个区块更新一次,故矿工一般会专注于读取数据集,而不是改变它。
验证过程和DAG产生的过程使用大量的散列计算,是PoW的具体体现。选择16MB的缓存是因为一个基于较小缓存的ASIC更容易生产,16MB的缓存仍然需要非常高的带宽读取,而较小的缓存更容易优化。将DAG的大小设为1GB,使其内存大于大多数专门的存储器和高速缓存器。但是对于普通的计算机而言它仍然足够的小,能利用它挖矿。
PPC(Peercoin,点点币)和NXT(未来币)使用的PoS算法表达方式不同。PPC使用PoW/PoS混合模式,用PoW解决货币产出的公平性,用PoS来保证网络安全,在其PoS中,每秒钟选择一个不同的验证者来产生区块。NXT则是100%采用PoS模式,基于账户余额调整用户被选择出块的可能性,并使用一个确定性算法随机选择一个股东来产生下一个区块。
拜占庭容错是对现实网络问题的模型化,由于硬件错误、网络拥塞或者断开以及遭到恶意攻击,计算机和网络可能出现不可预料的行为。拜占庭容错协议必须处理这些失效,并且这些协议还要满足所要解决问题要求的规范。
以太坊的PoS算法可以这样描述:以太坊区块链由一组验证者决定,拥有以太币的用户均可以发起一笔特殊形式的交易,将自己的以太币锁定在一个存储中,从而使自己称为验证者,通过当前验证者均可以参与的共识算法,完成新区块的产生和验证。
有两种类型的PoS:基于链的PoS和BFT(Byzantine Fault Tolerant,拜占庭容错)风格的PoS:
以太坊的每个节点都必须承担确认和验证交易的责任,这才是去中心化的管理模式,能够提高利益相关者在网络中的参与度。
未购买以太币的人无法对系统产生威胁,也就是说攻击者在系统中。
PoS的优点:
ETH,以太币来源包括:矿前+区块奖励+叔区块奖励+叔区块引用奖励:
以太币发行每年是1800万。理论上如果这个发行量是无限期的,则在某种程度每年创造的代币和丢失的差不多(如私钥丢失,持有人死亡),会达到动态平衡。
当前以太币使用幽灵协议(GHOST),自2018年,以太坊使用新的协议算法(Casper)代替当前的工作量证明机制,效率更高且需要更少的挖矿补贴。在Casper协议下以太币的发行率将大大低于幽灵协议下的发行率。
以太币有各种面额,最小的单位是wei(维),下面是主要货币单位:
以太坊上的账户管理和智能合约的部署都要花费以太币。挖矿奖励有两种:
以太坊出块时间为15s。
可以通过购买或者挖矿获得以太币,下面介绍几种可以获得以太币的交易所:
交易是指账户发送到区块链上另一账户的消息的签名数据包,包含发送者的签名、接收者的地址以及交易的以太币的数量。有手续费,用于支付交易所需要的计算开销。引入Gas作为执行开销的基本单位,提供Gas price与以太币进行换算,Gas price随市场波动调整,避免以太币价值受到市场的价格影响
为避免无意义交易,浪费矿工计算资源,所有公有链都采用交易收费,要求为每笔交易付出一定的代价。这笔交易费会由打包交易加入主链的矿工收取。比特币付出的交易费相对固定,而以太坊引入的智能合约,创建和调用的交易所耗费的计算差别较大,因此引入了Gas,Gas price。
至于区块的Gas Limit,表示区块包含的交易消耗的Gas的上限,由矿工决定其大小。总之,被打包交易的Gas Limit数量之和不能大于区块的Gas Limit。
区块的Gas Limit设置的越大,矿工收取的交易费越多,但是需要更多的带宽,叔区块出现的频率也会增大,使得挖出的区块无法形成最长的交易链。矿工不能随意更改区块的Gas Limit,以太坊规定当前区块的Gas Limit只能基于上一个区块的Gas Limit上下波动的1/1024。
交易内容
以太坊的交易是指存储从外部账户发送到区块链上另外一个账户的信息的签名数据包,可以是数字货币——以太币的转账,可以是包含智能合约的信息。一条交易包含以下:
交易有三种类型:
web3.eth.sendTransaction({
from: "safd7tsadf6tadsfrasd5sadf6t87saf5987asdf"
to: "asfdadsfasdvy76sadv87dsa6vas76dvcasdfdr5"
value: 1000000000
});
web3.eth.sendTransaction({
from: "0xsadyf76fdsadfr4a5sdfd9875sadv"
data: "contact binary code"
});
web3.eth.sendTransaction({
from: "0xafds65dsafasdfas45dfasf5387"
to: "0xads987fadsffvafasdf2as65d7f87"
data: "hash of the invoked method signature "
})
下面是一个查询交易的例子
web3.eth.getTransaction('0x3sda5c46dsa8cas8d7f9a8ds7f809sadf9')
{
blockHash: '0xdsa97fasdfasdfa0987dsfa6fdsfdsa',
blockNumber: 23412,
from: '0xds6fasdfasdgf45asdf64sadf86asddsafda',
Gas: 9000,
Gas price: 50000000000000000000,
hash: '0xasfdsadf5sadgy5sad46f75dsa98f609dsd';
input: '0x',
nonce: 32142,
to: '0xdasf7df6adsfa45987sadsf6sadf897sadfysad';
transactionIndex: 0,
value: 1234123412340000
}
用户可以使用sendTransaction执行一个交易,下面的代码就是一个简单的发送交易的示例,若想使用其他单位,可以使用web3.toWei进行转换
eth.sendTransaction({from: "0xdsafsadfasdfsa87d597586sadf", to: "0xds64fdsa4f5a86f7a9sd6asd", value: web3.toWei(1, "ether")})
RLP(Recursive Length Prefix,递归长度前缀法)是一种编码方法,用于编码任意的具有嵌套结构的二进制数据,是以太坊数据序列化的主要方法。以太坊中的区块、交易等数据结构会先经过RLP编码处理,然后存储到数据库中。RLP编码只处理两种类型的数据,即字符串和列表,并不包括原子数据类型,如整型、浮点型等。在RLP格式中,对字典数据的编码有两种建议方式:一种是按照字典顺序用含关键字的二维数组来表示,如:[[k1, v1], [k2, v2]… ],另一种是使用更高级的Patricia树来编码。
在以太坊中,当发送数据以及在MPT树中保存状态时,需要使用RLP编码。在用RLP编码处理的数据中,字符串一般指的是一串二进制数据,列表则是一个嵌套递归结构,列表元素可以是字符串或列表,通过这种方式可以实现数据的递归存储,如[“red”, [“blue”, “white”], purple]就是一个具有嵌套递归结构的列表。若要使用RLP编码对其他类型的数据进行处理,必须要将其转换成上述两种类型,RLP没有定义转换规则,用户可以按照自己的规则转换,如结构体可以转换为列表,int可以转换为二进制数(属于字符串一类)。
RLP的编码规则如下:
以太坊客户端是由以太坊基金会和以太坊研究组织开发的,供用户使用的人机友好的操作软件。使用客户端,用户可以在本地计算机上创建以太坊节点,还可以执行建立在以太坊上的去中心化应用,进行一些以太坊交易活动。
常用的以太坊客户端:
除此之外还有EthereumH(Hashell实现),Ruby-ethereum(Ruby语言实现)等以太坊客户端。
API(Application Programming Interface,应用程序编程接口)是一些预定义的函数,目的是提供应用程序与开发人员基于某些软件或硬件直接访问一组程序的能力。用户通过调用API可以直接获得某些服务,而无需了解内部细节。
JSON-RPC是一个无状态、轻量级的远程过程调用(Remote Process Call)协议,这个规范首先定义了几个数据结构及其处理规则,数据格式为JSON。
目前有两种数据类型是通过JSON传递的:无格式字节数组和数,二者均使用十六进制进行编码传递,但是对传递格式有不同的要求。
JSON-RPC API是较低等级的JSON-RPC2.0接口,其功能是与节点进行交互。
通过内部的JavaScipt应用通知一个以太坊节点使用Web3.js库,为RPC方法的使用提供了方便的交互界面。要让应用程序在以太坊上运行,可以使用Web3.js库提供的Web3对象。通过RPC调用Web.js可以与本地节点进行通信,并且能与RPL层次上的任何以太坊节点一起工作。
ENS(Ethereum Name Service,以太坊域名服务)是建立在以太坊区块链上的分布式、开放的命名系统。在以太坊网络中,地址比较长而复杂,记忆困难,为方便用户,以太坊推出可以将散列地址翻译成一个简短易记的地址的ENS命名服务。
ENS由三个主要构件组成,分别是注册表(registry)、解析器(resolver)和注册服务(registrar)。其中注册表是系统的核心不可变的部分,解析器最终由用户实现,注册服务是在ENS中拥有名称并根据规则分配子域的智能合约。ENS是以太坊基金会提供的去中心化应用。ENS做了两件事:1)使用户注册支持智能合约运行的域名;2)利用底层设备标识符解析部分域名。
用户要想获得域名的所有权,主要通过竞拍的方式。