精通以太坊 – 笔记

精通以太坊:开发智能合约和去中心化应用安德烈亚斯·M.安东波罗斯88个笔记

◆ 推荐序一
>> 区块链技术不是一门具体的技术,也不是几种技术简单地拼凑在一起形成的解决方案,而是一个体系非常庞大的技术群落,技术之间相互影响、相互促进。

◆ 推荐序二
>> DApp的核心是智能合约,而智能合约运行在一个叫作EVM的虚拟机上。

◆ 术语速查
>> 以太坊区块链与比特币的不同之处在于,前者没有区块大小限制,而使用gas上限来调整区块大小。
>> 创建合约交易(Contract creation transaction)一种为了注册一个合约并将其记录在以太坊区块链上的特殊交易,其中接收者地址“为零”。
>> 去中心化自治组织是一类没有分层管理体系的公司或其他组织。“The DAO”同时也可以指代一份2016年4月30日发布的合约,其随后在2016年6月遭到攻击,并最终引起了在区块高度1192000发生的硬分叉。该分叉回退了被攻击的DAO合约,也导致以太坊与以太坊经典分裂成两个竞争系统。
>> 权益证明(PoS)权益证明是加密货币区块链协议试图达成分布式共识的一类方法。权益证明要求用户先证明自己对一定量加密资产的所有权(即他们在网络中的“权益”),才可参与到验证交易的过程中。

◆ 第1章 什么是以太坊?
>> 从计算机科学的角度来看,以太坊是一个具备确定性但实际上却没有边际的状态机。它有两个特点:具有一个全球范围可访问的单体状态;还有一个执行状态更改的虚拟机。
>> 以太坊跟其他公共区块链有很多共同点:一个连接参与各方的点对点网络、一个用于同步状态的拜占庭容错共识算法(工作量证明)、使用数字签名和哈希等密码学原理、一种数字货币(以太币)。
>> 以太坊的主要目的不是成为数字货币的支付网络。虽然以太币本身对于以太坊的构成和运营是不可或缺的,但以太币的主要目的是作为一种效用货币来支付使用以太坊这个“世界计算机”所产生的花费。
>> Web 3把以太坊视为去中心化技术的一部分,去中心化技术的另外两个重要组成部分是Whisper和Swarm。
>> 使用类似以太坊这样的通用目的区块链技术,开发者不必构建点对点网络、区块链、共识算法等基础设施,就可以开发自己的应用。以太坊平台的目的是把这些细节抽象化,提供一个确定性的、安全的编程环境,用于去中心化的区块链应用程序。
>> 以太坊也是一个分布式状态机。但是不同于跟踪数字货币所有权的状态,以太坊跟踪的是一个通用目的的数据存储的状态转变。通用目的的意思是任何可以表示为键值元组的数据。
>> 以太坊的突破性创新在于,它把存储程序计算机这样的通用目的计算架构与去中心化区块链相结合,因此创建了一个分布式的单体状态世界计算机。无论以太坊的程序运行在任何地方,都能够产生一致的共识状态,通过共识规则确保安全。
>> 简单来说,在真正运行程序之前,人们无法预测程序的执行路径。图灵完备的系统可以在无限循环中运行,这是对一个不终止程序的极简描述方式。
>> 根据图灵的理论,在真正运行合约之前,以太坊实际上无法预先判断一个合约是否会运行终止,或者它需要运行多久,也许这个合约会陷入死循环一直运行。无论是程序中的瑕疵,还是故意为之,智能合约都可能在一个节点试图验证它的时候永远不停地执行下去,这也就造成了一种DDoS攻击的后果。相比于可能几个毫秒就能够验证和执行完的正常智能合约,这类永远运行的恶意合约会造成资源浪费、内存消耗、CPU过载等,这就是浪费节点的资源。对于一台世界计算机而言,一个滥用资源的程序可能会蔓延到所有的节点之上,也就是对“全球”资源的浪费。如果无法提前预估,那么以太坊如何防止智能合约过度使用资源呢?为了应对这个挑战,以太坊引入了名为gas的计量机制。EVM在执行智能合约时,它会仔细地计算每一个执行指令(计算量、数据访问,等等)。每一个指令都有一个预先定义好的开销,以gas为单位。当以太坊交易触发了智能合约的执行时,交易中必须包含这个智能合约执行过程中所需要的计算资源开销的上限。如果执行过程中的资源开销量超过了交易中指定的gas上限,那么EVM就会主动终止这个合约的执行。以太坊通过gas机制,在保证图灵完备计算的同时,限制了程序可以使用的资源量。接下来的问题是,如何在以太坊世界计算机上获得gas以支付计算开销?你不会在任何交易所找到gas。它只能作为交易的一部分购买,并且只能通过以太币购买。以太币需要与交易一起发送,并且需要明确标记gas,以及可接受的gas价格。就像在加油站一样,gas的价格也不固定。为交易而购买gas,然后执行计算,并将任何未使用的gas退还给交易发送方。
>> DApp至少包含:· 位于区块链之上的智能合约· Web前端用户界面除此之外,很多DApp还包括其他的去中心化组件,比如:· 去中心化(P2P形式)的存储协议和平台· 去中心化(P2P形式)的消息协议和平台
>> web3这个词首先由Gavin Wood博士提出,它代表Web应用新的愿景和关注点:从集中化和统一管理的应用,到构建于去中心化协议之上的应用。
>> 以太坊开发文化的特点是快速创新、快速变革,敢于进行前瞻性实验,即使牺牲后向兼容性也在所不惜。

