第1天,读以太坊白皮书 | 5天掌握以太坊 dApp 开发

464 阅读18分钟

0 前言

对我来说,了解一个产品最高效的方法就是阅读说明书。在阅读 以太坊白皮书 之后,认为很多概念比较晦涩,在没有实际开发经验的前提下阅读起来比较吃力。因此我会把其中重要又不容易理解的部分单独讲解,来帮助你们读懂以太坊白皮书。

1 比特币解决了拜占庭将军问题

1.1 拜占庭将军问题

比特币以前的所有电子货币协议所遇到的主要障碍是,尽管对如何创建安全的拜占庭问题容错(Byzantine-fault-tolerant)多方共识系统的研究已经历时多年,但是上述协议只解决了问题的一半。这些协议假设系统的所有参与者是已知的,并产生如“如果有N方参与到系统中,那么系统可以容忍N/4的恶意参与者”这样形式的安全边界。然而这个假设的问题在于,在匿名的情况下,系统设置的安全边界容易遭受女巫攻击,因为一个攻击者可以在一台服务器或者僵尸网络上创建数以千计的节点,从而单方面确保拥有多数份额。

—以太坊白皮书

这里提到了一个概念拜占庭问题容错。也可以称之为拜占庭将军问题( Byzantine Generals Problem ),是由 莱斯利·兰波特 在其同名论文中提出的分布式对等网络通信容错问题。

一组拜占庭将军分别各率领一支军队共同围困一座城市。为了简化问题,将各支军队的行动策略限定为进攻或撤离两种。因为部分军队进攻部分军队撤离可能会造成灾难性后果,因此各位将军必须通过投票来达成一致策略,即所有军队一起进攻或所有军队一起撤离。因为各位将军分处城市不同方向,他们只能通过信使互相联系。在投票过程中每位将军都将自己投票给进攻还是撤退的信息通过信使分别通知其他所有将军,这样一来每位将军根据自己的投票和其他所有将军送来的信息就可以知道共同的投票结果而决定行动策略。

系统的问题在于,将军中可能出现叛徒,他们不仅可能向较为糟糕的策略投票,还可能选择性地发送投票信息。假设有7位将军投票,其中1名叛徒。6名忠诚的将军中出现了3人投进攻,3人投撤离的情况。这时候叛徒可能故意给3名投进攻的将领送信表示投票进攻,而给3名投撤离的将领送信表示投撤离。这样一来在3名投进攻的将领看来,投票结果是4人投进攻,从而发起进攻;而在3名投撤离的将军看来则是4人投撤离。这样各支军队的一致协同就遭到了破坏。

拜占庭将军问题本质上是个信任问题,比特币之前的电子货币可以达到容忍N/4的恶意参与者,即系统出现小于N/4个叛徒时依然可以正常运行,但是利用女巫攻击(类似利用多个IP刷量的行为)可以创造大量节点从而恶意篡改投票结果。

1.2 比特币的出现解决拜占庭将军问题

中本聪的创新是引入这样一个理念:将一个非常简单的基于节点的去中心化共识协议与工作量证明机制结合在一起。节点通过工作量证明机制获得参与到系统的权利,每十分钟将交易打包到“区块”中,从而创建出不断增长的区块链。拥有大量算力的节点有更大的影响力,但获得比整个网络更多的算力比创建一百万个节点困难得多。尽管比特币区块链模型非常简陋,但是实践证明它已经足够好用了,在未来五年,它将成为全世界两百个以上的货币和协议的基石。

—以太坊白皮书

比特比解决拜占庭将军的方法是让将军决定之前先计算一道计算复杂但是容易验证的数学题,将军的决策不同题目也会不同。

先计算出来的将军公布计算结果和进攻或撤退指令。其它将军先验证结果正确性,如果正确则执行命令,验证错误则不执行。

这就是比特币的 POW( 工作量证明 )机制,通过计算一个数值( nonce ),使得拼揍上交易数据后内容的 Hash 值满足规定的上限 (计算数学题)。在节点成功找到满足的 Hash 值之后,会马上对全网进行广播打包区块 (公布计算结果),网络的节点收到广播打包区块,会立刻对其进行验证 (其它将军验证)

如果验证通过,则表明已经有节点成功解密,自己就不再竞争当前区块打包,而是选择接受这个区块,记录到自己的账本中,然后进行下一个区块的竞争猜谜。网络中只有最快解谜的区块,才会添加的账本中,其他的节点进行复制,这样就保证了整个账本的唯一性。

