以太坊原理书¶
原文地址:https://ethbook.abyteahead.com/
以下为笔者个人认为的重点总结
第 1 章 以太坊:一台全球计算机¶
简史¶
以太坊是什么?
以太坊(Ethereum),是一个全球协作的开源区块链项目。
- 该项目流通的加密货币称为以太币 (Ether),是全球仅次于比特币的第二大流通加密货币。
- 特色:具有一个运行时环境:以太坊虚拟机 (Ethereum Virtual Machine,简称 EVM), 为大规模分布式开放应用提供了运行的平台。
-
目标: 全球化的计算基础设施,也就是具有分布式、 公开透明、永不下线特性的全球计算机 。
-
在这台分布式计算机上运行的小程序, 被称为 智能合约 (Smart Contract)。
- 以太坊项被誉为区块链 2.0 时代的里程碑(比特币为区块链1.0时代)
第 2 章 账户是什么¶
基础知识¶
以太坊分布式地运行在一个计算机网络上,作为一个区块链项目,它具有几大要素:
- 一条完整记录所有交易的区块链
- 一个由数个节点组成的网络
- 一个大家公认的共识机制
它也具备两个特殊的要素:
- 每个节点具备运行智能合约的环境,
- 以及由交易推动的,随着每次交易不断变化的世界状态。
我的以太币记录在哪里?¶
你的以太币记载在 世界状态 (world state)里。
世界状态 = 每个人账户的状态的总集合
世界状态是一份不断变化的数据。 它在每个以太坊节点中都有一份一模一样的拷贝。 该状态记录了所有世界上以太坊账户的信息。
我的以太币余额如何变化?¶
你的以太币余额因为交易而变化。
促成 世界状态 (world state) 转移的手段过程是 交易
什么是区块?¶
区块(block) 是多个合法签名的 交易的有序集合 。
任何一个区块都包含几部分:
- 其前一区块的哈希值
- 当前区块的哈希值
- 一个计算工作量的参数
- 一个时间戳
- 该区块包含的交易列表的哈希值
在区块模型中,交易列表会用一棵树型结构来表示,并将该树的哈希值写入区块头进行防伪校验。
区块是 串联 成区块链的,一个区块包含了数笔交易。
区块和状态的关系¶
世界状态因为发生的交易而依序进行状态转移,而交易产生的前提是基于某一个时刻的世界状态。
“巨大的账本”¶
前文提到,区块是“多个合法签名交易的有序集合”。这就好比是账本中的一页记录。
创世区块是账本的第一页。
随着时间的推移,区块链不断记账,经过共识算法挑选的合法区块 逐一 堆叠而成的区块链是一个巨大的交易账本, 而最早的创世区块交易记录被压在 最下方 。
如下图所示,从这个观点来看,区块所组成的链,就是一个 账本的堆栈 。 每一页都记载着数条交易记录。最古老的记录处在账本的最下方, 若想推翻压在下方的某一区块记录,就得重新计算该区块之后的所有区块。 这么大的计算量对攻击者而言,是不经济的。
我如何参与以太坊?¶
你可以通过一台计算机来联网参与以太坊网络。
我如何与其他人同步账本?¶
以太坊节点之间的消息传递是将大块数据分割成小块后,用 点对点(P2P) 的技术传送、扩散的。
没有一个中央服务器负责数据校准或者消息扩散引导,这与分布式下载工具 比特彗星(BitComet) 有相似之处。 网络交易的发送、智能合约的调用、被挖掘出的新区块的播报,都是通过点对点网络进行广播的。 当发送交易时,用户将交易通过节点广播出去,在矿工成功打包出块后将区块广播到网络里。
所以你的本地账本是通过 P2P 网络分块下载的。就和BT下载差不多。
你发出的交易也是通过同一个 P2P 网络扩散出去的。
你的交易被打包后,最后也是通过P2P网络传消息回来,告诉你的。
在整个自治网络中,没有中央服务器,节点可以 随时* 选择自愿加入或者离开节点网络。
账户揭秘¶
在以太坊创建一个账户,就如同在银行开户一样。
账户是安全地进行以太坊交易的基础。 与在银行开户不同的是,以太坊的账户可以离线生成而不需要得到任何工作人员的许可, 并且这些账户是 完全匿名 的。 适用于生成账户的开源工具有很多,如网页工具、桌面软件、手机APP等。 它们遵循同一套账户生成标准。 一个用户也可以同时生成、保存、持有多个账户。
账户与账户状态¶
以太坊的账户共分成两类
- 外部账户 (Externally Owned Account, EOA )
- 智能合约 (Contract Account, CA )。
外部账户由 一把私钥 与该私钥对应的公开地址来表示。在一般情况下,私钥掌握在用户的手中。
智能合约账户 没有私钥 ,仅有公开的地址,它的行为由合约自身包含的代码逻辑来控制。
账户的状态(Acccount State)描述了一个账户当前的情况。 以太坊公链时时刻刻跟踪并维护着每一个账户的状态。 一个账户在初次接收或者发出交易后,都会形成初始状态。 随着时间的推移,每次针对该账户的交易将不断修改其状态。
总结而言,每一个账户在数据结构上具有两个元素:一个公开地址,一个与该地址关联的状态,如下图所示。
账户状态的内涵¶
账户状态包含四大元素:
nonce
已执行交易总数,用来标示该账户发出的交易数量;balance
持币数量,记录用户的以太币余额;storage hash
存储区的哈希值,指向智能合约账户的存储数据区;code hash
代码区的哈希值,指向智能合约账户存储的智能合约代码。
已执行交易总数:每多一次交易就加一
持币数量:可花费的以太币的数量
存储区的哈希值:该值为 智能合约独有 ,外部账户不包含该值。 存储区即为智能合约在运行中,产生的数据的存储地。
代码区的哈希值:该值为 智能合约独有,外部账户不包含该值。 代码区即为智能合约代码本身。该值即为代码区的哈希值。 在合约的生命周期中,该区域的内容是不可更改的 只读状态。
没有钱包App, 如何生成账户?¶
普通用户最频繁使用的账户主要是外部账户(Externally Owned Account, EOA)。 这个账户可以用来发送/接受以太币,也可以发起部署智能合约的行为。 以太坊的外部账户仅由私钥(private key)与它所相对应的公开地址(address)组成。
第一步,我如何生成私钥
私钥 是一个32 bytes (256 bits) 长度的随机数。用户需要一个可靠的随机源来产生该随机数,该随机数取值在0~2^256 之间。
第二步,公开地址是如何从私钥派生的呢?
这分为几个步骤:首先,我们选算法, 代入 私钥 作为参数进行运算,得出的结果为 公钥。
这个过程是不可逆的,并且是唯一与私钥对应的。 其次,在生成公钥后,再将其进一步放入一个哈希算法生成哈希值,截取哈希值的最后40位16进制字符得到地址(160 bits或20 bytes)。
我生成的账户安全吗?
和一般的网站申请账户不同, 加密货币的账户仅需要可靠的软件在离线状态下生成 , 而不需要去特殊网站进行注册。 如何保证每次生成的私钥不是已经被他人生成过的
在现实中,两个私钥碰撞的概率有多大呢?
我们已知:私钥地址空间有 2 256,而宇宙中的已知原子总数有 10 80, 两者比较谁大谁小?我们做一个除法。
2256÷1080=1.1579209e+69=10692256÷1080=1.1579209e+69=1069
从上述算式可以看出,私钥空间比我们宇宙空间的原子总数的倍数还要多。
你生成的账户,是安全的。
能合约地址的生成¶
智能合约也有账户,它是如何生成的呢?
与外部账户不同,智能合约账户的地址创建并非由外部促成,而是在创建合约时候由代码自动生成的。智能合约账户有公开的地址,却没有对应的私钥,这意味着:
- 合约转出以太币,并非通过私钥签名方式。
- 只有合约自身的逻辑代码能够管理它的以太币,除极少数例外(例如合约创建者销毁合约,合约收到的以太币将默认打给该创建者)。
第 3 章 交易是驱动力¶
交易的发送¶
交易由客户通过客户端软件发送。
下图为客户端软件通过 web3
与向网络发送交易的示意图。
交易分为简单的转账交易与智能合约调用,收到交易请求的节点进行相应的余额变更或者执行合约代码,在这个过程中是要消耗计算机算力、 内存与占用硬盘存储空间的。
相应地,该交易发起者也需要支付交易费来承担该计算行为,交易是用以太币支付的。
用户与以太坊互动的行为只有一种:发送交易。 以太坊上的交易活动是由三个步骤完成的:
- 用户签名打包一条或多条消息,组装成一笔交易,发送到以太坊网络上。
- 该交易被矿工捕获,并收纳入某一个区块。
- 区块形成后,被矿工广播到节点网络中,最终加入区块链。
交易与消息的区别¶
在以太坊中,经常混淆的两个概念是交易transaction与消息message。
交易 是外部账户发起的,可以包含一条消息。
消息 在账户与账户之间传递数据(data)与价值(value),消息的具体表现形式如下:
- 数据:一个账户向另一个账户请求函数调用。
- 价值:一个账户向另一个账户发送以太币。
消息的确可以由外部账户通过请求一次交易来触发。但是,被作用的对象如果是一个智能合约的话, 它还可以进一步调用其他的合约 (进一步发送消息);
举例说明:某用户调用了智能合约A的一个方法。可能会依序发生如下的效果:
- A合约代码被运行,该方法中调用了另一个智能合约B的一个方法。(函数调用)
- B合约代码被运行。运行中要给账户C 转账以太币。(价值转移)
- 以上的函数调用和价值转移这类消息并不是外部可见的,不记录在区块里。
交易的特性是什么?¶
“原子性”
修改操作要么完全执行,要么完全不执行 ,它不会部分执行,部分不执行。
“串行” 执行
单一时刻只有一个交易被执行,不会有并行出现。
“进入区块链的顺序不确定”
当全球的数万名用户向区块链中的节点发送交易时,交易最终进入区块链的顺序并不取决于发送的前后顺序
交易的样子¶
{
nonce: web3.toHex(10),
GasPrice: web3.toHex(100000000000),
Gas: web3.toHex(140000),
from: '0x633296baebc20f33ac2e1c1b105d7cd1f6a0718b',
to: '0xD1E1cdbCE15f1009B5A7874053E09C728Df91d47',
value: web3.toHex(0),
data: '0xcc9ab24952616d6100000000000000000000000000000000000000000000000000000000'
}
- nonce 该账户已发送交易数量,一个正整数。
- GasPrice 和 Gas 与现实生活中的汽油费类似,用以支付交易费。交易费 = Gas x GasPrice
- From 该笔交易的发送方。
- To 该笔交易的接收方。
- value 具体转移多少以太币到接收方。
- data 数据字段。
交易的生命周期¶
交易的生命周期从用户通过某节点/软件广播该交易为起点,经过网络扩散、矿工挖矿记账、被共识算法选入最终区块链条,到达终点。
从最源头开始,一笔交易的流转过程如下所示。
- 客户端软件在收集完交易信息,组织成相应的结构体,需要使用用户的私钥来签名该交易。
- 交易后编码为一个公开消息,通过节点网络发出并逐渐扩散到网络中各个节点。
- 挖矿节点和众多其他普通节点同时收到该消息,矿工将其暂时缓存起来。
- 若矿工决定将该交易打包入某区块,则执行该消息内容并获得执行结果。
- 矿工把打包好的区块(包含该交易)广播到网络中,参与共识算法挑选。
- 区块进入最终的区块链被永久保存。
以太坊上最常见的交易是:
- 以太币转账
- 智能合约调用
- 智能合约创建
这三种交易在交易发送时经历的步骤是一模一样的,区别仅在于填写交易时选择传递数据 data 还是传递价值 value 。
资料篇:共识与工作量证明(待完善¶
资料篇:矿工与挖矿奖励(待完善¶
第 4 章 数据结构(待完善)¶
以太坊大量使用名为 Merkle Patricia Trie (MPT树)的高效结构对数据进行组织、索引。此外,对于树的节点,使用一种高效的键值对数据库 LevelDB 进行本地持久化保存。
Radix树¶
{
"do": 0,
"dog": 1,
"dax": 2,
"dogu": 3,
"dodo": 4,
"house": 5,
"houses": 6
}
如何高效地搜索一个字符串在数据集中所对应的最终值?我们可以构建一棵树来表示该数据集。Radix树 (Radix Trie)是利用树状结构对于搜索进行优化的树。
将这个数据集的键(例如 dog
)和值(例如 0
)按照 Radix 树状结构组织起来,就是图 4-2 所示的结构, 值存储于节点中,键的存储拆分开存在树的路径中。 当查找 dodo
的值时候,仅需要从根节点开始,向下遍历三层,依次找到 d-o-d-o
四个字母即可,它对应的值是 4
。 这棵树中间键无对应值的节点的存储空间里是 null
。
Merkle树和 Merkle证明¶
Merkle Patricia树¶
第 5 章 构建一条以太坊私链¶
由于版本升级,原文这的创世块创建和运行命令过时,不适合作为教材。
第 6 章 手把手教你部署智能合约¶
什么是智能合约?¶
- 智能合约是被创造出来的独立管家
- 智能合约是能接收数据的实体
- 智能合约是代码编写的合同
- 具体部署参考原文