◆ 第2章 以太坊基本概念
>> 设计以太币是用来支付智能合约的,智能合约是运行在以太坊虚拟机(EVM)之上的计算机程序。
>> 外部账户是拥有私钥的账户,拥有私钥意味着控制对以太币或合约的访问。现在,你可能猜测还有其他类型的账户。另一种账户是合约账户。合约账户具有智能合约代码,而外部账户不具有。此外,合约账户没有私钥。相反,它由其智能合约代码的逻辑所拥有(并受其控制)。智能合约代码是在合约账户创建时由以太坊区块链记录的软件程序,由EVM执行。
>> ,使用交易和交易的数据作为其输入。除了以太币之外,交易还可以包含指示合约中要运行的特定函数以及要传递给该函数参数的数据。通过这种方式,交易可以调用合约中的函数。
>> 由于合约账户没有私钥,因此无法启动交易。只有外部账户才能启动交易,但合约可以通过调用其他合约,构建复杂的执行路径来对交易做出反应。
>> 可编程区块链的威力在于可以用去中心化的软件来控制资产!
>> 把合约注册到区块链上需要通过一个特殊的交易,这个交易的目标地址是0x0000000000000000000000000000000000000000,也被称为零地址。
>> 以太坊合约是用来控制以太币的程序,它运行在名为EVM的虚拟机之内。合约由特殊的交易创建,这个过程就是把合约的字节码保存到区块链上。在区块链上完成创建以后,合约会有一个以太坊地址,就如同钱包一样。任何时候,如果有人向这个合约地址发送交易,都会触发合约在EVM中被执行。这个交易本身,就是程序执行的输入参数。发送给合约的交易可以包括以太币或者数据,也可以同时包括这两者。如果交易包含以太币,就等于把以太币存入了合约的账户。如果交易包含数据,这个数据用来指定合约的具体函数并通过传递参数来调用它。

◆ 第3章 以太坊客户端
>> 实际上,拥有多个独立开发的客户端,已被证明是防御网络攻击的绝佳方法,因为特定客户端实现策略的漏洞只会影响到那些要修补漏洞的开发者,别的客户端可以保证整个网络几乎不受影响地继续运行。