假如节点有任何的作弊行为,都会导致网络的节点验证不通过,直接丢弃其打包的区块,这个区块就无法记录到总账本中,作弊的节点耗费的成本就白费了,因此在巨大的挖矿成本下,也使得矿工自觉自愿的遵守比特币系统的共识协议,也就确保了整个系统的安全。

1.3 Account Model 和 UTXO

比特币系统的“状态”是所有已经被挖出的、没有花费的比特币(技术上称为“未花费的交易输出,unspent transaction outputs 或UTXO”)的集合。

—以太坊白皮书

理解这段话我们就必须搞清楚 UTXO 是什么。 其实 Account Model 和 UTXO( unspent transaction outputs ) ,是当前区块链世界里两种 保存交易记录的方式

1.3.1 Account Model

以太坊采用的 Account Model 很好理解,就好像人人都有自己的账户一样。在以太坊的世界里,余额就直接保存在账户地址中,使用区块链浏览器就可以非常直观的查询每笔一交易的细节;

1.3.2 UTXO ( unspent transaction outputs )

然而,我们在区块链浏览器中观察 Bitcoin 的转账记录,却总是让人摸不到头脑。

数据来源 btc.com

相比以太坊,比特币的转账记录一下子多出来了好多个输入与输出。出现这种难以读懂的原因,正是因为比特币采用了 UTXO 模型。 在比特币的世界里,并没有记录账户余额,确定账户余额的方法就是回顾所有之前的转账记录从而计算出余额;(这听起来好傻呀)

UTXO 模型整体来说就确保输入 == 输出

举个例子: Joe 转给 Eury 3BTC,Eric 转给了 Eury 2BTC,那么 Eury 就得到了两笔 UTXO 合计 5BTC; 这时候 Eury 要转给 Judy 4.5 BTC,但是为了满足 输入==输出,4.5BTC 与 Eury 的 UTXO 5BTC 相差了 0.5BTC,所以 Eury就要发出两笔交易来满足 输入 == 输出的条件:

  • 第一笔:Eury –> Judy 4.5BTC
  • 第二笔:Eury –> Eury(自己) 0.5BTC

UTXO 使用起来如此繁琐,那么为何还要使用呢?

这是因为 UTXO 可以有效的防止 Double Spending,也就是双花攻击;矿工要验证的是在交易中某一笔 UTXO 是否被发送过。如果 UTXO 被花费过那么 unspent transaction outputs 当然就不是 unspent。验证就会失败,有内鬼终止交易。

还有就是 UTXO 可以隐匿自己的交易目的,相对于 Account Model 具有一定的匿名性。

但是 UTXO 的缺点也是很致命的,就是Stateless,这使得在比特币上构建应用的开发成本极高且运行效率低下。以太坊白皮书提出比特币的 UTXO 模式的目的就是指出了比特币在脚本运行上的不足,并且突出自己解决了区块链上运行脚本的问题。

2 以太坊原理简述

2.1 以太坊好比电脑租用商

以太坊的目的是基于脚本、竞争币和链上元协议(on-chain meta-protocol)概念进行整合和提高,使得开发者能够创建任意的基于共识的、可扩展的、标准化的、特性完备的、易于开发的和协同的应用。

—以太坊白皮书

这句话翻译过来就是:以太坊集大家之所成,能够让开发者使用简易的开发语言在以太坊平台上开发应用。

这就好比,以太坊的区块链中运行着好多个等待租用的电脑,我们可以把写好的代码发布到电脑中运行。发布的过程就相当于租用以太坊上面的计算机,是需要消耗手续费,而手续费的多少取决于发布的代码执行时消耗的性能。我们租用计算机就要按需付费,而这些费用支持着“电脑”的运转,也正是矿工的挖矿所得。

例如这是我于2018年5月创建的 LORDLESS LESS Token 的 ERC20 智能合约,相当于我租用了以太坊上的一台电脑运行了我编写的 ERC20 合约代码;发布费用是 0.009080855 ETH, 合约代码点击查看

因此在以太坊的世界,开发者可以“租用电脑”来发布自己的智能合约代码,而这些发布后的代码就会“部署在电脑上”,等待被调用。而调用智能合约的方式也很简单,只要知道已发布的智能合约地址,并且知道合约里存在的方法就可以实现调用了。

下图就是用合约中 balanceOf 方法查询 0x35d415bF0E6bbf8e10ebA814e10325c46a2CF009 中的 LESS 代币余额;查询页面点击直达

2.2 以太坊账户

在以太坊系统中,状态是由被称为“账户”(每个账户由一个20字节的地址)的对象和在两个账户之间转移价值和信息的状态转换构成的。

—以太坊白皮书

这里我们来扩展一下,以太坊中的账户分成两种

  • EOA ( Externally Owned Account )账户
  • 合约账户

EOA 就是平时我们使用的钱包地址,合约账户我们发布的智能合约的地址。这两种地址在形式上是一样的,都是 0x 开头,长度 20个字节

1
2
3
4
5
# EOA 钱包地址
0x35d415bF0E6bbf8e10ebA814e10325c46a2CF009

# 智能合约地址
0x7ca121b093e2fbd4bb9a894bd5ff487d16f1f83b

它们不仅形式上一样,不同类型账户之间也可以相互发送交易。

EOA –> EOA, 也就是我们平时的的 ETH 转账

EOA –> Contract –> EOA, 最典型的场景就是 ERC20 转账。这里要注意,ERC20 本质上是 EOA 账户调用智能合约的 tranfertransferFrom方法。

Contract –> Contract 合约调用合约也是一个常见的用法。

例如我们在去中心化的交易所完成挂单,就是交易所的挂单合约调用

2.3 交易

以太坊中“交易”是指存储从外部账户发出的消息的签名数据包。交易包含消息的接收者、用于确认发送者的签名、以太币账户余额、要发送的数据和两个被称为STARTGAS和GASPRICE的数值。为了防止代码的指数型爆炸和无限循环,每笔交易需要对执行代码所引发的计算步骤-包括初始消息和所有执行中引发的消息-做出限制。STARTGAS就是限制,GASPRICE是每一计算步骤需要支付矿工的费用。如果执行交易的过程中,“用完了瓦斯”,所有的状态改变恢复原状态,但是已经支付的交易费用不可收回了。如果执行交易中止时还剩余瓦斯,那么这些瓦斯将退还给发送者。创建合约有单独的交易类型和相应的消息类型;合约的地址是基于账号随机数和交易数据的哈希计算出来的。

—以太坊白皮书

以太坊中“交易”是指存储从外部账户发出的消息的签名数据包。 这句话很重要,是理解以太坊交易的关键。

以太坊中所谓的交易,并不是我们平时理解的交换,以物换物、以钱换物等,而是存储外部账户发出的消息签名数据包。 以太坊的智能合约应用场景非常多,比如赌博、拍卖、空投等等。而以太坊的交易,就是把EOA–>EOA、 EOA–>Contract–>EOA 等等这些信息记录在区块链上。

例如,下图表示通过向 空投合约(Airdrop Contract) 发送 Transaction 来领取 LESS Token:

可以看到以太坊每一笔交易当中都包含了:

  • Block 被打包进的区块高度
  • Timestamp 区块时间
  • From Tx发起地址
  • To Tx目标地址
  • Value 交易包含以太坊的数量
  • Transaction Fee 消耗掉的矿工费
  • Gas Limit 最大消耗Gas数
  • Gas Used by Transaction 本次交易消耗的Gas数
  • Gas Price 消耗单个 Gas 的单价
  • Nonce 随着交易次数递增的数字,目的是防止双花攻击
  • input Date 交易携带的数据,用于调用智能合约中的方法,例子中就是调用了 Airdrop 合约的 calim 方法来领取空投的 LESS

领取 LESS 的合约调用数序图如下: 图中的整个调用过程

Account1–>Airdrop Countract –> LESS Contract–>Account1

整个过程就是一个 Transaction,被记录在一个 0xe3950daee51dd77059f3b1d2fab05fd871ad664e2d6ccbcfbff8e2840295cb48 这个 Transaction 中。

那么现在你是否可以理解,“以太坊中“交易”是指存储从外部账户发出的消息的签名数据包。” 这句话的意思了。

白皮书中还提到了为什么会有STARTGASGASPRICE,因为在以太坊上“租用电脑”需要付费,为了防止用户操作失误,例如出现无限循环等导致租用费用消耗过大。因此发送Transaction 过程中要设置两个参数:STARTGASGASPRICE

  • STARTGAS 表示本次交易最大可以消耗的 GAS 数
  • GASPRICE 表示你愿意付给矿工的 GAS 的单价