◆ 第4章 以太坊背后的密码学
>> 密码学可以用来进行知识证明,这是指在不公开秘密数据的情况下,证明知道秘密的信息(数字签名);也可以用作证明信息的真实性(数字指纹,也称哈希)。
>> 外部账户对以太币的所有权是通过私钥、以太坊地址和数字签名建立起来的。私钥乃是用户与以太坊交互的核心。实际上,账户地址直接由私钥推导而来:一个私钥会与唯一一个以太坊地址(也称为账户)挂钩。
>> 只有账户地址和数字签名可以在链上传输或存储。
>> 在椭圆曲线运算中,质数的模乘运算是非常简单的,但是模除运算(反向运算)却是几乎不可能的,这被称为离散对数难题,至今我们还没有发现陷门。椭圆曲线密码学在现代计算机系统中被广泛应用,也是以太坊(和其他加密货币)的密钥对和数字签名的基础。
>> 密码学(这里具体指椭圆曲线密码学)中的数学规则使消息(即交易细节)可以与私钥结合在一起,创建出只能用私钥生成的代码。这些代码就是所谓的数字签名
>> 每个以太坊公钥都是椭圆曲线上的一个点,也就是说,每个公钥都是一组x、y坐标,这个坐标正好满足椭圆曲线方程。

◆ 第5章 钱包
>> 一个针对以太坊钱包的常见误解是认为钱包中包含以太币或者代币。实际上,钱包中只保存了密钥。以太币和其他各种代币都保存在以太坊区块链上。
>> 这种差别真正重要的地方是改变一个人将钱包当作传统银行的中心化系统的心态(认为只有你及银行可以看到你账户中的钱,要转账时,只需告诉银行你确实有此愿望),转变为将其当成区块链平台的去中心化系统:系统中的每个人都可以看到账户余额,虽然他们可能不知道账户的主人是谁,而主人要转账时需要说服每一个人

◆ 第6章 交易
>> 交易是唯一能够触发区块链状态改变,或触发EVM上的合约执行的东西。以太坊是一个全局的单体状态机,交易是唯一能够让这台状态机向前推进并改变状态的东西。合约并不会自动运行。以太坊也不会在“后台”运行。所有这一切,都是由交易触发的。
>> nonce:一个数值,等于这个地址发出的交易数量,当这个地址与合约关联时,是这个地址所创建的合约数量。
>> 相反,如果包含了随机数,那么你发送的第一笔交易将具有一个随机数,假设是3,而8 ether的交易将具有下一个随机数(如4)。因此,这笔交易将被忽略,直到nonce值为0到3的交易已经被处理,即便它是先接收到的。
>> 但是,如果交易数据中包含nonce值,那么每一笔交易都是唯一的,即便是多次向同一个收件人地址发送相同数量的以太币交易也是如此。因此,通过将递增的随机数作为交易的一部分,任何人都没有办法“复制”你已经完成的付款。
>> 如果你按顺序创建了一系列交易,但其中一个没有得到确认,那么之后的所有交易都会“堵”住,等待这个缺失的交易。
>> 交易数据包的核心是这两个字段:value和data。交易可以同时包括value和data,只有value、只有data或既没有value也没有data这几种情况都是正确且合法的。
>> 只包含value的交易是支付操作。只包含data的交易是针对合约的调用。既没有value也没有data的交易也许只是为了浪费gas,但也是允许的。
>> 在短短几秒钟的时间内,一个以太坊交易就能到达全球范围内所有的以太坊节点。从单个节点的角度而言,它无从知晓这个消息的来源。向这个节点发送交易的邻居,可能只是扮演了“二传手”的角色,但也可能是交易的真正发起方。为了追踪到交易的最初发起方,或者影响交易在以太坊中传播的形式,攻击者必须要控制网络中的大部分节点。这是P2P网络安全和隐私性的设计,对于区块链而言尤其重要。
>> 要想在多重条件下保护你的以太币,请将以太币转移到多重签名合约。每当你想将资金发送到另外一个账户时,所有必要的用户都需要通过常规的钱包应用向合约发送交易,从而有效授权合约执行最终的交易。