如果达到了STARTGAS上限,交易仍未执行完,那么链上所有的状态复位,但是依旧按照消耗的GAS产生矿工费用 STARTGAS * GASPRICE,也就是说白花钱了。但是如果还没达到STARTGAS就完成了交易,那么会把剩余未消耗的费用返还,这实际上对用户来说是一种保护措施。

2.4 以太坊状态机

以太坊的状态转换函数:APPLY(S,TX) -> S’,可以定义如下:

1.检查交易的格式是否正确(即有正确数值)、签名是否有效和随机数是否与发送者账户的随机数匹配。如否,返回错误。

2.计算交易费用:fee=STARTGAS * GASPRICE,并从签名中确定发送者的地址。从发送者的账户中减去交易费用和增加发送者的随机数。如果账户余额不足,返回错误。

3.设定初值GAS = STARTGAS,并根据交易中的字节数减去一定量的瓦斯值。

4.从发送者的账户转移价值到接收者账户。如果接收账户还不存在,创建此账户。如果接收账户是一个合约,运行合约的代码,直到代码运行结束或者瓦斯用完。

5.如果因为发送者账户没有足够的钱或者代码执行耗尽瓦斯导致价值转移失败,恢复原来的状态,但是还需要支付交易费用,交易费用加至矿工账户。

6.否则,将所有剩余的瓦斯归还给发送者,消耗掉的瓦斯作为交易费用发送给矿工。 例如,假设合约的代码如下

—以太坊白皮书

要理解这段话的内容,我们就要把区块链理解为一个分布式的状态机,所有节点按照相同的规则,相同的操作序列(增、删、改)不断变化,实现了所有节点在执行完相同编号区块内的 Transactions 之后,状态完全一致。

那么我们就清楚了,以上所列白皮书内容是以太坊更新状态机的控制流程。解读后如下图:

请认真读一遍这张图,理解了状态机的控制流程对我们后面学习以太坊的开发帮助很大。

3 以太坊的应用与未来

这一章白皮书上提到的应用领域过于宽泛,我想谈下个人想法;

3.1 最优秀的团队都选择了以太坊

按照以太坊(POW)目前的性能来讲,受到并发量和手续费所限,应用领域有限,但我依然推荐大家学习以太坊而不是 EOS、TRON 等所谓高性能公链。

原因是我认为以太坊是即能技术实力能打且有着无限创新基因的团队。 未来可期。

  • Github 的代码一直都在有条不紊的迭代中,社区的技术研发热情与币价无直接关系。
  • MetamaskInfuraTruffleWeb3.js 等开发的配套设施非常建全,开发者可以不必重新造轮子。
  • DDEXOpensea等二级市场的出现,无论是开发ERC20 Token 还是 ERC721 的 Non Fungible Token 都可以有依托的平台来面向更多用户
  • 以太坊社区经过 5 年的沉淀,技术上大部分的坑都已被填上,开发过程中 Google 一下就可以定位问题
  • EIPs( Ethereum Improvement Proposal ) 证明了以太坊的创新能力,EIPs 上诞生的 ERC20、ERC721、ERC1155 等最新理念崔生了出了众多优质的 dApp。而其它的公链也不得不抄袭以太坊的 EIPs 理念,搞出来类似 TRC20 的山寨货。

也正是因为以太坊社区以上的优秀特性,最优秀的团队都选择了以太坊, 所有曾经辉煌的 dApp 都是基于以太坊开发的。如 CryptokittiesFomo3d 等等。

当然从商业模式上来评价,cryptokitties 与 Fomo3d 都是击鼓传花的游戏,利用区块链的透明公开不可篡改的特点放大人性的贪图,这不值得鼓励。