◆ 第7章 智能合约与Solidity
>> 以太坊的智能合约既不智能,也没有法律上的合约效力,但是这个术语已经广为流传。在本书中,我们使用智能合约来指代那些不可改变的计算机程序,以确定性方式运行在以太坊的虚拟机上,也就是我们常说的以太坊去中心化世界计算机。
>> 不同于外部账户,对于新建的智能合约实例,并没有一个与之关联的私钥。作为合约的创建者,你并不会在协议层获得相对其他用户而言的任何特权(尽管你可以把自己的特权写入合约内部)。你肯定不会收到一个合约账户的私钥,因为它并不存在,我们可以认为,智能合约是它自己的主人。
>> 智能合约永远不会“自动运行”,或者“在后台运行”。在没有交易触发(不论是直接触发,还是通过智能合约调用链)执行的情况下,合约永远处在等待调用的状态。
>> 任何情况下智能合约的“并发执行”都是没有意义的:以太坊世界计算机可以被认为是一台单线程的计算机。
>> 如果程序执行因为错误而终止,它之前进行的所有操作(如改变的状态)都会被回滚,就像这个执行从来没有发生过一样。失败的交易仍旧会被作为一次失败的尝试而记录在案,执行所花费的gas将从发起账户中被扣除,除此之外,它不会对合约或者账户状态产生任何其他影响。
>> 合约实例的代码是不能被更改的。然而,合约实例可以被删除,从它的地址把代码和合约实例的内部状态(存储)清空,让这个地址变成一个空账户。
>> 要删除合约实例,需要执行名为SELFDESTRUCT(之前称为SUICIDE)的EVM字节码。这个操作会产生负的gas消耗,也就是系统会提供gas退款,这也会激励人们通过删除存储状态的方式释放资源。删除合约并不会清除这个合约之前交易的历史记录,因为区块链本身是不可变的。另外,需要注意,只有合约的开发者在代码中编写了对应的删除功能,SELFDESTRUCT字节码才会起作用。如果合约的代码不包含SELFDESTRUCT字节码,或者合约实例是不可执行的,那么这个合约实例就无法删除。
>> API定义了高级的、供程序员阅读和使用的源代码接口。ABI是向机器指令层面编码和解码并传送数据的主要方式。
>> 请注意,内部和私有这两个词会引起歧义。任何在合约内的数据或者函数都是在公共区块链上可见的,这也意味着任何人都能够看到代码或者数据。上述这两个关键字只是会影响函数是否可以被调用。
>> 程序员必须手动在合约中包含这个指令,这样合约才可以被销毁,这也是销毁合约的唯一途径。合约默认不提供这样的能力。如果用户希望合约永久存在,那么只要合约代码中没有加入SELFDESTRUCT字节码,这个合约就无法从以太坊中销毁。
>> 在修饰符中有一个特殊的下划线和分号组成的占位符号“;”。这个占位符会被修饰符所作用到的代码替代。简单地说,这个修饰符会包裹在被修饰函数之外,把被修饰函数的代码放在这个下划线占位符的位置。
>> 当合约遇到错误而中断执行时,所有的状态更改(变量、余额等)都会回滚,如果是一串合约的连续调用,则会一直恢复到最初触发这一串调用的那个合约时的状态。这确保了交易的原子化,意味着一个交易需要作为整体而成功,如果失败,不会发生任何状态改变,整体撤销。
>> revert和throw函数用于立即中止合约的执行,并且把状态回滚。throw函数已经淘汰,并将在未来版本的Solidity中被移除,我们应该使用revert函数。revert函数也可以接收一个作为出错信息的参数,这个信息会被记录在交易的日志中。

◆ 第8章 智能合约与Vyper
>> 在分析的过程中,研究人员总结了三种基本类型的漏洞:可自毁合约那些可以被任何地址杀死的合约。贪婪合约那些一旦达到某个执行状态,就无法释放以太币的合约。慷慨合约那些可以把以太币转给任意地址的合约。

◆ 第9章 智能合约安全
>> 区块变量不应该用来作为无序性的来源,因为它们可以被矿工们操纵。
>> 所有外部应用在把输入参数发送到区块链之前都应该对它们进行校验。而参数的顺序同样扮演了重要角色。由于数据填充仅会发生在尾部,所以在合约中仔细考虑参数的顺序也可以在一定程度上减轻这种攻击的危害。
>> 尽可能使用transfer函数而不是send,因为transfer会在外部调用失败时revert。如果真的需要用send,就务必要检查其返回值。