但是从技术角度来说,它们都是代码质量级高的产品,尤其是 Fomo3D 团队的代码非常 Cool 值得借鉴,点击查看 Fomo3D代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
 * ┴  ┴└─└─┘─┴┘└─┘└─┘ ┴                                        (_/   .--,-``-.
 *========,---,.======================____==========================/   /     '.=======,---,====*
 *      ,'  .' |                    ,'  , `.                       / ../        ;    .'  .' `\
 *    ,---.'   |    ,---.        ,-+-,.' _ |    ,---.              \ ``\  .`-    ' ,---.'     \
 *    |   |   .'   '   ,'\    ,-+-. ;   , ||   '   ,'\      ,---,.  \___\/   \   : |   |  .`\  |
 *    :   :  :    /   /   |  ,--.'|'   |  ||  /   /   |   ,'  .' |       \   :   | :   : |  '  |
 *    :   |  |-, .   ; ,. : |   |  ,', |  |, .   ; ,. : ,---.'   |       /  /   /  |   ' '  ;  :
 *    |   :  ;/| '   | |: : |   | /  | |--'  '   | |: : |   |  .'        \  \   \  '   | ;  .  |
 *    |   |   .' '   | .; : |   : |  | ,     '   | .; : :   |.'      ___ /   :   | |   | :  |  '
 *    '   :  '   |   :    | |   : |  |/      |   :    | `---'       /   /\   /   : '   : | /  ;
 *    |   |  |    \   \  /  |   | |`-'        \   \  /             / ,,/  ',-    . |   | '` ,/
 *    |   :  \     `----'   |   ;/             `----'              \ ''\        ;  ;   :  .'
 *====|   | ,'=============='---'==========(long version)===========\   \     .'===|   ,.'======*
 *    `----'                                                         `--`-,,-'     '---'
 *             ╔═╗┌─┐┌─┐┬┌─┐┬┌─┐┬   ┌─────────────────────────┐ ╦ ╦┌─┐┌┐ ╔═╗┬┌┬┐┌─┐ 
 *             ║ ║├┤ ├┤ ││  │├─┤│   │   https://exitscam.me   │ ║║║├┤ ├┴┐╚═╗│ │ ├┤  
 *             ╚═╝└  └  ┴└─┘┴┴ ┴┴─┘ └─┬─────────────────────┬─┘ ╚╩╝└─┘└─┘╚═╝┴ ┴ └─┘ 
 *   ┌────────────────────────────────┘                     └──────────────────────────────┐
 *   │╔═╗┌─┐┬  ┬┌┬┐┬┌┬┐┬ ┬   ╔╦╗┌─┐┌─┐┬┌─┐┌┐┌   ╦┌┐┌┌┬┐┌─┐┬─┐┌─┐┌─┐┌─┐┌─┐   ╔═╗┌┬┐┌─┐┌─┐┬┌─│
 *   │╚═╗│ ││  │ │││ │ └┬┘ ═  ║║├┤ └─┐││ ┬│││ ═ ║│││ │ ├┤ ├┬┘├┤ ├─┤│  ├┤  ═ ╚═╗ │ ├─┤│  ├┴┐│
 *   │╚═╝└─┘┴─┘┴─┴┘┴ ┴  ┴    ═╩╝└─┘└─┘┴└─┘┘└┘   ╩┘└┘ ┴ └─┘┴└─└  ┴ ┴└─┘└─┘   ╚═╝ ┴ ┴ ┴└─┘┴ ┴│
 *   │    ┌──────────┐           ┌───────┐            ┌─────────┐              ┌────────┐  │
 *   └────┤ Inventor ├───────────┤ Justo ├────────────┤ Sumpunk ├──────────────┤ Mantso ├──┘
 *        └──────────┘           └───────┘            └─────────┘              └────────┘
 */

3.2 以太坊是局部的局部

李笑来在书《定投改变命运》里写到:

正确的方法永远是“局部的局部”

— 李笑来

我同意他的观点,但是不同的是

  • 李笑来认为局部的局部是 EOS;
  • 我认为局部的局部是 Ethereum

我们都认同区块链是未来,是发站最快的行业,是第一个局部; 我们的分歧点在第二个局部,是 EOS 还是 Ethereum?

我们产生分歧的原因其实是目标不同

  • 李笑来老师说的局部的局部是 EOS,其目标是更高的投资收益。
  • 而我认为局部的局部是 Ethereum ,其目标是技术学习,正确把握科技发展趋势。

EOS 是个注重商业模式的团队,投资我不如李笑来老师,我相信他的判断;但是对于技术本身,我相信做过区块链开发、无数个深夜踩过无数坑、完成过大量智能合约的人则会拥有独特的技术洞察力。我判断未来的区块链的局部一定是以太坊;

以太坊1.0 的成功让我们对以太坊2.0 充满了期待:

我们来看下以太坊2.0 的技术指标 :eth2.0-specs

以太坊2.0 将引入很多全新的技术,如分片技术、零知识证明技术、抗量子攻击技术等等。这些问题的可行性已被证明,剩下的问题只是工程化的落地实现了。

以太坊2.0的上线将直接影响区块链未来5-10年的发展趋势,希望我们都不将错过这次技术革命;