◆ 第10章 代币
>> 代币可以提供多种功能,很多情况下这些功能互相重叠。例如,一个代币既可以代表一个投票的权利,同时又可以代表针对特定资源的访问权和所有权。数字货币只是代币的第一个应用场景而已。
>> 代币的可替代性是指当我们把一个代币的基本单元互相交换时,并不影响它的价值或功能。
>> 不可替代性代币是指那些代表了独特的有形或无形资产的代币,因此这些代币之间不可以互相替代。
>> 代表着区块链内在资产的代币不会有额外的对手方风险。如果你持有一个以太币,没有额外的第三方可以控制或影响你的所有权。区块链的共识规则会起作用,你对私钥的控制就相当于是对对应资产的完全所有权,没有任何的中间层。相反地,很多代币用来表示区块链之外的资产,例如房地产、公司的投票权、商标、金条等。这些资产的所有权,并不在区块链之上,是由现实世界中的法律、法规这些与区块链世界中的共识规则完全不同的方式管理。因此,这些区块链之外的资产带有额外的对手方风险,因为它们被一些人持有,记录在额外的登记系统内,或由区块链之外的法律和法规进行控制。
>> 基于区块链代币的一个非常重要的未来,就是用区块链内的资产替代区块链外的资产,因此可以消除对手方风险。
>> 工具型代币是指用来支付某个服务、应用或资源的代币。工具型代币的例子包括代表了资源的共享存储、访问例如社交媒体网络等服务,或者类似以太坊网络中使用以太币支付的gas。相比而言,权益型代币是指代表了一个初创公司股权的代币。权益型代币可以被设定为没有投票权的,用来分红和分配利润的代币,也可以承载一个去中心化自治组织的投票权,这类组织的管理由持有代币的所有人共同投票决定。
>> 对于一个初创公司,每次创新都增加了失败的风险。如果你在已经有风险的创业主意的基础上再增加一个工具型代币,你就相当于把整个平台(以太坊)、相关生态(交易所)、监管环境(权益、商品监管)和技术(智能合约、代币标准)的风险都加到了你的创业项目之上。这对于一个初创公司来说是难以承担的。
>> 代币的第一个标准由Fabian Vogelsteller在2015年11月提出,作为一个以太坊的需求提议(ERC)。这个提议在GitHub上被自动分配了20的编号,因此这个标准对应的代币在之后都被称为ERC20代币。现在大多数的代币都是基于ERC20标准,这个需求提议最终成为以太坊的标准EIP-20,但是大多数人仍旧喜欢采用ERC20这个叫法。
>> ERC20支持两种转账。第一种是单一式转账,直接使用transfer函数。这个流程被钱包软件用来发送代币给其他地址。大多数的代币转账都是通过transfer函数完成的。
>> 第二种方式是使用了approve和transferFrom的两步式交易。这个流程允许代币的持有人授权其他地址操纵他们的代币。这通常用于授权给某一个合约地址,进行代币的分发,但也可以用于交易所的场景。
>> 实际上,很多以太坊用户不慎把各种代币转入并不具备ERC20代币操作能力的合约,他们都没有考虑到这个问题。根据一些估算,价值超过250万美元的各种代币就这样永远地“卡”在了区块链上。
>> 以太币是使用带有目标接受人地址的交易进行转账的,而代币的转账是通过代币合约内相关的状态转换进行的,使用合约作为地址,而不是接收方的地址。代币合约跟踪余额并发出事件。在代币的转账过程中,并没有任何针对接收方地址的交易。接收方的地址被加入代币合约的余额映射表中。一个发送以太币的合约会改变目标地址的状态。一个发送代币的合约只会改变合约内部的状态,而不是接收方地址的状态
>> 为了发送代币,你也需要以太币。你不能使用代币来支付一笔交易所需要的gas,代币合约也不会替你支付这笔gas。这会造成一些奇怪的用户体验。比如,你使用交易所或者Shapeshift把一笔以太币转换为代币。你可以把这些代币“接收”到一个关注了这个代币合约的钱包软件中。这跟你钱包中的其他数字货币看上去没什么区别。如果这时你想转账代币,你的钱包软件会提醒你转账需要支付以太币。你会非常疑惑:因为你在接收代币的时候并不需要以太币。
>> ERC20代币标准只是跟踪每一个账户的最终余额,并不跟踪每一个单位的代币是从何而来的。

◆ 第11章 预言机
>> 在理想情况下,预言机是无信任的系统,这意味着它们不需要被信任,因为它们是按照去中心化的原则运行的。
>> 为了保持共识,EVM的执行过程必须完全确定,并且仅基于以太坊状态和签名交易的共享上下文。这产生了两个特别重要的后果:一个是EVM和智能合约没有内在的随机性来源;另一个是外部数据只能作为交易的数据载荷引入。
>> 假想一个猜硬币决胜负的游戏场景,这个游戏依赖于扔硬币正反面的随意性。矿工可以轻易破解这个游戏:他们只需要打包那些对其有利的随机结果即可。
>> 可以将预言机视为弥合链外世界与智能合约之间差距的机制。允许智能合约基于真实世界的事件和数据来强制执行合约关系,从而大大扩展了它们的范围。
>> 根据定义,所有的预言机都提供了一些关键功能。这些能力包括:· 从链外的数据源收集数据。· 使用签名消息在链上传输数据。· 将数据放入智能合约的存储空间,使数据可用。
>> 预言机为智能合约提供了至关重要的服务:它们将外部事实带入合约执行。当然,预言机也会带来很大的风险:如果它们是受信任的来源并且可能受到损害,可能导致它们提供的智能合约的执行受损。

◆ 第12章 去中心化应用
>> 其中一个最主要的区别是任何在智能合约中执行的计算都特别昂贵,所以应该保持智能合约尽量小。因此,确定一个应用的哪些组件需要可信且去中心化的执行平台显得尤为重要。
>> 由于昂贵的gas费用以及当前较低的区块gas上限,智能合约不太适合存储和处理大量数据。因此,大多数DApp利用链下数据存储服务,这意味着它们将大量数据存储在(链下)数据存储平台上,而非以太坊链上。数据存储平台可以是中心化的(例如典型的云端数据库),也可以是诸如IPFS和以太坊自有平台Swarm等点对点形式的。
>> 治理问题是一个特别难解决的问题,通常它代表了一把双刃剑。一方面,拥有特权账户是危险的,因为一旦特权账户被破坏,DApp的安全性就随之被破坏。另一方面,如果没有特权账户,一旦合约出现问题,就没有恢复的余地。
>> 在构建一个DApp时,你必须决定是让其完全独立,一旦部署之后就无法被控制,还是创建一个特权账户,承受受到攻击的风险。任何一种选择都会带来风险,但是长远来看,真正的DApp不应该存在能进行特权访问的特权账户,因为这不是去中心化。

◆ 第13章 以太坊虚拟机
>> EVM是一个“准”图灵完备的状态机,因为在其中进行的任意智能合约的执行都必须限定在一个由可用的gas总量所限制的、有限的计算步骤数量之内。这样,停机故障(指所有程序执行都被迫停止)就被“解决了”,并且避免了程序可能会(意外地或者恶意地)永远执行下去,从而使以太坊平台进入完全停止的状态的问题。EVM有一个基于栈的架构,在一个栈中保存了所有内存数值。EVM的数据处理单位被定义为256位的“字”(这主要是为了方便处理哈希运算和椭圆曲线运算操作),并且它还具有以下数据组件:· 一个不可变的程序代码存储区ROM,加载了要执行的智能合约字节码。· 一个内容可变的内存,它被严格地初始化为全0数值。· 一个永久的存储,它是作为以太坊状态的一部分存在的,也会被初始化为全0。
>> EVM中有两个操作带有负的gas消耗:· 删除一个合约(SELFDESTRUCT)会返还24000 gas。· 将一个非零值的存储地址设置为0(SSTORE[x]=0)会返还15000 gas。为了避免通过返还机制牟利,交易的最大gas返还数量被设定为交易中总共消耗的gas数量的一半(向下舍入)

◆ 第14章 共识
>> 挖矿(以及其他所有共识模型)的真实目的都是保护区块链的安全,同时保证对系统的控制权是去中心化的(在参与者之间尽可能广泛地分布)。
>> 实际上,以太坊的PoW算法被精心地置入了一个叫作“难度炸弹”的机制,目的就是逐渐让以太坊的PoW挖矿变得越来越难,迫使网络转向PoS。

发表评论