区块链快速参考(二)

原文:zh.annas-archive.org/md5/b5e57485b0609afbfba46ff759c5d264

译者:飞龙

协议:CC BY-NC-SA 4.0

第九章:加密货币钱包

在本章中,我们将详细讨论加密货币钱包。在之前的章节中,我们已经介绍了钱包以及加密货币钱包的类型;在本章中,我们将进一步详细讨论钱包、它们的来源以及如何加强钱包的安全性。

钱包用于存储私钥、公钥以及比特币地址。可以使用钱包发送或接收货币。钱包可以将数据存储在数据库中或结构化文件中。例如,比特币核心客户端钱包使用 Berkeley DB 文件。

本章我们将涵盖的主题如下:

  • 加密货币钱包的重要性

  • 软件钱包

  • 硬件钱包

  • 纸质钱包

  • 脑钱包

  • 加密货币钱包中的密钥派生方法

  • 记忆代码

加密货币钱包简介

任何加密货币的钱包都可以存储多个公钥和私钥。加密货币本身并不包含在钱包中;相反,加密货币是去中心化存储和维护在公共分类帐中的。每个加密货币都有一个私钥,用它可以在公共分类帐中写入,这使得在加密货币中进行消费成为可能。

了解钱包的重要性很重要,因为保护私钥安全对于保护货币安全至关重要。钱包是公钥和私钥的集合,每个都对于货币持有者的安全性和匿名性都很重要。

加密货币钱包中的交易

钱包之间的交易不是价值转移;相反,钱包中存储着私钥,该私钥用于签署交易。交易的签名是从私钥和公钥的组合中生成的。安全存储私钥是非常重要的。

钱包可以存储多个私钥,并生成与私钥相关联的多个公钥。

因此,保持钱包安全以保护私钥的安全非常重要;如果私钥丢失,与该私钥相关的硬币将永远丢失,没有可行的方法来恢复这些硬币。

加密货币钱包的类型

根据其特征,钱包可以分为各种类型。钱包可以根据支持的货币数量、可用性、软件或硬件、密钥派生方法等进行分类。我们将在下面的子章节中查看要涵盖的加密货币钱包类型。

货币支持

区分钱包的一个主要特征是钱包支持的货币数量;例如,可以有支持单一货币或多货币的钱包。每种货币都有一个包含钱包的核心客户端。

官方钱包通常只支持单一货币,但现在,许多第三方钱包开始支持多种货币,这些钱包执行与常规钱包相同的功能,唯一的区别在于它们支持的货币种类。

一些支持多种货币的钱包如下所示:

  • 无限钱包

  • Jaxx 钱包

  • Electrum

  • Trezor

  • Coinbase 钱包

以下是支持各种货币的 EXODUS 钱包的截图:

有时,会有各种其他的钱包涌现,提供多种货币。有时,支持单一货币的现有钱包开始引入多种货币,以增加其受欢迎程度,甚至以支持另一种加密货币。

租约

钱包还可以根据它们是基于软件、硬件、纸质还是云的来区分。让我们详细讨论这些钱包。

软件钱包

这些钱包是基于本地计算机或手机的。这些可以进一步分为桌面或移动钱包。这些钱包受限于本地机器;它们通常会按顺序下载完整的区块链或记录公共分类帐的信息:

  • 桌面软件:它们在桌面或笔记本电脑上本地存储密钥。这为加密货币提供了完全的控制权,尽管安全责任由托管钱包的人员承担,因此,即使机器的硬盘发生故障且没有备份,也有永久丢失货币的风险。没有必要在每时每刻都更新区块链,因此,在这种情况下,也可以使用未连接到计算机的机器。

  • 移动钱包:这些钱包通过手机上的应用程序运行。这使用户可以轻松访问他们的货币。这些钱包将货币或密钥存储在手机上,就像桌面软件钱包一样,或者它们只是一个云钱包的界面;我们稍后将讨论该类型的钱包。以下截图是移动钱包的示例:

大多数加密货币的核心客户端最初提供软件钱包,并初步支持桌面钱包。

硬件钱包

私钥应存储在可能的最安全位置。硬件钱包将私钥存储在专为存储私钥设计的自定义硬件中。无法以纯文本形式导出私钥,这增加了另一层安全性。只有在需要时,硬件才连接到计算机,而在其他所有时候,私钥都保持安全。硬件钱包于 2012 年由 Trezor 首次推出。

目前可用的一些流行的硬件钱包包括 Trezor、Ledger 和 KeepKey 钱包。以下快照显示了一个连接到计算机的硬件钱包的示例:

纸钱包

纸钱包,顾名思义,只是公钥和私钥一起打印出来。密钥通常以二维码形式打印,也作为地址。任何人都可以通过打印密钥来创建纸钱包,但也要确保他们将密钥从计算机中删除,否则任何人都可以访问密钥。纸钱包应只存储在纸上,没有其他地方的备份。有各种在线服务可生成纸钱包,例如 www.walletgenerator.net。以下屏幕截图是纸钱包的示例,以下图片可打印,以接收支付,公钥地址是共享的,但标记为秘密的私钥必须保密:

大脑钱包

大脑钱包是一个简单的钱包,通过对口令进行哈希运算生成地址以生成私钥和公钥。要生成大脑钱包,我们选择一个简单的口令来生成公钥和私钥对。以下屏幕截图显示了如何生成公共地址和私钥。输入要记住的口令,如下图所示:

使用频率

钱包还可以根据使用情况区分;在这个基础上,主要有两种类型的钱包:冷钱包和热钱包。简单来说,冷钱包不连接到互联网,而热钱包则始终连接到互联网,可以随时用于发送相应的加密货币。即使未连接到互联网,冷钱包也可以用于接收货币,但在将其连接到互联网之前,不可能将货币发送到其他地址。

硬件钱包不连接到互联网,除非连接到设备;它们可以被视为冷钱包。

密钥派生

私钥由钱包生成以存在于区块链上,主要有两种方法可以生成密钥。密钥生成方法对于钱包的安全性至关重要,也对于在丢失钱包时恢复钱包至关重要。

非确定性钱包

这些是比特币客户端的最初迭代版本;钱包具有随机生成的私钥。这种类型的钱包因一个主要缺点而被停用,即如果丢失钱包,则无法访问随机密钥。由于建议在网络上维护匿名性时每次交易使用不同的地址,而随机密钥过多,因此难以维护,因此地址容易被重复使用。尽管在比特币核心客户端中,有一个实现为类型-0 钱包的钱包,但其使用受到普遍不鼓励。

确定性钱包

在这些钱包中,密钥是从单个主密钥或一个可以说是共同种子派生的。在这种类型的钱包中,所有私钥都链接到一个共同的种子。只备份种子即可恢复在这种类型的钱包中派生的所有密钥。

分层确定性钱包

这是确定性钱包的最高级形式。这些是在比特币改进提案系统的 BIP0032 中引入的。这些钱包遵循树结构,也就是说,种子创建主密钥,进一步创建子密钥,每个密钥都可以派生更多的孙子密钥。因此,在这些类型的钱包中,可以有多个分支的密钥,并且分支中的每个密钥都能够按需创建更多的密钥。以下图表显示了在这种钱包中创建的密钥和地址层次结构:

图片

助记码

这些是用于表示确定性钱包中用于派生种子的随机数的英文单词。这些单词充当密码;这些单词可以帮助恢复种子,以及随后从种子派生的密钥。助记码对钱包用户来说是一个很好的备份系统。

创建钱包时,钱包显示一个包含 12 至 24 个单词的列表。这些单词序列用于备份钱包,并在钱包无法访问时恢复所有密钥。

这是根据 BIP0039 标准生成助记码和种子的过程:

  1. 初始随机熵ENT比特在允许的 128-256 比特大小之间生成。

  2. 校验和是通过取其 SHA256 哈希的前几位生成的。校验和长度由ENT/32公式定义。

  3. CS标识的校验和添加在初始熵的末尾。

  4. 创建的序列分割成 11 位;每个都被编码为一个在 0 和 2,047 之间的数字,该数字充当预定义单词列表中的索引。

  5. 创建代表助记码的 12-24 个单词列表。

助记码长度,也称为助记句(MS),由MS = (ENT + CS) / 11定义。以下屏幕截图显示了单词长度和与其相关联的熵:

图片

从助记序列生成的 512 比特种子使用PBKDF2函数,其中助记句用作密码,字符串助记句+密码用作盐。密码是用户用来保护自己助记句的内容;如果未设置,则使用""

从这个过程派生的密钥长度是 512 位;不同的钱包可以使用自己的过程来创建单词列表,并且拥有任何所需的单词列表。尽管建议使用 BIP 中指定的助记词生成过程,但钱包可以根据需要使用自己版本的单词列表。

HD 钱包的密钥生成过程

我们将详细讨论密钥生成过程,从主密钥到私钥,以及钱包为交易目的创建的各种地址。

初始过程是创建根种子,它是一个 128、256 或 512 位的随机数。根种子由助记句表示,这使得在丢失钱包访问权的情况下更容易恢复完整的钱包。

根种子是使用助记句和根种子生成的,根种子的长度选择在 128 到 512 位之间,尽管建议使用 256 位。使用(P)RNG 生成。生成的哈希值用于创建主私钥和主节点。主密钥的生成是层级系统中的深度级别 0;随后的钱包或密钥由深度 1、2 等表示。

子密钥派生

HD 钱包广泛使用子密钥派生CKD)函数从父密钥创建子密钥。使用以下元素使用单向哈希函数派生密钥:

  • 父密钥

  • 作为种子的链码,256 位

  • 索引号,32 位

子密钥可以从已经存在的密钥中生成的方式有多种;以下是关键派生序列:

  • 从私有父密钥生成私有子密钥

  • 从公共父密钥生成公共子密钥

  • 从私有父密钥生成公共子密钥

让我们详细讨论前面提到的每个序列。

私钥生成

父密钥、链码和索引号被组合并使用HMAC-SHA512算法进行哈希运算,生成一个 512 位的哈希值,使用以下公式:

I = HMAC-SHA512(Key = Cpar ,Data = serp (point(kpar )) || ser32 (i))

生成的哈希值被分成两个哈希值,I[L] 和 I[R]。哈希输出的右半部分成为子节点的链码,哈希的左半部分及其索引号用于生成子私钥以及推导子公钥。

通过更改索引,我们可以按顺序创建多个子密钥。

扩展密钥

如前所述,可以从父密钥派生出许多子密钥,考虑到已有的三个必需输入。我们还可以创建另一种类型的密钥,称为扩展密钥,它由父密钥和链码组成。

此外,有两种类型的扩展密钥,区别在于所使用的父密钥是私钥还是公钥。扩展密钥可以创建子项,子项可以进一步在树结构中创建子项。

扩展密钥使用Base58Check进行编码,这有助于在钱包之间轻松导出和导入。这些密钥基本上是父密钥的扩展,因此共享任何扩展密钥都可以访问整个分支中的所有内容。

扩展私钥在密钥的Base58Check中具有xprv前缀,而扩展公钥在密钥的Base58Check中具有xpub前缀。以下图表显示了扩展密钥是如何形成的:

图片

摘要

在这一章中,我们详细讨论了加密货币钱包和各种类型的加密货币钱包,我们阅读了基于这些货币钱包可以区分的各种特征,并且我们谈论了钱包的使用、每种钱包类型的好处以及在使用特定钱包类型时可能会遇到的问题。我们讨论了关键派生方法及其在安全性、可访问性和钱包的其他方面的重要性。

第十章:替代区块链

在前几章中,我们学习了区块链、其结构、组成部分、机制以及区块链的最大用例——比特币。在最后一章中,我们讨论了加密货币钱包及其在区块链中的角色和用途。我们的讨论大部分围绕比特币和其他加密货币展开。

比特币的成功吸引了很多关注,不仅是技术上的,还有底层的区块链分类账系统,社区开始创建基于区块链的替代加密货币,每次都在试图在某种程度上改进。随后,各种组织开始通过对比特币的参数进行轻微修改或变更,但保持区块链的核心定义不变,即公共分类账。一些试图创建替代区块链的项目并没有引起太多关注,但其他项目则得到了很多关注和社区支持。

在这一章中,我们将讨论以下主题:

  • 区块链在政府、医疗保健、医学研究、供应链、艺术品、航运、能源、企业等各个行业的用途

  • 瑞波支付系统

  • 星际支付网络

  • Tendermint

  • Monax

区块链的各种用途

分布式分类账技术被称为互联网之后计算机领域最大的革命;区块链正在并将在未来几年影响和改变每个个体。

区块链在货币相关应用中如比特币和山寨币中使用,但除此之外,区块链在其他行业中有各种完全不同的货币使用的用例。以下图表展示了一些正在使用区块链的行业:

政府

全球各地的各个政府正在利用区块链存储公共记录或其他各种政府部门的信息,例如医疗保健、身份管理、税收、投票和金融服务等。

通过拥有去中心化的数据库,政府可以轻松减少欺诈,并在数据输入分布式分类账系统之前引入某些检查。

医疗保健

个人的医疗记录需要进行正确信息的认证,并且有权访问各方面完整的健康记录非常重要。区块链可用于促进数据共享和记录保管。敏感的医疗数据可以方便地被医生和其他医疗社区相关人员访问。

医学研究

医学界的研究人员一直在努力开发更好的创新和技术,以改善临床护理。由于数据存在于区块链上,研究人员可以轻松访问真实数据,并根据适当的批准周期添加理论/结果。系统的互操作性可以在多个层面上提供帮助,并提供精确性和真实性。

供应链

供应链管理是业务流程中最分散的瓶颈之一。一直以来,供应链管理需要更高的效率。由于使用了多个软件系统,它们之间的不兼容性是存在的,每个系统都需要各种数据点以进行更顺利的运转。区块链可以为供应链过程中的每个参与者提供访问相关信息的可能,减少沟通或数据错误,正如下图所示:

图片

版权

区块链可以用于解决版权索赔,因为在基于区块链的系统中,只有在经过共识系统批准后才能引入任何条目,从而确保版权得到维护。

艺术品

艺术产业依赖于艺术品的鉴定;尽管区块链不能鉴定艺术品,也不能确认一幅画是否是原作还是赝品,但它可以用于鉴定所有权。

运输

许多项目正在利用区块链在海运物流业内带来透明度来提高国际贸易。各个全球船东正出于同样的原因使用区块链,以引入基于区块链的技术,并消除分布式分类账技术为该行业解决的任何瓶颈。

能源

区块链能够通过跟踪能源分配和实施高效分配来最大限度地提高能源分配部门的效率。能源生产和在新可持续资源方面的研究可以通过使用区块链来监测真实性和共识的维护,正如下面所示:

图片

计算和数据存储

计算资源在全球范围内被浪费。数据中心和数据湖一直需要高效的数据维护。使用区块链可以确保安全性和改善。

身份和社会保障

用户识别是政府中使用区块链的一个重要用例,但也可以被其他组织用于社会保障和其他需要的身份识别过程。

企业

企业可以在各种情况下使用区块链,例如部门间的协调、办公室内部和办公室间的沟通、数据迁移和其他各种任务。微软、IBM、谷歌、亚马逊等公司已经开始在各种企业部门进行区块链使用的 Beta 测试。

涟漪

Ripple 由 Ripple 公司于 2012 年创建的实时毛额结算和汇款网络。它允许各方之间的支付在几秒钟内完成。它使用自己的货币,称为RippleXRP),也支持非 XRP 支付。Ripple 提出了一个新的分散式全球银行和支付提供者网络,称为 RippleNet。该网络在其核心使用 Ripple 的交易结算技术。RippleNet 拟定独立于银行和支付提供者,为实时支付结算设置了一个标准化网络。

Ripple 网络由执行各自定义任务的各种节点组成。促进系统的第一个节点称为用户节点。用户节点使用 Ripple 进行支付和交易,例如进行付款和接收付款。Ripple 中的第二种节点是验证节点。这些节点是 Ripple 网络中共识机制的一部分。唯一节点列表UNL)中的节点是 Ripple 网络的一部分,并且受到共识机制的信任。任何人都可以成为验证节点或用户节点。以下图显示了 Ripple 网络中发生的交易流程。交易从收集阶段开始,然后通过共识阶段进行移动。最后阶段是账本关闭阶段,为下一组交易创建确定交易的区块以接收:

对于共识机制,Ripple 使用Ripple 协议共识算法RPCA)。RPCA 既不基于工作量证明PoW)也不基于股权证明PoS)系统;相反,其共识机制基于基于正确性的系统运作。共识过程通过向验证节点循环地寻求接受来运作投票系统,以便获得所需数量的投票。一旦收到所需数量的投票,就会验证更改并关闭账本。一旦接受账本中的更改并关闭账本,就会向网络发送警报。

Ripple 网络由各种元素组成,这些元素共同使 Ripple 中的交易成功:

  • 验证器:此元素是共识协议中的参与者。

  • 账本:其中包含账本编号、账户设置、交易、时间戳和账本验证标志等元素。

  • 开放账本:这是进行投票的账本。开放账本包含了提议的交易。

  • 唯一节点列表:这是验证服务器用来寻求投票并推进共识的节点列表。

  • 提议者:此元素提议要成为共识过程一部分的新交易。

交易

Ripple 网络节点创建交易,以更新分类账。交易需要进行数字签名和验证,以便成为共识过程的一部分。每笔交易都需要支付一小笔 XRP,就像以太坊中的 Gas。Ripple 网络有各种类型的交易:与付款相关的、与订单相关的和与账户相关的。

Ripple 网络还提供了各种开发者 API,用于处理交易和付款,以及在 RippleNet 上的集成。Interledger 与 RippleNet 合作,实现与不同网络的兼容性。下图描述了 Ripple 网络中一个区块包含的内容:

Stellar

星际网络用于任何货币的交换,包括自定义代币。星际具有更常被称为星际共识协议SCP)的共识系统,它基于联邦拜占庭协议FBA)。SCP 与 PoW 和 PoS 不同,其主要焦点是为了提供低延迟的更快交易。

它有四个主要特性:

  • 去中心化属性:它允许任何人参与,没有任何中心化的一方。

  • 低延迟:它解决了快速交易处理的急需需求。

  • 灵活的信任:它允许用户选择他们信任的特定目的方。

  • 渐进式安全性:它利用数字签名和哈希函数来提供网络所需的安全级别。

星际网络维护着一个分布式分类账,保存了每一笔交易,并在连接到网络的每个星际服务器上进行复制。共识是通过服务器验证交易,并使用同一交易的更新更新分类账来实现的。星际分类账也可以作为分布式交易所订单薄,因为用户可以存储他们的购买或出售货币的报价。

Tendermint

Tendermint 提供了一种安全且一致的状态机复制功能。它的主要任务是开发一个安全且高性能、易于复制的状态机。它是拜占庭容错的,即使其中三分之一的机器出现故障,Tendermint 也能继续工作。

Tendermint 的两个主要组成部分如下:

  • Tendermint Core:Tendermint Core 能够在网络中的每个节点上安全复制交易。它是一个共识引擎。

  • Tendermint 套接字协议TMSP):TMSP 是一种应用接口协议,允许与任何编程语言进行接口,并有助于处理交易。

Tendermint 共识算法是一种基于轮次的机制,其中验证节点在每个轮次中启动新的块。使用锁定机制来确保当两个不同的块被选定用于在区块链的同一高度关闭时不会出现问题。每个验证节点同步包含交易的块的完整本地复制分类帐。每个块包含一个标头,其中包含前一个块哈希、建议块的时间戳、当前块高度以及该块中包含的所有交易的 Merkle 根哈希。

以下图表显示了共识引擎和客户端应用程序通过 Tendermint Socket 协议之间的流程:

Tendermint 协议的参与者通常被称为验证者。每个验证者轮流提议交易块。他们也像之前讨论过的 Ripple 投票系统一样对其进行投票。如果一个块无法提交,协议将进入下一轮。然后新的验证者为同一高度提议一个块。投票需要两个阶段才能成功提交一个块。这两个阶段通常称为预投票和预提交阶段。只有三分之二以上的验证者为同一块在同一轮进行了预提交,块才会被提交。

由于各种原因,验证者无法提交一个块。这可能包括当前的提议者离线,或者网络质量或速度的问题。Tendermint 还允许验证者确认是否应跳过一个验证者。每个验证者等待一小段时间以从相关的提议者那里收到一个提议块。只有在这之后才能进行投票,他们才能进入下一轮。尽管协议的其余部分是异步的,并且只有听到超过三分之二的验证者集的消息后,验证者才能进展,但这种对时间段的依赖使得 Tendermint 成为一种同步协议。Tendermint 的一个简化要素是,它使用相同的机制来提交一个块,以及跳过到下一轮。

假设少于三分之一的验证节点是拜占庭节点,Tendermint 可以保证不会破坏安全性。这意味着验证节点永远不会在同一高度提交冲突的块。有一些锁定规则来调节可以遵循的路径。一旦一个验证者预提交一个块,它就会锁定在那个块上。在这种情况下,它必须为它将要锁定的块进行预投票,并且它只能解锁并为一个新块进行预提交。

Monax

Monax 是一个成立于 2014 年的区块链和智能合约技术。它最初名为 Eris Industries,但在 2016 年 10 月更名为 Monax。

Monax 有很多可以提供的东西。其中包括各种框架、SDK 和工具,可加速区块链的开发和部署以用于企业。Monax 应用平台背后的理念是实现使用区块链作为后端的生态系统应用的开发。它还允许与多个区块链集成,并使各种第三方系统能够与其他区块链系统交互,并提供高度兼容性。该平台使用以太坊或比特币等区块链上编写的智能合约。它可以与多个区块链进行交互。所有命令对不同的区块链都是标准化的,并且可以在整个平台上使用相同的命令。

Monax 目前积极用于以下应用:

  • 车队租赁

  • 公司治理

  • 知识产权

  • 法律流程

摘要

在本章中,我们介绍了另类区块链。我们讨论了除加密货币以外的区块链的各种用途。其中一些包括政府、医疗保健、医学研究、供应链、版权、美术、航运、能源等。另外,我们讨论了瑞波币(Ripple),这是一种用于快速支付的新区块链,与比特币区块链相比提供了各种修改和改进。接着,我们讨论了恒星支付协议及其主要特性,这有助于加速恒星的支付。Tendermint 是另一种区块链软件,我们讨论并引起了我们的注意。

在下一章中,我们将详细讨论 Hyperledger 及一些基于 Hyperledger 协议的重要项目。我们还将讨论 Hyperledger 协议的详细信息和其他参数。

第十一章:Hyperledger 和企业区块链

与本书讨论的大多数其他区块链系统不同,Hyperledger 从未进行首次 代币发行(ICO),也没有公开交易的代币。这是因为 Hyperledger 本身并不是一个区块链,而是一组用于创建新区块链的技术。此外,这些区块链技术专门设计和构建用于企业用例,而不是公共市场。

在本章中,我们将涵盖以下内容:

  • Hyperledger 的历史

  • 六个当前 Hyperledger 项目的关键细节

  • 支持生态系统使用的 Hyperledger 工具概述

  • 如何选择项目中的 Hyperledger 技术的建议

Hyperledger 的名称不适用于单一技术,而是适用于所有捐赠给 Linux 基金会的区块链技术的集合。

Hyperledger 项目成员包括 Consensys、R3 和 Onchain 等主要区块链公司,以及百度、思科、富士通、日立、IBM、英特尔、NEC、红帽和 VMware 等许多企业技术公司。除了这些公司,许多金融服务公司也加入了,因为区块链在金融科技领域的明显应用。金融服务成员包括澳新银行、美林银行、摩根大通、SWIFT 和富国银行。为了成为下一波商业软件咨询机会的一部分,主要的整合商也加入了——例如安永、CA 科技、普华永道和 Wipro,以及其他许多公司。

最近,亚马逊、IBM 和微软都发布了基于 Hyperledger 技术的区块链即服务产品。

Hyperledger 的历史

Hyperledger 项目成立于 2015 年,当时 Linux 基金会宣布了创建 Hyperledger 项目。它是与 IBM、英特尔、富士通和摩根大通等许多企业玩家合作成立的。其目标是改进并在技术、金融和供应链等主要适合区块链颠覆行业的领域,促进区块链技术的行业合作,使其适用于复杂的企业用例。

该项目在 2016 年获得实质性进展,当时进行了首次技术捐赠。IBM 捐赠了后来成为著名的Hyperledger Fabric的内容,而英特尔捐赠了成为 Hyperledger Sawtooth 的代码库。

与区块链领域的大多数项目不同,Hyperledger 从未发行自己的加密货币。事实上,Hyperledger 的执行董事公开表示永远不会发行加密货币。

Hyperledger 项目

如前所述,超级账本并不是单一的区块链技术,而是由成员公司捐赠的技术集合。虽然有更好的集成长期目标,但目前大多数超级账本项目都是独立运行的。每个项目的核心代码库是由一个或多个超级账本成员组织捐赠的,基于他们在向 Linux 基金会开放源代码和移交所有权之前正在试图解决的问题。

超级账本 Burrow

超级账本 Burrow 是以太坊虚拟机(EVM)和区块链技术的重新实现,但有一些关键变化。首先,Burrow 不使用公共以太坊链使用的工作量证明共识算法,而是设计围绕 Tendermint 共识算法(参见第七章,实现共识)。这意味着在基于 Burrow 的项目中没有矿工,也没有挖矿活动。

其次,超级账本 Burrow 是许可的——允许参与超级账本 Burrow 网络的计算机是已知的并获得授权的,而签署块的计算机(称为验证者,如 Tendermint 中的)也都是已知的。这与以太坊非常不同,任何人都可以匿名下载以太坊软件并加入网络。

为 EVM 编写的智能合约仍然大部分能够工作。由于共识的改变,Gas 的使用方式也有所改变。在公共以太坊区块链中,每笔交易都要根据交易的复杂性付出 Gas 的代价,并且每个区块都有一个 Gas 限制。根据网络负载的不同,参与者必须支付 Ether 的可变成本来获取所需的 Gas。在 Burrow 中,这些复杂性大多被摒弃了。每笔交易都自动获得一定数量的 Gas。由于 Gas 仍然是有限的,Burrow 能够保证所有交易最终完成——要么成功,要么因为 Gas 耗尽而失败。

有关 EVM、solidity 语言以及与超级账本 Burrow 分享的以太坊的其他方面,请参见第十二章,以太坊 101,直至第十五章,以太坊开发

超级账本锯齿状

超级账本锯齿状,与超级账本家族的其他成员一样,是为许可(私有)网络而建立的,而不是公共网络,例如以太坊、比特币等。作为面向企业的区块链系统,它旨在允许不同公司使用区块链和智能合约进行协调。最初由英特尔开发,Sawtooth 使用一种称为时间逝去的证明PoET的独特共识算法。

PoET 使用基于抽奖的系统进行领导者选举。使用特殊的英特尔技术,称为 可信执行环境TEE),以及一些英特尔芯片组上可用的 软件保护扩展SGX),每个节点通过生成随机等待时间来选择领导者,最短等待时间优先。由于生成等待时间的代码位于 TEE 中,因此可以验证每个节点是否运行适当的代码,并且没有通过跳过由随机时间生成器生成的时间来成为领导者。因此,领导者(和区块发行者)的选举非常快速,从而使区块链能够快速运行。

锯齿状架构

Sawtooth 具有可插拔的架构,由 Sawtooth 核心、应用级别和事务族以及共识机制(通常是 PoET,但理论上可以插拔其他机制)组成。我们将在以下章节中详细研究它们。

事务族

因为 Sawtooth 旨在成为可插拔的企业级架构,所以应用层是高度可配置的。每个基于 Sawtooth 的区块链都允许根据所谓的事务族进行交易。事务族确定了在 Sawtooth 区块链上允许进行的操作类型。例如,可以使用 Seth 事务族允许智能合约,就像在以太坊中一样。在 Seth 下,所有可能的基于以太坊的合约和基于以太坊的合约交易都是可允许的,以及由此自由带来的所有可能的错误和问题。

基于 Sawtooth 的区块链可以同时运行多个事务族。事实上,这是常见的,因为 Sawtooth 随附的其中一个事务族是设置族,它直接将系统范围的配置设置存储到区块链上。在大多数情况下,这个事务族和其他几个由业务用例组成的事务族将同时运行。此外,由于可以同时运行多个事务族,这意味着业务逻辑可以被隔离并在多个区块链实现中作为独立的事务族被重用。

由于许多企业只有少数有效的业务规则和业务结果,因此可以通过创建自定义事务系列来定制区块链上的可用操作。例如,一个运输公司可以使用 Sawtooth 来跟踪包裹的位置,而唯一有效的事务可能是新包裹、包裹已接收、包裹已释放、包裹在运输中、更新包裹位置和包裹已交付。通过限制可用事务,可以减少错误和失误的数量。以运输公司为例,网络参与者可能是卡车公司、仓库等。为了使包裹在卡车和仓库之间移动,这两个网络参与者将分别在区块链上的一批中发行包裹已释放和包裹已接收的事务。这引出了 Sawtooth 中的下一个概念:事务批处理

事务和批处理

在 Sawtooth 中,事务始终是批处理的一部分。批处理是一组一起到达并且要么全部成功要么全部失败的事务。如果某个事务需要单独处理,则它将位于仅包含该事务的单个批处理中。使用运输公司的示例,事务包裹已释放和包裹已接收可以被编程为只有在它们的对应事务也在同一批处理中时才成功,从而强制执行成功的交接或抛出错误。下图显示了事务批处理的数据结构:

Sawtooth 中的事务和批处理在高层次上进行抽象,以便可以由自定义事务系列和任意编程语言创建。由于这一点,可以使用 Java、Python、Go、C++ 和 JavaScript 编程智能合约和事务系列。对于任何语言,事务还有另一个限制:序列化,或者从计算机上的内存结构转换为可以通过网络发送的固定二进制。无论使用哪种语言,序列化方法的输出都必须相同。在 Sawtooth 中,所有事务和批处理都以一种称为协议缓冲区的格式进行编码,这是 Google 在内部创建的一种格式,于 2008 年发布。协议缓冲区是在计算机之间具有固定且高性能的数据交换方法,不受编程语言和计算机体系结构的限制。

关键要点

在 Sawtooth 中,事务系列和事务需要开发人员创建一些东西。考虑以下内容:

  • 首先,您需要为将存储的每个事务的数据模型定义协议缓冲区。

  • 其次,您需要一个事务处理程序来处理属于事务系列的传入事务。

  • 最后,需要使用核心 SDK 将处理程序注册到事务处理器中。

Sawtooth 包括基于 Python 的示例源,用于在 GitHub 上的设置和基于身份的交易族。接下来,我们将介绍另一种面向企业的区块链技术 Hyperledger Fabric。

Hyperledger Fabric

Hyperledger Fabric,像 Sawtooth 一样,旨在成为高度模块化和可定制的面向企业的区块链解决方案。Hyperledger Fabric 既是私有的又是许可的。这意味着,默认情况下,Hyperledger 区块链不会对公众开放,也不会在交易所上有可交易的代币。区块链的用户必须具有经过验证的身份,并通过使用成员服务提供商MSP)加入区块链。这些 MSP 在系统上配置,并且可以有多个,但所有成员必须通过一个或多个 MSP 成功获得访问权限。Fabric 还有许多特殊工具,使其功能特别齐全,我们稍后会进行介绍。

架构选择和特性

Hyperledger Fabric 是围绕着几个关键特性和用例设计的,被视为企业用户至关重要。

在核心是账本本身。账本是一组区块,每个区块包含一组交易。交易是更新区块链状态的任何事物。交易是通过安装在区块链上的智能合约代码(称为 链码)执行的。让我们看看区块和交易是如何形成的。

每个区块按顺序排序,每个区块内部都包含一组交易。这些交易也按照特定顺序存储。与其他区块链不同,交易的创建和最终给予的顺序不一定在同一时间或在同一台计算机上执行。这是因为交易的排序和执行是分开的。在 Hyperledger Fabric 中,用于操作区块链的计算机可以运行三种不同模式的节点;它们如下:

  1. Client:客户端代表区块链用户提交操作和事件到网络,作为应用程序的一部分。

  2. Peer:对等节点处理传入的交易以进行验证,并处理由于交易和链代码执行而引起的状态更改。一旦他们执行了交易,他们就会将结果广播给网络,以便交易可以由一个排序者处理(参见下一个角色)。

  3. Orderer:虽然对等节点执行交易,但排序节点查看所有已执行的交易,并决定它们在区块链中被视为发生的最终顺序。排序服务节点决定事件的最终排序,从而决定将写入下一个区块的事件的最终集合。

重要的是要注意,单个计算机可以在 Fabric 区块链上扮演这三种节点类型中的任意一种,但这并非必须。在 Hyperledger 网络上,同一台计算机可以执行交易并排序它们的顺序,但 Hyperledger 可以通过提供这些作为不同服务来实现更好的扩展性。为了说明这一点,请看下面的图表(摘自 Hyperledger 文档):

如您所见,进入的交易首先发送到对等体,对等体使用链码/智能合约执行交易,然后将成功的交易广播到排序服务。一旦被接受,排序服务决定交易的最终顺序,然后将结果交易集重新传输给对等节点,对等节点将最终区块写入链上。

组织重点

作为面向企业的系统,Fabric 在对等体和排序者(区块链网络上的节点)以及拥有它们的组织之间进行了区分。Fabric 旨在在组织之间创建网络,运行区块链的节点代表该组织。通过这种方式,每个节点及其权限都与其代表的组织相关联。以下是来自 Hyperledger 的另一个图表:

如您所见,每个网络节点代表贡献组织运行区块链网络。这与以太坊和比特币等网络不同,在这些网络中,网络由一组独立贡献资源的计算机创建,或者至少在网络看来是独立贡献资源的计算机创建,无论谁拥有它们。在 Hyperledger Fabric 中,是组织创建了共享账本,并通过提供对等体和排序节点的资源来为网络做出贡献。这种区别微妙但至关重要。在大多数公共网络中,想法是让计算机协调,但在 Fabric 中,想法是让公司协调。拥有组织为每个对等体提供了签名的数字证书,证明其是某个组织的成员。然后,该证书允许每个节点通过 MSP 连接到网络,从而获得对网络资源的访问权限。组织与私有计算机的区别将我们带到了 Hyperledger Fabric 的另一个面向企业的特性,这是满足许多公司要求所必需的一个特性:私有通道

私有通道

Hyperledger Fabric 具有一个关键且独特的功能,称为私有渠道。私有渠道允许基于 Fabric 的区块链上的成员子集创建一个新的区块链,该区块链只对他们可见且可互操作。这意味着,虽然 Fabric 已经是私有且有权限的,但私有区块链的成员可以创建一个更小、更独特的链来交换信息,这些信息在整个成员网络上无法交换。因此,Fabric 能够支持关键的用例(例如法律通信),即使在相对独特的网络上也无法广播。

例如,如果 Hyperledger Fabric 被用于建立一个物流网络,主要的区块链可以用于跟踪包裹,但定价竞标可以在私有渠道上进行。网络的参与者将包括许多运输提供商、材料提供商和一组买家。买家可以向区块链发出通知,表示他们接受竞标进行某些物资的转移,然后他们可以在自己和所有运输商和供应商之间创建私有渠道。供应商和运输公司可以向买家提供时间和成本价格,而不将这些信息公开给竞争对手。虽然是私有的,但所有这些交易都会被编码到区块链上进行记录、法律遵从等。此外,如果公司政策是类似于接受第二低价的竞标,整个过程可以通过智能合约自动化。

资产

在 Hyperledger Fabric 中,资产被定义为可以赋予价值的任何东西。虽然这可以用来交换不同的法定货币,但资产也可以被设计为表示一些抽象的东西,比如知识产权,或者更具体的东西,比如一批新鲜鱼的运输。

在 Fabric 中,资产在内部被处理为简单的键值对,其状态存储在分类账上,并可通过链码进行修改。Hyperledger 中的资产可以完成以太坊中由 ERC-20 和 ERC-721 代币执行的所有职责,甚至更多。任何可以以代币格式描述的东西都可以作为资产存储在 Hyperledger Fabric 中。

智能合约

在 Hyperledger Fabric 中,智能合约被称为链码。与以太坊不同,链码不直接嵌入在分类账中。相反,链码安装在每个对等节点上,并与分类账交互,读取和更新链码控制的资产的状态信息。因为链码被所有对等方签名和批准,并且因为使用链码的每个对等方必须验证分类账上的任何状态变化,所以这个系统仍然允许分布式和可信的共识,使用智能合约。为了提供一致性,链码本身在隔离的 Docker 容器中运行。

由于分布式分类帐和链代码的模块化性质,可以使用多种编程语言来开发智能合约;但是,目前支持的选项有限。只有 Go 和 Node.js 有全功能的 SDK 包,但最终计划添加 Java 支持。

Fabric 的优势

Fabric 是最受欢迎的 Hyperledger 项目之一,原因很多。它高度模块化,设计用于跨公司协调,并且私有通道功能使得在公共链上、甚至大多数私有链上都不可能实现的安全功能成为可能。此外,Hyperledger Fabric 还有Composer—一个用于构建区块链应用程序的可视化工具。我们将在后面的 Hyperledger 工具部分讨论 Composer。

接下来,我们将介绍Iroha,这是一个旨在将区块链带入移动设备的 Hyperledger 项目。

Hyperledger Iroha

Hyperledger Iroha是一个由 Soramitsu 贡献的用 C++编写的项目。该项目的目标是提供一个基于可移植 C++的区块链实现,可用于移动设备。iOS 和 Android 操作系统以及诸如树莓派等小型计算机都能够高效地运行紧密编写的 C++代码。为了使事情更加简单,Iroha 为开发人员提供了 iOS、Android 和 JavaScript 库。

与以太坊相比,Hyperledger Iroha 的一个主要区别在于允许用户通过使用系统中预先构建的命令执行常见功能,例如创建和转移数字资产。这消除了编写繁琐且难以测试的智能合约以完成最常见功能的需求,使开发人员能够更快地完成简单任务并减少风险。例如,在 Iroha 上创建新的令牌类型只需一个命令—crt_ast。为了使事情更加简单,Iroha 还有一个命令行界面,将指导新用户在完全不编写代码的情况下创建资产。

如果 Sawtooth 和 Fabric 的目标是完整性,那么 Iroha 更倾向于易用性和设备兼容性。

Hyperledger Indy

区块链技术的更常见的用例之一是身份验证和授权。您可能已经在网络上遇到了问题,您需要记住许多用户名和密码来向其他提供商(例如 Google 或 Facebook)确认您的身份。这里的问题是您必须信任 Google、Facebook 或其他提供商来管理您的身份并保护它。这会造成单点故障,并允许集中式机构控制哪些身份是有效的以及他们拥有什么权限。这个生态系统是显而易见的分散和去中心化的目标。

Hyperledger Indy 是围绕分散、自我声明的身份构建的区块链项目。Indy 的目标是提供用于创建可在区块链上管理并与其他应用程序和需要身份验证的用例互操作的数字身份的工具和库。

虽然 Fabric、Sawtooth 和 Iroha 都内置了一定程度的身份机制,但 Indy 是专门围绕身份管理而设计的,并且可供不运行在区块链上的应用程序使用。因此,Indy 可用于为 Web 应用程序、公司资源等提供身份服务。现有公司包括 Sovrin(捐赠了原始 Indy 代码库)和 Every。

Hyperledger 中的工具

任何应用程序常被忽视的一个方面是需要有助于管理该应用程序生命周期的有用工具。诸如用于简化部署、调试和设计的软件工具可以极大地提高系统的易用性,对开发人员和用户都是如此。大多数公共区块链严重受限于缺乏高质量的工具和支持。然而,Hyperledger 生态系统继续投资于构建优秀的支持工具。

Hyperledger Caliper

任何系统的常见需求之一是基准测试。Hyperledger Caliper 是一个面向区块链的基准测试工具,旨在帮助区块链架构师确保系统性能足够快,以满足托管组织的需求。使用一组预定义的常见用例,Hyperledger Caliper 将报告一系列关键性能指标,例如资源使用情况、每秒交易数TPS)、交易延迟等。

使用 Caliper,一个致力于区块链应用程序的团队可以在构建智能合约和交易逻辑时持续进行测量,并使用这些测量结果监控性能变化。Caliper 可与 Sawtooth、Indy 和 Fabric 区块链系统兼容。

Hyperledger Composer

Hyperledger Composer 是一个用于在区块链上构建智能合约和业务应用程序的设计工具。它旨在快速原型化用于 Hyperledger Fabric 的链码和资产数据模型。作为一个 Fabric 特定的工具(到目前为止),它主要设计用于帮助理解 Hyperledger Fabric 特定的概念,例如资产、身份管理、交易以及用于驱动所有这些项之间业务规则的链码。

它不是设计成一个“建立完整生态系统并投入生产”的工具,而是设计成用于快速可视化原型制作,以便快速启动可测试的应用程序,并在代码库中直接迭代细节。IBM 在 composer-playground.mybluemix.net/editor 上提供在线演示。

Composer 的主要用户将是区块链开发人员(特别是新开发人员)和一些技术业务用户。它作为开发区块链应用程序的敏捷流程的一部分,可以让开发人员、网络管理员和技术业务用户可视化网络和在其上运行的代码。

超级账本 Cello

如果 Composer 用于辅助构建基于 Fabric 的区块链的某些方面,那么 Cello 就是用于将该区块链部署到各种服务器和云服务的工具。Cello 可用于管理区块链基础设施或以区块链即服务的方式启动新的区块链。常见的生命周期和部署任务包括启动、停止和删除区块链,将新节点部署到现有区块链中,并将区块链操作抽象化,以便在本地机器、云中、虚拟机中等运行。Cello 还允许监视和分析。

Cello 主要是用于所谓的 DevOps,或者说是开发团队和生产运营之间的连接工具。它主要针对 Hyperledger Fabric 项目,但是未来的发展也将支持 Sawtooth 和 Iroha。

超级账本资源管理器

超级账本资源管理器是一个区块链模块,是由 Linux 基金会托管的超级账本项目之一。设计为创建用户友好的 Web 应用程序,超级账本资源管理器可以查看、调用、部署或查询区块、交易和相关数据,网络信息(名称、状态、节点列表)、链码和交易系列,以及存储在分类帐中的任何其他相关信息。超级账本资源管理器最初由 IBM、Intel 和 DTCC 贡献。

超级账本 Quilt

有时候,多个区块链能够进行通信是有意义的。这就是 超级账本 Quilt 发挥作用的地方。Quilt 是一个通过实现 Interledger 协议ILP)来促进跨区块链通信的工具。ILP 是一个通用规范,可供所有区块链使用,以允许跨分类帐通信,最初由 Ripple Labs 创建。借助 ILP,两个分类帐(它们不必是区块链)可以协调,从而将一个分类帐中的值交换到另一个分类帐中。

ILP 是一个协议,可以使用任何编程语言或技术来实现,只要符合标准即可。由于这个原因,它可以用于连接多个完全独立的分类帐,甚至是具有完全不同架构的分类帐。这些分类帐不需要是区块链,可以是任何会计系统。在 ILP 中,跨分类帐通信主要通过称为 连接器 的角色来进行。参见来自 interledger.org 的下图:

ILP 通过一组连接器连接账本。连接器是提供向其目的地转发跨账本通信服务的系统,类似于互联网上的数据包是如何点对点转发的。ILP 的通信数据包从发送者发送到一系列连接器,最终到达接收者。

连接器是此序列中值得信任的参与者,发送者和所有中间连接器必须明确地互相信任。与其他面向区块链的技术不同,ILP 不涉及无需信任的交换。但是,发送者和每个连接器只需信任它们链中最近的链接才能正常工作。

Quilt 是 ILP 的实现,已经代表 Ripple Labs、Everis 和 NTT DATA 捐赠给了 Hyperledger 项目。这些组织还赞助了持续的专职人员,帮助改进 Quilt 代码库,主要使用 Java 语言。

工具之间的关系

Fabric、Cello、Composer、Explorer 和 Caliper 之间的区别可以描述如下:

  • Fabric 是应用程序本身,也是业务逻辑最终所在地

  • Composer 是一个帮助构建此逻辑和最终链码的工具

Fabric 和 Composer 主要参与了区块链项目的开发阶段,紧随其后的是 Caliper 用于性能测试:

  • Cello 和 Explorer 更多地涉及项目的运营方面。Cello 由 DevOps 团队用于在服务器和虚拟机上部署和扩展区块链应用程序

  • Explorer 是一个监控工具,用于检查不同账本之间的运行情况

最后,Hyperledger Quilt 可以用于连接不同的账本和区块链。例如,Quilt 可以用于从基于 Fabric 的系统通信到公共以太坊网络,或者到 ACH 银行系统,或者以上所有情况。

因此,Hyperledger 项目具有用于端到端创建、运行和区块链应用生态系统互操作性的工具。

你应该使用哪个 Hyperledger 项目?

在 Hyperledger 内部存在许多专注于业务用例的子项目,如果存在一些混淆使用的情况也就不足为奇了。这是可以理解的,但好消息是,对于大多数情况,选择适当的项目是清晰的。

到目前为止,最受欢迎和文档最全面的框架是 Hyperledger Fabric。Fabric 还得到了亚马逊和微软的区块链即服务的支持。此外,Composer、Cello 和 Caliper 工具都与最新版本的 Fabric 兼容。对于绝大多数项目来说,Hyperledger Fabric 将是最感兴趣的项目。

第二个最明显的选择是 Sawtooth。对于供应链解决方案,Sawtooth 已经有了一个参考实现。除此之外,Sawtooth 更好地支持用多种语言编写智能合约,而 Hyperledger 仅支持 Go 和 JavaScript。此外,Sawtooth 核心是用 Python 编写的。Python 是数据科学中非常流行的语言,而数据科学经常与区块链技术搭配使用。

最终的选择是 Burrow,它将与从以太坊迁移的技术或需要与公共以太坊网络进行接口的项目很匹配,以及 Iroha,它将与需要在移动设备或其他小型机器上运行区块链的项目更匹配。

使用 Hyperledger

就像许多区块链技术一样,Hyperledger 生态系统相对较新,许多项目甚至还没有达到完整的 1.0 版本。虽然有大量的开发活动和多个已经在生产中使用的工作系统,但整个系统还是分裂的。例如,Sawtooth 是用 Python 编写的,Fabric 是用 Go,Quilt 是用 Java,等等。即使在 Hyperledger 家族内部,要想使用一组同质的技术进行端到端实现也是困难的。

此外,Hyperledger 对私有网络的关注是那些希望拥有公共组件的项目的一个问题。区块链技术的吸引力之一是透明度。一个通过公共使用其技术寻求最大透明度的项目可能需要寻找其他地方或找到一种在 Hyperledger 和公共网络之间建立桥梁的方式——可能是使用 Quilt 和 ILP。

同样,通过 ICO 筹集资金的项目可能应该寻找其他方案。很少有项目尝试将 Hyperledger 作为 ICO 的一部分,据我们所知,其中没有一个项目实际上成功筹款。Hyperledger 仍然主要面向私有网络,而在这方面取得了巨大成功。

总结

现在你对构成 Hyperledger 的不同子项目有了一个很好的了解,并且意识到了可以用来构建基于 Hyperledger 项目的工具。Hyperledger 是一组用于构建企业私有区块链网络的技术,与以太坊和比特币等公开可交易的网络相对。Hyperledger 家族由六个项目和一套支持工具组成,它们都有略微不同的关注点和优势,以适应不同的项目。

随着时间的推移,预计不同的项目将变得更加一致和互操作。例如,Hyperledger Burrow 和 Hyperledger Sawtooth 已经与 Seth 交易族跨界交流,这使 Sawtooth 能够运行以太坊智能合约。预计像 Cello 和 Composer 这样的工具将在适当的时候被扩展以支持更多的 Hyperledger 项目,从而使生态系统变得越来越健壮。

接下来,我们将深入讨论以太坊。以太坊是一个公共区块链网络,也是第一个和最受欢迎的支持完全可编程智能合约的公共网络。

第十二章:以太坊 101

在前几章中,我们详细研究了区块链,比特币,替代加密货币和加密钱包。我们讨论了区块链在不仅是基于货币的应用程序中的用途和好处,而且在其他类似领域中的用途。我们还讨论了比特币如何改变了用于货币利益的区块链使用的格局以及它如何塑造了全球经济。

在本章中,我们将深入研究以太坊区块链。它当前是最大的社区支持的区块链项目,仅次于比特币,支持者和各种项目和代币在其上运行。在本章中,我们将讨论以下主题:

  • 以太坊账户

  • 以太坊网络

  • 以太坊客户端,比如 Geth

  • 以太坊区块链项目的执行环境

  • 以太坊区块

  • 以太坊虚拟机

  • 在以太坊交易中使用燃气

  • 以太和以太获取方法

介绍以太坊

以太坊是一个基于区块链的系统,具有特殊的脚本功能,允许其他开发者在其上构建分散和分布式应用程序。以太坊在开发者中主要以易于开发分散应用程序而闻名。以太坊和区块链之间存在差异。最重要的区别是以太坊区块链可以运行大多数分散应用程序。

以太坊概念于 2013 年底由加密货币研究员和开发者 Vitalik Buterin 构想。它是通过 2014 年 7 月至 8 月间的众筹出售获得资金。以太坊内建了 Turing 完全编程语言,即用于解决任何计算复杂性的编程语言。这个编程语言被称为 Solidity,用于创建合约,有助于在以太坊上创建分散应用程序。

以太坊于 2015 年 7 月 30 日上线,预挖了 11.9 百万枚代币进行众筹,用于资助以太坊的发展。以太坊的主要内部加密货币被称为以太。它被称为首字母缩写ETH

以太坊的组件

让我们讨论一下以太坊的一些通用组件,其主要货币,网络以及其他细节。这将有助于更好地理解以太坊,也可以帮助我们看到与比特币的区别,以及为什么它拥有一个庞大的社区,目前使它成为最重要的加密货币和区块链项目,仅次于比特币区块链。

以太坊账户

以太坊账户在以太坊区块链中起着重要作用。这些账户包含钱包地址以及其他细节。有两种类型的账户:外部拥有账户EOA),由私钥控制,和合约账户,由它们的合同代码控制。

EOAs 类似于比特币中由私钥控制的账户。合约账户与代码相关联,并带有私钥。外部拥有账户具有以太余额,并且可以发送交易,以消息的形式,从一个账户发送到另一个账户。另一方面,合约账户可以有以太余额和合约代码。当合约账户接收到消息时,代码会被触发以执行对内部存储的读取或写入功能,或者向另一个合约账户发送消息。

以太坊网络

只有两个以太坊节点具有相同的创世区块和相同的网络 ID 才能连接。根据使用情况,以太坊网络分为三种类型:

  • MainNet:这是以太坊当前的实时网络;目前最新版本的 MainNet 称为homestead

  • TestNet:这用于测试目的,供开发人员在将合约部署到区块链之前测试智能合约和 DApps。最新版本的 TestNet 称为Ropsten

  • PrivateNet:这用于通过生成新的创世区块来创建权限区块链。

所有前述类型相同,除了它们每个都有不同的创世区块和网络 ID;它们有助于区分各种合约账户和外部拥有账户,如果任何合约正在运行不同的创世区块,那么它们将使用不同的网络 ID 来区分它与其他合约账户。

以太坊正式使用一些网络 ID。其余的网络 ID 可以由合约账户使用。以下是一些已知的 ID:

  • 0:这是以太坊公共预发布测试网,以项目名称奥林匹克(Olympic)而闻名。

  • 1:此 ID 是以太坊公共主网络;它已经有许多版本:Frontier、Homestead 和 Metropolis。我们将在未来的部分中更多地讨论公共 MainNet。

  • 2:这是最初的测试网所使用的 ID;在 2016 年末被弃用。

  • 3:这是书写本书时最新的测试网。它于 2016 年末启动,因为旧的测试网出现了多个问题。

  • 4:这是一个公共测试网,正在尝试 PoA 共识。它被称为Rinkeby

以太坊公共 MainNet

公共 MainNet 的网络 ID 为 1,但由于以太坊拥有一个非常活跃的社区支持,因此以太坊区块链正在进行各种更新和升级;主要有四个阶段的以太坊网络;让我们详细讨论每个阶段:

  • Frontier:这是第一个正式的公共主网络;于 2015 年中期启动。

  • Homestead:这是 2016 年 3 月的一次重大升级。

  • Metropolis:这个升级阶段将给以太坊区块链带来许多升级。这个升级将通过硬分叉实施,分为两个阶段,拜占庭君士坦丁堡

  • Serenity:以太坊的这一版本将共识从 PoW 转移到权益证明PoS)。这本质上是为了降低以太坊网络的功耗。

以太坊客户端

客户端是以太坊区块链的实现;它们具有各种功能。除了拥有常规钱包外,用户还可以观察智能合约、部署智能合约、清理多个以太币账户、存储以太币余额,并进行挖矿以参与 PoW 共识协议。

有各种各样的客户端使用不同的编程语言,一些由以太坊基金会官方开发,一些由其他开发者支持:

  • Geth:基于 Go 编程语言,有时也被称为go-ethereum

  • Parity:基于 Rust 编程语言,由 Ethcore 开发

  • cpp-ethereum:基于 C++构建,由以太坊基金会官方开发

  • Pyethapp:基于 Python 编程语言,由以太坊官方开发

  • ethereumjs-lib:基于 JavaScript 编程语言

  • 以太坊(Java):由 Ether camp 开发的基于 Java 的客户端

  • ruby-ethereum:由 Jan Xie 开发的基于 Ruby 的客户端

  • ethereumH:由 BlockApps 开发和维护的基于 Haskell 的客户端

上述列表包括目前在生产中使用的一些最显著的以太坊特定客户端。除了这些之外,还有许多其他客户端,它们不是由社区大力支持,或者处于开发阶段。现在让我们讨论最显著的以太坊客户端——Geth,或go-ethereum

Geth

这是目前在 Golang 上构建的最广泛使用的以太坊客户端之一;它是运行完整以太坊节点的命令行界面。它是 Frontier 版本的一部分,目前也支持 Homestead。Geth 可以允许其用户执行以下各种操作:

  • 挖矿以太币

  • 创建和管理账户

  • 在两个以太坊账户之间转移以太币

  • 创建、测试和部署智能合约

  • 探索区块历史

安装 Geth

可以使用以下命令在 Ubuntu 系统上安装 Geth:

sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum

安装完成后,运行geth account new来在你的节点上创建一个账户。可以使用geth --help命令来查看各种选项和命令。

在基于 Windows 的系统上,通过从geth.ethereum.org/downloads/下载最新版本,然后下载所需的zip文件,解压缩zip文件,并打开geth.exe程序,可以更容易地安装 Geth。

管理账户

Geth 提供账户管理,使用account命令。有关 Geth 上与账户管理相关的最常用命令如下:

COMMANDS:
 list Print summary of existing accounts
 new Create a new account
 update Update an existing account
 import Import a private key into a new account

以下截图是执行上述代码后生成的输出:

当我们运行创建新账户的命令时,Geth 会在我们的区块链上提供一个地址:

$ geth account new
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat Passphrase:
Address: {168bc315a2ee09042d83d7c5811b533620531f67}

当我们运行list命令时,它会提供与自定义密钥存储目录关联的帐户列表:

$ geth account list --keystore /tmp/mykeystore/
Account #0: {5afdd78bdacb56ab1dad28741ea2a0e47fe41331} keystore:///tmp/mykeystore/UTC--2017-04-28T08-46-27.437847599Z--5afdd78bdacb56ab1dad28741ea2a0e47fe41331
Account #1: {9acb9ff906641a434803efb474c96a837756287f} keystore:///tmp/mykeystore/UTC--2017-04-28T08-46-52.180688336Z--9acb9ff906641a434803efb474c96a837756287f

我们将在后续章节讨论挖矿和合约开发。

以太坊气体

以太坊区块链上的每个交易都需要支付计算成本;这是通过向交易发起者支付气体来实现的。交易执行的每个操作都与一定数量的气体相关联。

每个交易所需的气体量直接取决于要执行的操作数,基本上是为了覆盖整个计算。

简单来说,以太坊区块链上的每个交易都需要用气体付费。气体的最低价格是 1 Wei(以太币的最小单位),但这根据各种因素而增加或减少。以下是显示以太坊气体价格波动的图表:

以太坊虚拟机

以太坊虚拟机EVM)是一个简单的基于堆栈的执行机器,充当智能合约的运行环境。EVM 的字长为 256 位,这也是每个堆栈项的大小限制。堆栈的最大大小为 1,024 个元素,并且采用后进先出LIFO)队列系统。EVM 是一个图灵完备的机器,但受到运行任何指令所需的气体量的限制。气体充当一种推进剂,具有计算信用,这确保了任何错误代码或无限循环都无法运行,因为一旦气体用尽,机器将停止执行指令。以下图表显示了一个 EVM 堆栈:

EVM 在发生异常、气体不足或指令无效时支持异常处理。在这种情况下,EVM 会停止并向执行节点返回错误。气体耗尽时的异常通常称为耗尽气体OOG)异常。

合约和 EVM 可用的存储有两种类型:一种是内存,另一种称为存储。内存就像 RAM 一样,并且在代码完全执行时清除。存储永久存储在区块链上。EVM 是完全隔离的,存储在存储或内存访问方面是独立的,如下图所示:

EVM 直接可访问的存储是字数组,它是非易失性的,并且是系统状态的一部分。程序代码存储在虚拟 ROM 中,可以使用CODECOPY访问,它基本上是将代码从当前环境复制到内存中。

执行环境

除了系统状态和气体外,还需要在执行环境中提供执行节点必须的各种其他元素和信息:

  • 拥有执行代码的帐户的地址。

  • 交易发起方地址。

  • 执行的起始地址。

  • 发起执行的交易的燃气价格。

  • 输入数据或交易数据,取决于执行代理类型。如果执行节点是一个交易,则交易数据将被包含为输入数据。

  • 发起代码执行或交易发起方的帐户地址。如果启动是通过交易,则为发送方的地址,否则为帐户的地址。

  • 交易价值——此金额以 Wei(以太最小单位)表示。如果执行代理是一个交易,则它是交易的价值。

  • 要执行的代码,呈现为迭代函数可以循环执行的字节数组。

  • 当前区块的区块头。

  • 在执行中的消息调用或合约创建交易的数量——即,在当前执行周期中正在执行的 CALL 或 CREATE 数量。

以太坊区块

以太坊区块链是一组类似于比特币区块链的必需参数的集合;以下是以太坊区块的主要元素:

  • 区块头

  • 交易列表

  • 未确认叔/OMMer 的标题列表

区块头

区块头是各种宝贵信息的集合,定义了区块在以太坊区块链中的存在。看看以下内容:

  • 父哈希:父区块头的 Keccak 256 位哈希。

  • 叔/OMMer 哈希:该区块的叔/OMMer 列表的 Keccak 256 位哈希。

  • 受益人:此区块挖矿收集所有费用的 160 位地址。

  • 状态根:状态 trie 根节点的 Keccak 256 位哈希。它在所有交易被处理和执行后计算。

  • 交易根:trie 结构根节点的 keccak 256 位哈希。交易 trie 表示包含在此区块中的交易列表。

  • 收据根:这是基于 trie 结构根节点的 keccak 256 位哈希。这个 trie 由包含在区块中的所有交易的收据组成。收据是在每个交易成功执行后生成的。

  • 日志布隆:这是由包含区块的每个交易收据的日志记录器地址和日志主题组成的布隆过滤器。

  • 难度:每个区块的难度级别。这是通过前一个区块的难度和时间戳计算的。

  • 编号:这是先前区块的总数;创世区块的编号为零。

  • Gas 限制:当前区块的燃料消耗上限。

  • 已使用 Gas:包含在区块中的交易消耗的总燃料。

  • 时间戳:这是区块初始化时间的时代 Unix 时间。

  • 额外数据:此文件可用于存储与此区块相关的任意数据。它的大小必须不超过 32 个字节。

  • Mixhash:这包含一个 256 位哈希,与 nonce 结合使用;它用于证明已消耗足够的计算能力来挖掘块,是 PoW 机制的一部分。

  • Nonce:这是一个 64 位哈希,用于证明(与 mix hash 字段一起)已花费足够的计算工作来创建此块。

以下图表显示了一个块头的结构:

乌姆和叔叔

当挖掘出一个块时,以太坊激励矿工包含一个姑妈或叔叔列表,直到达到一定的限制。尽管在比特币中,如果在相同高度挖掘出一个块,或者如果一个块不包含交易,那么它被认为是无用的;但在以太坊中并非如此。包括叔叔并将它们作为以太坊区块链的一个重要部分的主要原因是,它们减少了发生攻击的可能性,因为它们阻止了中心化。

消息

消息是在两个账户之间传递的数据和价值。此数据包含数据和价值(乙醚金额)。消息可以在合同账户或外部拥有的账户之间以交易的形式发送。

Ethash

Ethash 是以太坊中使用的工作证明PoW)算法。它是 Dagger–Hashimoto 算法的最新版本。它类似于比特币,尽管有一个区别—Ethash 是一种内存密集型算法;因此,难以为其实施 ASIC。Ethash 使用 Keccak 哈希函数,该函数现在已标准化为 SHA-3。

乙醚

乙醚是与以太坊区块链相关联的主要加密货币;每个合同账户都可以创建自己的货币,但在以太坊区块链内使用乙醚支付对 EVM 上合同的执行。乙醚用于购买 gas,而乙醚的最小单位用作 gas 的单位。

由于 Wei 是最小的 Wei 单位,因此这里列出了一个表格,列出了各种面额及其常用名称,以及相关值:

采购乙醚

有各种方式可以获得乙醚进行交易、构建智能合约或分散应用程序:

  • 通过加入挖矿池或进行独立挖矿来挖掘乙醚

  • 使用加密货币交易平台进行交易,并与任何其他加密货币交换

  • 从任何法定货币购买乙醚—有各种交易所允许从法定货币购买乙醚

交易

由于其庞大的社区支持和主要的积极发展,乙醚一直是每个人首选的投资机会。已知有超过 500 个交易所支持乙醚与其他加密货币或法定货币的交换。这里有一个价格图表,显示了从 2018 年 4 月 17 日到 2018 年 5 月 17 日的乙醚价格波动情况:

摘要

在本章中,我们讨论了以太坊的各种组成部分,包括其执行、网络和账户,还对以太坊的客户端进行了详细研究。我们还讨论了燃气和 EVM,包括其环境以及执行过程的工作原理。最后,我们讨论了以太坊块及其块头,以太坊算法,以及以太的获取。

在下一章中,我们将学习Solidity,这是以太坊区块链上合约编写的官方标准语言。学习 Solidity 将帮助我们更好地理解智能合约的开发和部署。

第十三章:Solidity 101

在前几章中,我们详细了解了以太坊。我们了解了以太坊网络、客户端、燃气、以太坊虚拟机和以太坊区块链的其他元素。有关以太坊的一个有趣事实是,任何人都可以使用以太坊创建自己的区块链。

以太坊在其平台上运行智能合约;这些是利用区块链技术执行所需操作的应用程序,使用户能够创建自己的区块链并发行自己的另类加密货币。这是通过使用 Solidity 编码实现的,它是一种用于编写将在以太坊区块链上执行并执行程序化任务的智能合约的合约导向编程语言。

Solidity 是一种静态类型的编程语言,运行在以太坊虚拟机上。它受到 C++、Python 和 JavaScript 的影响,于 2014 年 8 月提出,并由以太坊项目的 Solidity 团队开发。完整的应用部署在区块链上,包括智能合约、前端界面和其他模块;这被称为 DApp分散式应用

我们将在本章中涵盖以下主题:

  • Solidity 基础知识

  • Solidity 文件的布局

  • 智能合约的结构

  • 变量和函数

  • 数据类型

  • 引用类型

  • 键值映射

Solidity 基础知识

Solidity 并不是唯一用于以太坊智能合约的语言;在 Solidity 之前,还有其他语言,但它们并不成功。以下是当前(截至 2018 年 8 月)与以太坊兼容的语言的简要列表:

  • Mutan:受 Golang 启发,于 2015 年 3 月被弃用。

  • LLL:Lisp-like 语言的缩写。虽然它仍然受支持,但很少使用。

  • Serpent:虽然这种语言类似于 Python,但不再推荐使用。

  • Solidity:以太坊基金会引入的第四种语言,迄今为止最成功的用于开发智能合约的语言。它是最有文档记录、最稳定且拥有庞大社区支持的。

  • Vyper:新引入的,比 Solidity 简单易懂得多,尽管它目前没有太多社区支持。它受 Python 的影响。

Solidity 也被称为合约导向语言,因为合约类似于面向对象语言中的类。Solidity 语言 loosely 基于 ECMAScript(JavaScript);因此,了解 ECMAScript 将有助于理解 Solidity。以下是开发、测试和部署以 Solidity 编写的智能合约所需的一些工具:

  • 测试网:选择要工作的测试网,要使用的指定网络 ID。

  • 编译器:选择所需的编译器,例如 solc,它是 Solidity 编译器;它包含在大多数节点中,并且还作为一个独立的软件包提供。

  • Web3.js:连接以太坊网络和我们的 DApp 的库,通过 HTTP 或 IPC 网络连接。

  • 框架:从可用于合约编译、部署和其他任务的框架中选择一个是很重要的。一些常用的框架包括 Truffle、Embark、Dapple 等。

除了我们已经提到的关键工具之外,还有各种其他工具可用于开发在以太坊区块链上运行的智能合约,例如理解合约流程、发现安全漏洞、运行测试应用程序、编写文档等等。请看下面的图示:

在 Solidity 上工作的基础知识

如果你经常编程,你应该已经了解到代码编辑器或集成开发环境IDE)。目前已经有一系列各种 IDE 的集成工具列表;除此之外,以太坊基金会还发布了一个基于浏览器的 IDE,其中包含了集成编译器和 Solidity 运行环境,无需服务器组件即可编写和测试智能合约。你可以在 remix.ethereum.org 找到它。

使用编译器

对于小型和基于学习的 DApps 项目,建议使用以太坊基金会的基于浏览器的编译器:Remix。另一种方法是将 Solidity 编译器安装到您的计算机上。可以使用以下命令从 npm 安装 solc

npm install -g solc

Solidity 也可以通过克隆 GitHub 链接上的 Git 存储库来构建:github.com/ethereum/solidity.git

在 Solidity 中编程

在本节中,我们将讨论 Solidity 源文件的结构和元素;我们将讨论布局、结构、数据类型、类型、单位、控件、表达式以及 Solidity 的其他方面。Solidity 文件的格式扩展名是.sol

设计 Solidity 文件的布局

Solidity 正在进行积极的开发,并且有大量来自庞大社区的常规更改和建议;因此,在源文件的开头指定 Solidity 文件的版本是很重要的,以避免任何冲突。这通过 Pragma 版本来实现。这在 Solidity 文件的开头定义,以便任何打算运行该文件的人都知道先前的版本。看看这段代码:

pragma solidity ⁰.4.24;

通过指定版本号,该特定源文件将与指定版本号之前或之后的版本一起编译。

导入文件

与 ECMAScript 类似,Solidity 文件使用import语句声明,如下所示:

import "filename.sol";

上述语句将把filename.sol文件中的所有符号导入到当前文件中作为全局语句。

在导入文件时也支持路径,因此您可以像 JavaScript 一样使用 /...

注释

单行(//)注释和多行(/* ... */)注释被使用,尽管除此之外还有另一种称为Natspec 注释的注释样式,这也是可能的;在这种类型的注释中,我们可以使用////** ... */,它们只能在函数声明或语句之前使用。

Natspec 是自然规范的简称;根据最新的 Solidity 版本(0.4.24),这些注释不适用于变量,即使变量是公开的也是如此。以下是一个小的代码片段,其中包含了这些类型的注释的示例:

pragma solidity ⁰.4.19;

/// @title A simulator for Batman, Gotham's Hero
/// @author DC-man
/// @notice You can use this contract for only the most basic simulation
/// @dev All function calls are currently implement without side effects
contract Batman {
 /// @author Samanyu Chopra
 /// @notice Determine if Bugs will accept `(_weapons)` to kill
 /// @dev String comparison may be inefficient
 /// @param _weapons The name weapons to save in the repo (English)
 /// @return true if Batman will keep it, false otherwise
 function doesKeep(string _weapons) external pure returns (bool) {
 return keccak256(_weapons) == keccak256("Shotgun");
 }
}

标签

它们用于 Natspec 注释;每个标签根据其用法具有自己的上下文,如下表所示:

标签用于
@title智能合约的标题
@author智能合约作者
@notice函数的解释
@dev开发者的解释
@param参数的说明
@return返回类型的解释

合约的结构

Solidity 中的每个合约类似于类的概念。合约可以从其他合约继承,类似于类。一个合约可以包含以下的声明:

  • 状态变量

  • 函数

  • 函数修饰符

  • 事件

  • 结构类型

  • 枚举类型

状态变量

这些值被永久存储在合约存储中,例如:

pragma solidity ⁰.4.24;

contract Gotham {
 uint storedData; // State variable
 // ...
}

函数

函数可以在内部或外部调用,例如:

pragma solidity ⁰.4.24;

contract Gotham {
 function joker() public Bat { // Function
 // ...
 }
}

函数修饰符

函数修饰符可用于在声明中修改函数的语义。也就是说,它们被用来改变函数的行为。例如,它们被用于在执行函数之前自动检查条件,或者根据需要在给定时间段内解锁函数。它们可以被派生合约覆盖,如下所示:

pragma solidity ⁰.4.24;

contract Gotham {
 address public weapons;

modifier Bank() { // Modifier
 require(
     msg.sender == coins,
     "Only coins can call this."
     );
     _;
 }

    function abort() public coinsbuyer { // Modifier usage
 // ...
 }
}

事件

事件允许通过 DApp 前端方便地使用 EVM。事件可以被监测和维护。请看以下代码:

pragma solidity ⁰.4.24;

contract Attendance {
      event Mark_attendance(string name, uint ID); // Event

    function roll_call() public marking {
             // ...
                 emit Mark_attendance(Name, ID); //Triggering event
         }
}

类型

在 Solidity 中,每个变量的类型都需要在编译时指定。复杂类型也可以通过组合复杂类型在 Solidity 中创建。在 Solidity 中有两类数据类型:值类型引用类型

值类型

值类型被称为值类型,是因为这些类型的变量在自己分配的内存中保存数据。

布尔

这种类型的数据有两个值,要么为真,要么为假,例如:

bool b = false;

上述语句将false赋给布尔数据类型 b

Solidity 中的运算符与 JavaScript 运算符相似,例如算术运算符、赋值运算符、字符串运算符、比较运算符、逻辑运算符、类型运算符和位运算符。这些运算符可以根据允许的用法与各种值类型一起使用。

整数

这个数值类型分配整数。整数有两个子类型,分别是intuint,分别是有符号整数和无符号整数类型。内存大小在编译时分配;使用int8int256来指定,在这里数字代表内存中分配的大小。只使用intunit来分配内存,默认情况下分配最大的内存大小。

地址

这个数值类型保存了一个 20 字节的数值,这个大小等同于以太坊地址的大小(40 个十六进制字符或 160 位)。看看这个:

address a = 0xe2793a1b9a149253341cA268057a9EFA42965F83

这个类型有几个成员可以用来与合同交互。这些成员如下:

  • balance

  • transfer

  • send

  • call

  • callcode

  • delegatecall

balance 返回地址的 wei 单位的余额,例如:

address a = 0xe2793a1b9a149253341cA268057a9EFA42965F83;
uint bal = a.balance;

transfer用于从一个地址转账到另一个地址,例如:

address a = 0xe2793a1b9a149253341cA268057a9EFA42965F83;
address b = 0x126B3adF2556C7e8B4C3197035D0E4cbec1dBa83;
if (a.balance > b.balance) b.transfer(6);

当我们使用transfersend成员时,消耗的燃气几乎相同。transfer是从 Solidity 0.4.13 开始引入的,因为send不发送任何燃气,也不传播异常。transfer被认为是从一个地址安全地发送以太到另一个地址的一种方式,因为它会抛出一个错误并允许某人传播该错误。

callcallcodedelegatecall用于与没有应用程序二进制接口ABI)的函数交互。call返回一个布尔值,指示函数是否在 EVM 中成功运行或终止。

a调用b时,代码在b的上下文中运行,使用的是b的存储。另一方面,当abcallcode时,代码在a的上下文中运行,并使用a的存储,但是a的代码和存储会被使用。

delegatecall函数用于委托一个合同使用另一个合同的存储,如有需要。

所有这些成员:calldelegatecallcallcode都不建议使用,除非真的有必要,因为它们倾向于破坏 Solidity 的类型安全性。有可能callcode将在不久的将来被弃用。

数组数值类型

Solidity 有固定和动态数组数值类型。关键字从bytes1bytes32在固定大小的字节数组中。另一方面,在动态大小的字节数组中,关键字可以包含字节或字符串。bytes用于原始字节数据,strings用于用UTF-8编码的字符串。

length 是一个成员,用于返回固定大小的字节数组或动态大小的字节数组的长度。

固定大小数组初始化为test[10],动态大小数组初始化为test2[

文字

文字用于表示一个固定的值;有多种类型的文字被使用;它们如下:

  • 整数字面值

  • 字符串字面值

  • 十六进制字面值

  • 地址文字

整数字面量由从 0 到 9 的数字序列组成。八进制字面量和以 0 开头的字面量无效,因为以太坊中的地址以 0 开头。看一下这个:

int a = 11;

字符串字面量使用一对双引号("...")或单引号('...')声明,例如:

Test = 'Batman';
Test2 = "Batman";

十六进制字面量以关键字 hex 为前缀,并用双引号 (hex"69ed75") 或单引号 (hex'69ed75') 包围。

通过地址校验和测试的十六进制字面量是address 类型的字面量,例如:

0xe2793a1b9a149253341cA268057a9EFA42965F83;
0x126B3adF2556C7e8B4C3197035D0E4cbec1dBa83;

枚举

枚举允许在 Solidity 中创建用户定义类型。枚举可转换为所有整数类型。下面是 Solidity 中一个枚举的示例:

enum Action {jump, fly, ride, fight};

函数

有两种类型的函数:内部函数和外部函数。内部函数只能从当前合约内部调用。外部函数可通过外部函数调用方式调用。

函数修饰符

有各种可用的修饰符,对于基于 Solidity 的函数,你不必使用。看看这些:

  • pure

  • constant

  • view

  • payable

pure 函数不能从存储中读取或写入;它们只是根据其内容返回一个值。constant 修饰符函数不能以任何方式在存储中写入。尽管,自 Solidity 版本 0.4.17 起,constant 被废弃以为pureview 函数腾出位置。view 的作用就像constant ,它的函数不能在任何方式改变存储。payable 允许函数在调用时接收以太币。

函数可以通过指定每个之间用空格分隔的修饰符来使用多个修饰符;它们按照编写顺序进行评估。

引用类型

这些是通过引用传递的;它们非常消耗内存,由于分配了它们构成的内存。

结构体

结构体是在一个逻辑组下声明的复合数据类型。结构体用于定义新类型。结构体不能包含自己类型的成员,虽然一个结构体可以是映射成员的值类型。下面是结构体的一个示例:

struct Gotham {

address Batcave;
uint cars;
uint batcomputer;
uint enemies;
string gordon;
address twoface;

}

数据位置

这指定了特定数据类型将被存储的位置。它与数组和结构体一起使用。数据位置使用 storagememory 关键字来指定。还有第三种数据位置,calldata,是不可修改且非持久的。外部函数的参数使用 calldata 存储器。默认情况下,函数的参数存储在 memory 中;其他局部变量使用 storage

映射

mapping 用于键值映射。mapping 可以被视为虚拟初始化的哈希表,使得每个可能的键都存在并映射到默认值。默认值为全零。键从不存储在 mapping 中,只有 keccak256 哈希用于值查找。mapping 定义方式与任何其他变量类型相同。看一下这段代码:

contract Gotham {

    struct Batman {
        string friends;
        string foes;
        int funds;
        string fox;
    }

    mapping (address => Batman) Catwoman;
   address[] public Batman_address;
}

前面的代码示例显示了 Catwoman 被初始化为 mapping

单位和全局变量

全局变量可以被任何 Solidity 智能合约调用。它们主要用于返回有关以太坊区块链的信息。其中一些变量还可以执行各种功能。时间和以太的单位也可以全局使用。没有后缀的以太货币数被假定为 wei。与货币类似,时间相关的单位也可以使用,并且它们之间可以进行转换。

摘要

在本章中,我们详细讨论了 Solidity,了解了编译器,进行了关于 Solidity 编程的详细研究,包括研究 Solidity 文件的布局、合约的结构以及值和引用类型。我们还学习了关于映射的内容。

在下一章中,我们将运用本章的新知识来开发一个实际的合约,并将其部署到测试网络上。

第十四章:智能合约

智能合约的概念最早是由研究人员尼克·萨博在 1990 年代中期构想出来的。在他的论文中,他将智能合约描述为一组承诺,以数字形式指定,其中包括各方执行这些承诺的协议。这个描述可以分为四个部分:

  • 一组承诺

  • 数字形式

  • 通信和执行的协议

  • 自动触发的行动的性能

如您所见,在此过程中并没有直接指定区块链,因为区块链技术当时尚未发明,直到另外 13 年才被发明。然而,随着区块链技术的发明,智能合约突然变得更加可行。

智能合约和区块链技术是独立的概念。区块链可以存在而没有智能合约(例如,比特币实际上没有内置真正的智能合约能力),而智能合约可以在没有区块链的情况下构建。但是,区块链是一种非常适合开发智能合约的技术,因为它允许无信任、去中心化的交换。基本上,区块链提供了智能合约所需的四项中的两项:数字形式和在不同方之间进行通信和执行操作的协议。

在本章中,我们将介绍一些不同的区块链网络及其对智能合约技术的方法。本章将涵盖以下主题:

  • 为什么使用智能合约?

  • 智能合约的方法

  • 智能合约的局限性

通常,各种智能合约方法可以分为不同类型:图灵完备受限指令链下执行链上执行,如下图所示:

在系统上执行的智能合约类型决定了性能,系统上可以执行和不能执行的内容,复杂性,以及当然,安全性的水平。

在我们进一步探讨之前,让我们讨论一下为什么智能合约备受追捧,甚至被认为是具有革命性的。

为什么要使用智能合约?

在智能合约出现之前的世界充满了不确定性。法律合同,即使是简单的合同,也不一定会被遵守,而且在大多数法律体系中寻求救济的成本非常昂贵,即使在法律体系不腐败的国家也是如此。在世界许多地方,合同几乎一文不值,通常只有具有重大政治或财务实力的各方才能强制执行。对于经济或政治体系中较弱的行动者来说,这是一种可怕而不公平的境遇。

我们之前提到的问题主要源于人为因素。只要一个人参与合同的执行,他们就可能是腐败的、懒惰的、误导的、偏见的等等。相比之下,智能合约是以代码编写的,并且旨在无论涉及哪些方都能忠实执行。这为更安全、更便宜、更快速、更公平的结果提供了机会。

让我们更深入地了解智能合约的关键优势,在以下小节中进行讨论。

自动化各方之间的流程和解决方案

智能合约最直接的优势是它们减少了即使是成功和忠实执行的协议所涉及的劳动和痛苦。举个例子,考虑两家公司之间的一个简单的采购订单和发票。想象一下,一个名为**FakeCar Inc.**的公司决定从他们的供应商 Wheelmaster 那里购买 1000 辆轮子。他们之间达成协议,每个轮子的价格是 $20,支付将在轮子送到 FakeCar 时进行。一开始,轮子可能会通过货运公司运送,途中经过多个人的手。一旦到达,FakeCar 需要扫描和检查每个轮子,做笔记,然后向 Wheelmaster 发出支票或电汇。根据涉及的距离,轮子可能由多家公司承运:一家货运公司,洲际航运,另一家货运公司,最后是 FakeCar 的制造设施。在每个阶段,都存在损坏、丢失或交付错误的可能性。一旦交付完成,FakeCar 就需要发出转账以支付发票。即使一切顺利,这个过程也可能需要几周。在此期间,FakeCar 和 Wheelmaster 都不得不担心他们是否能得到他们的轮子或他们的钱。

现在让我们看看这个流程如何通过智能合约来工作:

  1. FakeCar 在区块链上发布了一个采购订单,购买 1000 辆轮子,每辆轮子价格为$20,有效期为 1 个月。

  2. Wheelmaster 从他们的供应商那里发出了一个交货请求,要求一个月内交货,并接受了采购订单。

  3. FakeCar 在智能合约托管中拨款采购订单;Wheelmaster 可以确信如果轮子到货,他们将会得到支付。

  4. Wheelmaster 看到有资金可用于支付轮子费用,并与一个跟踪每个步骤的公司合作,在区块链上记录每个步骤,并接受支付任何遗失的轮子的条款。他们(或其保险公司)还向一个装运托管合同提供足够的资金,以支付可能遗失的装运事件。一旦 FakeCar 签署收据,合同将自动退还运输商的款项。

  5. 轮子已发货并送达,FakeCar 的托管被释放,保险金返回给运输公司。这发生在 FakeCar 登记收据并运输公司签署变更监护权的时刻。

在这种情况下,如果所有参与方都参与到基于区块链的智能合约生态系统中,支付和保险可以得到即时验证和处理,即使跨越国界、文化和语言,结果是所有参与方的结果确定性大幅增加,效率随之增加。例如,如果 Wheelmaster 能够确信他们的发票将被支付,那么他们可以更有效地做出业务决策。

实例:

截至目前,使用区块链和智能合约完成的第一笔重大物流交易在 Corda 区块链上由汇丰银行和荷兰银行完成,涉及从阿根廷到马来西亚的大豆运输。据银行称,这种转移过去非常耗时,需要五到十天。通过区块链,整个金融问题在不到 24 小时内就得到解决了。

智能合约的使用仍处于起步阶段,然而这项技术已经使跨境金融服务的摩擦减少了 80-90%。随着技术和周围生态系统的改善,优势可能会变得更加极端。

提高透明度

如前所述,全球组织经历的负面因素之一是,对于许多交易,信任是必需的。这在金融交易中尤其如此,采购订单、发票和货物在多个方之间移动。这里的信任问题很多。不仅是是否有人会付款的问题,还有他们是否根本就付不起?他们是否有准时付款的历史,如果没有,他们的付款历史有多糟糕?在许多情况下,任何市场中的买家和卖家都拥有非常有限的信息。这在国际上尤为真实。这就是区块链和智能合约可以发挥作用的地方。

结束集中式数据

在美国,每个人都有一个信用评分,由三家大型信用机构计算。这些机构及其方法是不透明的。购买此信息的人以及被报告的人都不被允许深入了解评分是如何计算的,也不能直接更新此信息。信用机构的错误可能对某人融资购买房屋或汽车的能力造成毁灭性影响,给消费者带来宝贵的时间和金钱损失。尽管如此,如果消费者在其信用报告中发现错误,他们必须请求发行者更新,如果该组织拒绝,他们几乎没有选择。更糟糕的是,这些发行者已经证明他们不良地保管了他们收集的私人财务信息。例如,2017 年,Experian 遭受了一次大规模数据泄露事件,泄露了超过 1 亿人的记录。如果这些机构被区块链系统和智能合约取代,人们将能够直接看到规则并更新记录,而不必支付可能不诚实的中间人。

在当前市场上,大公司具有优势:他们既可以支付这些第三方服务的金融数据,也可以支付需要随时间跟踪信息的人员和系统。较小的公司没有获得这样的规模经济,使他们处于竞争劣势,并增加了他们的开销,甚至可能因为缺乏信息而使糟糕的决策使他们破产。然而,即使对于较大的公司来说,汇编这些数据的成本和费用也是累积的。随着越来越多关于信任的数据变得公开并由智能合约自动化,市场竞争格局将会平衡,希望能将市场上的不诚实行为排除在外。这应该会带来市场信心的增加,以及开销的降低,从而增加利润、降低价格,或者两者兼而有之。

增加公平性

在美国,曾经有一个被称为红线的过程,特定族裔的人们被拒绝贷款和获取金融服务,尤其是抵押贷款。这些不公平的做法在某种程度上仍在继续,因为贷款的标准和流程以及利率计算方式都隐藏在中心化组织中。这种现象并不局限于美国;世界上许多地区的种族、宗教和其他偏见扭曲了原本应该是客观决策的事实。通过基于智能合约的系统,规则将会是公开的和可审计的,以确保公平和准确性。

智能合约方法

智能合约的一种方法是允许全功能软件嵌入或与区块链并行,能够响应区块链事件。这是 Hyperledger Fabric、Ethereum、NEO 等公司采取的一种方法。这种方法提供了最大的灵活性,因为基本上没有什么是不能写入区块链系统的。这种权力的缺点是存在出错的风险。可用选项越多,就必须测试的边界情况和排列组合越多,代码中就可能存在未发现的漏洞的风险就越高。

智能合约的另一种方法是为了增加安全性和降低错误成本而大幅减少可能发生的范围。目前的权衡是灵活性与安全性。例如,在恒星生态系统中,智能合约被制作为一组操作。在恒星中,只有十一种操作:

  • 创建账户

  • 支付

  • 路径支付

  • 管理报价

  • 创建被动报价

  • 设置选项

  • 更改信任

  • 允许信任

  • 账户合并

  • 通货膨胀

  • 管理数据

这些操作本身有多种选项和排列方式,因此能够实现相当多的行为。然而,使用这些操作来执行像 DAO 或其他链上治理组织之类的功能并不容易。相反,这种功能必须托管在链下。同样地,在 Stellar 中没有明确的方法来管理类似于 ERC-721 代币,这些代币将跟踪类似于交易卡或甚至是房地产的等价物。Stellar 的智能合约系统专注于可互换资产的转移,如货币。因此,它可以非常快速地扩展,轻松处理多重签名账户和托管,并且以非常高的吞吐量在几秒钟内处理交易。以太坊更灵活,但多重签名功能、代币本身等都需要用 Solidity 编写的软件来创建。以太坊显然更灵活,但需要更多的代码,因此存在更高的缺陷风险。

以太坊智能合约示例

最广泛使用智能合约的区块链是以太坊。在这里呈现的所有具备智能合约能力的网络中,它不仅是使用最广泛的,而且拥有最大的公共分布式应用生态系统。以太坊如此受欢迎的一个原因是,它对智能合约的表示相对直观且易于阅读。在本节中,我们将看一个常见的基于以太坊的智能合约,它满足前面四个条件,并且相对容易理解:一个代币销售合约。以下代码将用 Solidity 编写;有关更多详情,请参阅 Chapter 13,Solidity 101,以及 Chapter 15,以太坊开发

承诺

智能合约的第一个方面是它必须做出一系列的程序性承诺。我们选择查看代币销售合约的原因是它有一个非常简单的承诺:如果你向合约发送以太坊,合约将自动向您的账户发送一个新代币。让我们看一些基本代码,这是明确不是用于生产的;这是简化的代码,以使某些概念更清晰。这段代码来自于StandardToken合约,这是基于 OpenZeppelin 项目的一部分(你将在 References 部分找到相关链接),该项目具有全功能且经过审计的代码来实现相同的效果,但更复杂一些。

首先,这里是一个ERC20代币的接口合约,我们将其保存为名为ERC20.sol的文件:

pragma solidity ⁰.4.23;
interface ERC20 {
 function totalSupply() public view returns (uint256);
  function balanceOf(address who) public view returns (uint256);
  function transfer(address to, uint256 value) public returns (bool);
  function allowance(address owner, address spender) public view returns (uint256);
  function transferFrom(address from, address to, uint256 value) public returns (bool);
  function approve(address spender, uint256 value) public returns (bool);
  event Transfer(address indexed from, address indexed to, uint256 value);
  event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

接下来,我们将在我们的众筹合约中引用该代币接口,该合约将在以太币支付后发送一个ERC20代币:

pragma solidity ⁰.4.23;
import "./ERC20.sol";

contract Crowdsale {

 // The token being sold, conforms to ERC20 standard.
 ERC20 public token;

 // 1 tokens per Eth, both have 18 decimals.
 uint256 public rate = 1; 

 constructor(ERC20 _token) public {
    token = _token;
 }

 function () external payable {
    uint256 _tokenAmount = msg.value * rate;
    token.transfer(msg.sender, _tokenAmount);
 }
}

这是一个非常简化的合约,但再次强调,这对于完整的真实的 Crowdsale 是不够的。然而,它确实说明了智能合约的关键概念。让我们看看每一部分。constructor 方法需要一个对 ERC20 代币的引用,这是将发送以太坊的购买者所得到的代币,如以下代码所示:

constructor(ERC20 _token) public {
    token = _token;
}

由于 Solidity 的工作方式,除非加载了代币,否则此合约无法运行。因此,这段代码隐含的第一个承诺是:必须有一个可供购买的ERC20代币。第二个承诺是转换率,这里设置为非常简单的 1。对于每一个 wei(以太坊中的最小货币单位),购买此代币的人将获得 1 单位的新代币。以太坊有 18 个小数位数,大多数代币也是如此,因此可以假定这将使以太坊与此代币的转换率现在是 1:1。这带我们来到智能合约必要方面的第 4 点:自动执行。以下代码处理此问题:

function () external payable {
    uint 256 _tokenAmount = msg.value * rate; //Calculate tokens purchased
    token.transfer(msg.sender, _tokenAmount); //Execute send on token contract.
}

由于这是代码,智能合约应该以数字形式存在的要求是显而易见的。这里的自动化方面也很简单。在以太坊中,msg.value保存发送命令的以太币货币的价值。当合约接收到以太币时,它会计算购买者应该收到的代币数量并发送它们:无需人类交互,也不需要或可能有可信的方。同样,没有人能够干预,因为一旦部署到网络上,以太坊中的代码是不可变的。因此,使用此智能合约的发件人可以绝对确保他们将收到他们的代币。

安全注意事项

重要的是要了解智能合约所在的领域:分散的、异步的网络。由于生活在这个生态系统中,存在着并不总是显而易见的安全注意事项,可能会导致问题。为了说明这一点,我们将研究 ERC20 标准的两个相关函数:approvetransferFrom。以下是来自 OpenZeppelin 的 approve 函数的代码:

function approve(address _spender, uint256 _value) public returns (bool) {
   allowed[msg.sender][_spender] = _value;
   emit Approval(msg.sender, _spender, _value);
   return true;
 }

approve 函数允许代币所有者表示他们已经批准将其代币转移到另一个帐户。然后,针对不同的事件,可以进行未来的转移。这如何发生取决于应用程序,但是例如代币销售,通过批准转移,区块链应用程序可以随后调用 transferFrom 并移动代币,也许是为了接受支付然后执行操作。让我们看看那段代码:

function transferFrom(address _from,address _to,uint256 _value) public returns (bool) {
   require(_to != address(0)); // check to make sure we aren't transfering to nowhere.

   // checks to ensure that the number of tokens being moved is valid.
   require(_value <= balances[_from]); 
   require(_value <= allowed[_from][msg.sender]);

   // execute the transfer.
   balances[_from] = balances[_from].sub(_value);
   balances[_to] = balances[_to].add(_value);
   allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);

   //Record the transfer to the blockchain.
   emit Transfer(_from, _to, _value); 
   // let the calling code or app know that the transfer was a success.
   return true;
 }

这两个函数共同工作。希望使用该应用程序的用户使用 approve 允许支付,应用程序调用 transferFrom 以接受。但由于调用的异步性质,存在缺陷是可能的。

想象一个应用,在这个应用中,用户可以支付代币来加入数字俱乐部——40 代币可以获得基本会员资格,60 代币则可以获得增强会员资格。用户也可以将代币交易给其他人,或者根据他们的意愿出售代币。这两个功能的理想情况是,用户批准了 40 代币,应用程序将此注册并调用transferFrom来移动这 40 代币,然后作为智能合约的一部分授予用户访问权限。到目前为止一切顺利。

需要牢记的是,这里的每个操作都需要时间,并且事件的顺序是不固定的。实际上,发生的是用户向网络发送消息,触发approve,应用程序发送另一条消息,触发transferFrom,然后一切会在区块被挖掘时解决。如果这些交易的顺序出现错误(transferFromapprove之前执行),交易将失败。此外,如果用户改变主意,决定将批准的代币从 40 个更改为 60 个呢?用户意图如下:

  1. User: approve 40 (block 1)

  2. User: approve 60 (block 1)

  3. App: transferFrom 60 to App (block 1)

  4. App: Grant enhanced membership (block 2)

最终,用户支付了 60 代币,并得到了他们想要的东西。但因为这些事件都是异步的,并且订单是由矿工决定的,所以这个顺序并不是保证的。在这里,可能会发生以下情况:

  1. User: approve 40 (block 1)

  2. App: transferFrom 40 to App (block 1)

  3. User: approve 60 (block 2,因为矿工没有在块 1 中包含它)

  4. App: transferFrom 60 to App (Block 2)

现在用户意外支付了 100 代币。以下是另一个排列组合:

  1. User: approve 40 (block 1)

  2. User: approve 60 (block 1)

  3. App: transferFrom 40 to app (block 2)

  4. App: Grants basic membership (block 2)

  5. App: transferFrom 60 to app (block 3) | 失败

在这个顺序结束时,用户仍然批准了 20 代币,而尝试获得增强会员资格失败了。虽然可以并且应该编写应用程序来避免这些问题,比如允许用 20 代币升级会员资格,并在调用transferFrom之前检查最大批准数量,但这种对细节的关注并不是应用程序作者所保证或自动的。

重要的是要了解的是,在以太坊中,竞争条件和顺序问题是非常重要的。用户无法控制区块链上事件的顺序,应用程序也不行。相反,决定哪些交易发生在哪个块中以及什么顺序的是矿工。在以太坊中,燃料价格影响矿工为交易给出的优先级。其他影响可能涉及最大块燃料限制,已经在块中的交易数量,以及成功解决块的矿工是否已经在网络上看到了交易。因此,智能合约不能假设事件的顺序就是预期的那样。

处理智能合约中的威胁

每个去中心化网络都将不得不处理由不同排序引起的竞态条件。关键是要仔细评估智能合约是否可能存在竞态条件和其他攻击。判断竞态条件错误是否可能的方法就是判断是否涉及到多个函数调用,直接或间接都可以。在前述情况中,用户和应用程序都调用了函数;因此,竞态条件是可能的,还可能发生一种称为前端运行的攻击。单个方法内也可能存在竞态条件,因此智能合约开发者不应放松警惕。

每个网络都有不同的合约执行模型,因此每个网络都有不同的最佳实践。对于以太坊,Consensys 在 consensys.github.io/smart-contract-best-practices/ 维护着智能合约最佳实践清单。

在发布任何智能合约之前,强烈建议组织编写广泛的单元测试和模拟测试,然后根据该网络的最佳实践审计智能合约。

智能合约的局限性

智能合约拥有巨大的权力,但它们确实有局限性。重要的是要注意,这些系统只有建造它们的人一样好。到目前为止,许多智能合约系统由于未预料到的错误和不属于初始设计的事件而失败。在许多情况下,这些只是技术缺陷,可以在时间内至少修复。然而,随着最近急于将区块链技术用于一切,我们可能会开始看到更多实质性的失败,因为人们未能理解技术的限制。要使区块链真正发挥最大的商业影响,必须解决其优点和局限性。

数据质量和错误

像所有系统一样,智能合约的效果取决于其作用的数据。智能合约从网络接收到错误或不正确的信息仍将执行。在区块链系统中,这可能是一个巨大的问题,因为大多数由人类或合约发起的交易都是不可撤销的。因此,如果在区块链上放置了错误、欺诈或其他缺陷的信息,那么智能合约仍将忠实执行。智能合约现在不是在促进网络的正常运行,而是在帮助传播错误。

以前在 FakeCar 和 Wheelmaster 之间运输轮胎的例子中,如果在运输途中装载轮胎的箱子被破坏并被替换了,那该怎么办?如果 FakeCar 的工人扫描收货的箱子而不检查每一个箱子,智能合约会看到这个更新并释放托管资金。承运人会收回他们的保险金,Wheelmaster 会收到付款,而 FakeCar 仍然没有他们订购的轮子。对于智能合约的纯粹主义者来说,这才是事情应该的样子。但在这些情况下,公司可能会拒绝使用智能合约,或者要求额外的批准层——基本上重建旧系统。

因此,在设计智能合约系统时,设计者们努力设想所有可能发生错误的方式至关重要。就像 DAO 和迄今为止使用的其他智能合约系统,在这些系统中,小错误可能带来重大后果。

许多智能合约涉及一定程度的人为干预。例如,多重签名钱包要求多人授权交易才会执行。这些接触点引入了与旧系统同样会出现错误的可能性,但会带来不可撤销的后果。

法律有效性

智能合约执行其程序设计的功能。如果法院判定一个智能合约无效,那么该问题将如何解决?目前的答案是没有人真正知道,但这种情况可能发生,而且很可能会发生。世界上大多数国家对合同可以达成的内容和不可达成的内容,以及合同中可以合法使用的条款有所限制。例如,在美国,对某些金融产品可以收取的利息金额有所限制。其他法规则定了特定行业中支付条件和条款。违反当地和国家法律的智能合约可能面临被取消的风险,导致参与组织进行赔偿、赔偿损害或其他后果,甚至可能是合同的作者。

意义的稳定性

在前面我们看到的代币出售合同中,用户可以确保他们将收到他们购买的代币。但他们无法确定这些代币将来是否有价值或仍然有用。此外,如果这些代币代表其他东西(进入系统,现实资产或其他东西),则这些代币的存在并不意味着这种进入将持续下去,人们将继续接受代币换取资产(请参阅前面提到的法律有效性问题),等等。对于国家货币,货币的使用和接受是由拥有实质权力的政府强制规定的。对于代币,代币的接受和使用没有强制要求。对一些人来说,这正是吸引人的地方——代币的价值更可信赖,因为它建立在社会批准和使用而不是政府的强制执行上。

随着时间的推移,法律框架和贸易可能会变得更加稳定,这将不再是一个问题。

总结

智能合约是在代码中编写的各方之间的协议。智能合约的关键方面是它们包含以数字形式表达的承诺。所有这些承诺都可以使用数字协议进行通信性能执行。合同的结果会自动触发。

此时,您应该对智能合约是什么,它们如何工作以及它们的优势和局限有了扎实的理解。您应该能够理解智能合约生态系统中固有的风险,并能够评估基于智能合约的系统开发中可能的风险。至少,您应该意识到出于安全原因需要仔细而彻底地评估智能合约。请记住,使用智能合约,代码几乎不需要人工干预就可以执行。智能合约中的错误意味着错误造成的损害将与代码运行的速度同步增加。

接下来,我们将深入探讨以太坊开发的智能合约章节。

参考资料

  1. firstmonday.org/ojs/index.php/fm/article/view/548

  2. 尼克·萨博(Nick Szabo),《智能合约:数字市场的构建模块》,1996 年

  3. www.cnbc.com/2018/05/14/hsbc-makes-worlds-first-trade-finance-transaction-using-blockchain.html

  4. fortune.com/2017/12/22/experian-data-breach-alteryx-amazon-equifax/

  5. github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC20/StandardToken.sol

第十五章:以太坊开发

在过去的几章中,我们一直在学习以太坊区块链及其用途以及它如何塑造了分散式技术,不仅仅是基于货币的用途,也适用于其他行业垂直领域。此外,我们还了解了在以太坊区块链上开发的内容,使用智能合约。

在上一章中,我们讨论了 Solidity —— 以太坊基金会推出的编程语言。Solidity 是一种使在以太坊区块链上创建去中心化应用成为可能的语言,无论是用于创建另一种加密货币代币还是区块链可以发挥重要作用的任何其他用例。

在这一章中,我们将专门讨论以太坊开发,其中包括创建代表智能合约的代币。我们将创建一个在以太坊区块链平台上运行的硬币或代币。我们将学习使用 Solidity 进行代币的开发、测试和部署,并讨论智能合约开发阶段的重要方面,这将有助于将智能合约应用于其他应用和行业。

简言之,我们将涵盖以下主题:

  • 准备智能合约开发

  • 智能合约开发

介绍

在这一章中,我们将前进并在以太坊区块链上创建一个代币。我们还将简要介绍 DApp 的开发,它将充分利用智能合约。以下是开发流程所需的工具列表:

  • 代码编辑器或 IDE:与上一章一样,选择一个您喜欢使用的代码编辑器;在本章中,我们选择 Sublime 文本。虽然,也可使用官方在线 IDE Remix。

  • 以太坊钱包:这对在 TestnNet 上部署和测试智能合约是必需的。

  • Solc 编译器:这用于编译智能合约,将 Solidity 语言代码转换为字节码以供 EVM 读取。

  • Truffle 框架:这使得测试和部署智能合约变得更容易。

  • Web3:这是一个 JavaScript 库,用于与以太坊节点通信;例如,如果我们的应用程序有一个前端界面供用户与区块链交互,那么 Web3 允许用户界面与部署在区块链上的合同进行交互。

准备智能合约开发

在我们深入智能合约的开发以及后续测试和部署流程之前,重要的是准备好工具和其他模块,以及准备开发过程,这将有助于创建期望的结果。

Remix

Remix 是目前可在网上使用的官方 IDE;如果您更喜欢使用其他 IDE,可以检查 Solidity 是否是受支持的语言,并开始使用。以下是 Remix 的样式截图:

Remix 是一个功能齐全的在线 IDE,具有诸如代码编译、运行、连接本地主机、在 GitHub 上发布代码等必要功能。

当 Remix 第一次打开时,会加载 Ballot 合约。

Geth 和 Mist

我们可以使用 Geth 运行测试节点,尽管连接和挖掘以太在 TestNetprivate net 中的任务也可以使用官方以太坊客户端完成,该客户端是在 Geth 节点上运行的 Mist 浏览器。

Mist 客户端具有各种功能,例如能够创建以太坊帐户并连接到 MainNetTestNet。我们可以使用 Mist 在区块链上部署或监视已部署的合约。以下截图说明了 Mist 的外观:

MetaMask

MetaMask 是以太坊钱包和以太坊浏览器。MetaMask 使我们能够通过网络浏览器与 DApps 和智能合约进行交互,而无需下载完整的以太坊区块链。它作为 Chrome、Firefox 和其他浏览器的浏览器扩展程序提供。

它允许网站从区块链获取数据,还允许用户从扩展本身发送交易。有了 MetaMask,通过浏览器与以太坊 DApp 进行交互变得更加容易。以下是以太坊钱包的示例截图:

代币标准

使用以太坊,可以创建去中心化应用程序,并且我们还可以在以太坊区块链上发行代币。就像比特币改进提案BIPs)一样,在 GitHub 上托管了一份以太坊改进提案EIPs)的在线列表,可以在此处找到:github.com/ethereum/EIPs。在 EIP-20 中,于 2015 年底左右引入了一个新的代币标准。这个代币标准被称为 ERC20ERC 代表 **以太坊请求评论。**ERC 是由社区开发者编写的;在社区和核心团队的批准后,该提案成为标准。除了 ERC20 外,还有其他各种标准,例如 ERC223 和 ERC721 也在使用中。

在 EIP 中定义了必须遵循的方法,以便代币可以成为 ERC20 代币合约的一部分。

ERC20 中的方法

下面是 ERC20 合约类型中指定的方法;重要的是要遵循给定的方法/事件,以便合约可以属于 ERC20 家族。尽管其中一些规范是可选的,不一定要存在。看一下这个列表:

  • name: 它应该返回合约的名称,例如:BaToken

  • symbol: 返回代币的符号,例如:BATN

  • decimals: 返回代币使用的小数位数,例如:18。

  • totalSupply: 返回代币的总供应量。这是一个必需的方法。

  • balanceOf(address _owner): 返回另一个地址_owner的帐户余额。这是一个强制性方法。

  • transfer(address _to, unit256 _value): 将_value数量的令牌发送到地址_to。这是一个强制性方法。

  • transferFrom(address _from, address _to, uint256 _value): 此方法将_value数量的令牌从地址_from转移到地址_to。智能合约中必须有此方法才能成为有效的 ERC20 合约。

  • approve(address _spender, uint256 _value): 此方法允许地址_spender多次从给定账户提取;它可以提取的最大金额为_value。这也是一个强制性方法;建议首先将 allowance 设置为 0,以防止任何漏洞。

  • allowance(address _owner, address _spender): 返回_spender仍然可以从_owner提取的金额。智能合约中必须有此方法。

  • event Transfer(address indexed _from, address indexed _to, uint256 _value): 当令牌转移时,即使转移的令牌价值为零,也必须触发此事件。

  • event Approval(address indexed _owner, address indexed _spender, uint256 _value): 每当调用approve方法时,也会调用此事件。

Web3

Web3.js是一个 JavaScript 库;它可以通过 JSON RPC 调用与以太坊节点通信,通过连接到 HTTP 或 IPC 连接。Web3.js通过暴露已在 RPC 上启用的方法来工作。

可以使用以下命令通过npm安装Web3

npm install web3

Truffle 框架

Truffle是一个开发框架,可以简化测试和部署以太坊智能合约。可以使用以下命令通过npm安装 Truffle:

npm install -g truffle

Truffle 通过 Mocha 和 Chai 提供的自动化测试框架来帮助合约编译和链接。使用 Truffle,我们可以轻松地将合约部署到任何TestNet、MainNet 或私有 Network ID。Truffle 在 DApp 中完成所有工作,如编译合约、将其注入用户界面并进行测试以检查漏洞。

Ganache

Ganache是由 Truffle 基金会引入的工具,用于在创建的以太坊区块链上运行测试。它具有命令行界面,但在需要时也可以使用图形界面。以下屏幕截图显示了Ganache工具:

在智能合约上工作

让我们深入了解创建智能合约的任务,以及在TestNet上测试智能合约的过程。运行以下讨论的代码的最简单方法是使用 Remix。只需按照以下步骤进行操作:

  1. 当您在浏览器中打开 Remix 时,默认情况下会打开ballot.sol文件;您可以创建一个新文件并开始编辑您的第一个智能合约。看一下这个:
pragma solidity ⁰.4.24;

//This is a test comment, details about the contract can be added here
/*details like Total supply, contract address, Name, Symbol an decimals which will help someone knowing about the contract instead of finding these details within the source code 

*/

contract Gotham{

 string public name;    
    string public symbol;
    uint8 public decimals;
    //most suggested decimal places in 18
   uint256 public totalSupply;

}
  1. 在前面的代码片段中,我们创建了一个使用 Solidity 版本 0.4.24 并命名为Gotham的合约。现在让我们创建一个构造函数,它将初始化我们定义的变量。现在我们的contract代码应该如下所示:
contract Gotham{

    string public name;    
    string public symbol;
    uint8 public decimals;
    //most suggested decimal places in 18
    uint256 public totalSupply;

//Constructor

    constructor() public {
        symbol = "GOTH";         //This is the symbol of our Token
        name = "GothCoin";       //This is the name of our Token 
        decimals = 12;           /* These are the number of decimal places it can have,  it is suggested to have 18 decimal places */
        totalSupply = 100000;    //total supply of coins allowed 
        }

}
  1. 现在,让我们将标准的 ERC20 方法添加到一个单独的合约中;这些方法必须存在于以太坊智能合约中。看看这段代码:
contract ERC20 {

     function totalSupply() public constant returns (uint);
     function balanceOf(address tokenOwner) public constant returns (uint balance);
     function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
     function transfer(address to, uint tokens) public returns (bool success);
     function approve(address spender, uint tokens) public returns (bool success);
     function transferFrom(address from, address to, uint tokens) public returns (bool success);

     event Transfer(address indexed from, address indexed to, uint tokens);
     event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
  1. 此外,为了避免任何溢出或类似问题,重要的是实现一些具有检查机制的基本数学函数,以避免任何函数溢出。以下是可以创建的合约:
contract Arithmetic {

   function Addition(uint a, uint b) public pure returns (uint c) {
        c = a + b;
        require(c >= a);
    }
    function Subtraction(uint a, uint b) public pure returns (uint c) {
        require(b <= a);
        c = a - b;
    }
    function Multiplication(uint a, uint b) public pure returns (uint c) {
        c = a * b;
        require(a == 0 || c / a == b);
    }
    function Division(uint a, uint b) public pure returns (uint c) {
        require(b > 0);
        c = a / b;
    }
}
  1. 我们的合约必须有所有者的地址;当合约部署时,这将有助于转移代币。为此,我们在 Solidity 文件中创建了一个名为Im_owner的合约。看看下面的内容:
contract Im_owner {

    address public owner;
    address public newOwner;
    event OwnershipTransferred(address indexed _from, address indexed _to);

    constructor() public {
        owner = msg.sender;
    }

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }

    function transferOwnership(address _newOwner) public onlyOwner {
        newOwner = _newOwner;
    }
    function acceptOwnership() public {
        require(msg.sender == newOwner);
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
        newOwner = address(0);
    }
}
  1. 现在是时候在contract Gotham上工作,以添加各种将返回总供应量、获取账户中可用代币余额、转移代币和其他重要功能所需的函数。此外,由于此contract Gotham是主要合约,因此我们 Solidity 文件中的其他合约应该在此合约中继承。现在,contract Gotham应如下所示:
contract Gotham is ERC20, Im_owner, arithmetic {

    string public symbol;
    string public name;
    uint8 public decimals;
    uint public totalSupply;

    mapping(address => uint) balances;
    mapping(address => mapping(address => uint)) allowed;

    // Constructor

    constructor() public {
        symbol = "GOTH"; //This is the symbol of our Token
        name = "GothCoin"; //This is the name of our Token 
        decimals = 12; /* These are the number of decimal places it can have, it is suggested to have 18                             decimal places */
        totalSupply = 100000; //total supply of coins allowed 
        }

    // Total supply

    function totalSupply() public constant returns (uint) {
        return totalSupply - balances[address(0)];
    }

    // Get the token balance for account tokenOwner

    function balanceOf(address tokenOwner) public constant returns (uint balance) {
        return balances[tokenOwner];
    }

    // Transfer the balance from token owner's account to to account
    // - Owner's account must have sufficient balance to transfer
    // - 0 value transfers are allowed
    //This function returns true when this is successful

    function transfer(address to, uint tokens) public returns (bool success) {
        balances[msg.sender] = safeSub(balances[msg.sender], tokens);
        balances[to] = safeAdd(balances[to], tokens);
        emit Transfer(msg.sender, to, tokens);
        return true;
    }

    // Token owner can approve for spender to transferFrom(...) tokens
    // from the token owner's account
    //
    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
    // recommends that there are no checks for the approval double-spend attack
    // as this should be implemented in user interfaces 

    function approve(address spender, uint tokens) public returns (bool success) {
        allowed[msg.sender][spender] = tokens;
        emit Approval(msg.sender, spender, tokens);
        return true;
    }

    // This function transfers tokens from the from account to the two account
    // 
    // The calling account must already have sufficient tokens approve(...)-d
    // for spending from the from account and
    // - From account must have sufficient balance to transfer
    // - Spender must have sufficient allowance to transfer
    // - 0 value transfers are allowed

    function transferFrom(address from, address to, uint tokens) public returns (bool success) {
        balances[from] = safeSub(balances[from], tokens);
        allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
        balances[to] = safeAdd(balances[to], tokens);
        emit Transfer(from, to, tokens);
        return true;
    }

    // Returns the amount of tokens approved by the owner that can be transferred to spender's account
    // transferred to the spender's account

    function allowance(address tokenOwner, address spender) public constant returns (uint remaining) {
        return allowed[tokenOwner][spender];
    }

    }
}

前面的代码具有成为有效 ERC20 标准代币的 Solidity 文件所需的最小功能。一旦代码完成,您可以通过按 Remix 右侧面板上的“开始编译”按钮来运行它。编译选项卡旁边还有一个名为“运行”的选项卡,它可以帮助在TestNet上部署智能合约,如下图所示:

在您的浏览器上使用 Remix 运行的 BrowserHello_World.sol 文件

总结

在本章中,我们学习了智能合约开发、测试和部署所需的工具。我们了解了 Remix,以太坊基金会的官方在线集成开发环境;Mist,官方以太坊钱包和浏览器;以及 MetaMask,这是一款帮助以太坊智能合约开发的工具。我们学习了 ERC20 代币标准、Web3 和 Truffle 框架。此外,我们还介绍了智能合约的创建,以及在 Ropsten 上部署智能合约的各种细节。

在接下来的章节中,我们将更深入地学习去中心化应用程序和以太坊账户。我们还将深入研究挖掘、ICO、通过分叉比特币存储库创建我们自己的货币,以及我们将讨论区块链技术面临的挑战。

第十六章:以太坊账户和以太代币

在之前的章节中,我们讨论了以太坊、智能合约,以及智能合约的开发过程,包括基于以太坊区块链开发 ERC20 代币。我们还讨论了以太坊的开发过程以及在以太坊区块链上部署智能合约和代币的过程。

在本章中,我们将详细讨论以太坊账户,还将研究一种以太代币;这个讨论将帮助我们更好地理解去中心化应用。我们还将简要讨论一些热门的以太坊代币和智能合约。我们还将讨论一些重要的话题,比如交易子状态,以太坊区块的验证以及区块最终化过程中涉及的各个步骤。随后,我们将简要讨论以太坊智能合约和货币的一些缺点。

本章涵盖了以下主题:

  • 以太坊状态转换函数

  • 创世区块

  • 交易收据

  • 交易子状态

  • 区块验证

  • 以太坊代币的缺点

介绍以太坊账户

以太坊中的状态由对象组成,每个对象称为一个账户。以太坊中的每个账户包含一个 20 字节的地址。每次状态转换都是各个账户之间的价值和信息的直接交易。在账户之间或对账户进行的每次操作被称为状态 转换。以太坊中的状态转换是通过以太坊状态转换函数完成的。

以太坊区块链中的状态变化从区块链的创世区块开始,如下图所示:

每个区块包含一系列交易,每个区块都与其前一个区块链接在一起。要从一个状态转换到下一个状态,交易必须是有效的。利用共识技术进一步验证交易的有效性,这是我们在前几章已经讨论过的。

为了避免以太坊中的陈旧区块,引入了GHOSTGreedy Heaviest Observed Subtree)协议。这是为了避免任何节点的随意分叉和其他节点的不恰当验证。当两个节点同时发现一个区块时,就会产生陈旧区块。每个节点都发送区块链中的区块进行验证。这在比特币中不会发生,因为在比特币中,区块时间为 10 分钟,区块传播到大约 50%的网络大约需要 12 秒。 GHOST 协议还包括称为叔区块的陈旧区块,并将它们包含在链的计算中。

如前几章所讨论的,在以太坊区块链中有两种类型的账户。即合约账户CA)和外部拥有账户EOAs)。合约账户是具有与其关联的代码以及私钥的账户。EOA 具有以太币余额;它能够发送交易并且没有关联的代码,而 CA 具有以太币余额和关联的代码。合约账户和外部拥有账户各有其特点,新代币只能由合约账户发起。

以太坊状态转换函数

在状态转换函数中,以太坊中的每笔交易都遵循以下过程:

  • 通过确保签名有效、nonce 与发件人账户中的 nonce 匹配以及语法来确认交易的有效性和结构。如果有任何问题,则返回错误。

  • 交易费用的计算是使用燃气价格进行的,并使用签名确定发件人地址。然后,检查并相应减少发件人的账户余额,同时增加 nonce。如果余额不足,则会出现错误。

  • 为了支付交易的费用,需要使用一定数量的燃气。根据交易的大小,按字节逐步收费。

  • 在此步骤中,发生实际价值的转移。流程从发件人账户到接收者账户。如果接收账户不存在,则会创建该账户。另外,如果接收账户是合约账户,则执行合约的代码。如果有足够的燃气可用,则合约代码会完全运行,或者在燃气用尽时停止。

  • 如果由于余额不足或燃气而导致交易失败,则所有状态更改都将被撤销,除了支付给矿工的费用之外。

  • 如果有余额可用,则在支付矿工所需的费用后将其发送回发件人作为找零。函数在此时返回结果状态。

以下图表描述了状态转换流程:

该函数在以太坊的每个客户端中独立实现。

创世区块

这是以太坊区块链的第一个区块,就像比特币区块链的创世区块一样。创世区块的高度为 0。

创世区块于 2015 年 7 月 30 日被挖掘,标志着以太坊区块链的第一个区块。创世区块的难度为 17,179,869,184,如下图所示:

交易收据

收据用于存储事务执行后的状态。这些结构用于记录事务执行的结果。每次事务执行后都会产生收据。所有收据都存储在一个索引为眼树中。其根据置于块头中作为收据根。

元素

元素由四个主要元素组成;让我们在查看收据结构之前讨论以太坊事务收据的每个元素。

事务后状态

事务后状态是在事务执行后保存状态的一种 trie 结构。它被编码为一个字节数组。

已使用燃气

已使用燃气表示包含事务收据的块中使用的总燃气量。它可以为零,但不是负整数。

日志集合

日志集合显示由事务执行产生的日志条目集合。日志包含记录者的地址、日志主题和其他日志数据。

布隆过滤器

布隆过滤器是根据讨论的日志中包含的信息创建的。日志条目被减少为 256 字节的哈希,然后嵌入到块的头部作为日志布隆。日志条目由记录者的地址、日志主题和日志数据组成。日志主题被编码为一系列 32 字节的数据结构,而日志数据由一些字节的数据组成。

结构

以下是事务收据结构:

  Result: {
    "blockHash": "0xb839c4a9d166705062079903fa8f99c848b5d44e20534d42c75b40bd8667fff7",
      "blockNumber": 5810552,
      "contractAddress": null,
      "cumulativeGasUsed": 68527,
      "from": "0x52bc44d5378309EE2abF1539BF71dE1b7d7bE3b5",
      "gasUsed": 7097057,
      "logs": [
        {
          "address": "0x91067b439e1be22196a5f64ee61e803670ba5be9",
          "blockHash": "0xb839c4a9d166705062079903fa8f99c848b5d44e20534d42c75b40bd8667fff7",
          "blockNumber": 5810552,
          "data": "0x00000000000000000000000000000000000000000000000000000000576eca940000000000000000000000000fd8cd36bebcee2bcb35e24c925af5cf7ea9475d0100000000000000000000000000000000000000000000000000000000000000",
          "logIndex": 0,
          "topics": [
            "0x72d0d212148041614162a44c61fef731170dd7cccc35d1974690989386be0999"
          ],
          "transactionHash": "0x58ac2580d1495572c519d4e0959e74d70af82757f7e9469c5e3d1b65cc2b5b0b",
          "transactionIndex": 0
        }
      ],
      "root": "7583254379574ee8eb2943c3ee41582a0041156215e2c7d82e363098c89fe21b",
      "to": "0x91067b439e1be22196a5f64ee61e803670ba5be9",
      "transactionHash": "0x58ac2580d1495572c519d4e0959e74d70af82757f7e9469c5e3d1b65cc2b5b0b",
      "transactionIndex": 0
    }
    Transaction cost: 7097057 gas. 

还需注意,收据在待处理事务中不可用。

事务子状态

事务子状态是在事务执行期间创建的。此事务在执行完成后立即处理。事务子状态由以下三个子项组成。

自杀集合

自杀集合包含在事务执行后处置的账户列表。

日志系列

日志系列是一个索引系列的检查点,允许对以太坊环境外部实体的合约调用进行监控和通知。日志是对智能合约中事件的响应而创建的。它也可以用作更便宜的存储形式。

退款余额

退款余额是发起执行事务的事务中的燃气总价。

消息

消息是在两个账户之间传递数据的事务。这是在两个账户之间传递的数据包。消息可以通过合约账户CA)发送。它们也可以是已由发送者数字签名的交易形式的外部拥有账户EOA)。

消息从不存储,类似于事务。以太坊消息的关键组成部分包括:

  • 发送消息调用者

  • 事务发起者

  • 事务接收方

  • 合约账户,其代码在消息调用期间执行,如果有此目的的账户

  • 最大可用燃气

  • 燃气价格

消息是使用CALLDELEGATECALL方法生成的。

调用

CALL不会在区块链中广播任何内容;相反,它是对指定的合约函数的本地调用。它在节点中本地运行,就像本地函数调用一样。它不消耗任何 gas,是一个只读操作。调用仅在节点上本地执行,不会导致任何状态更改。如果目标账户有关联的 EVM 代码,则虚拟机将在接收到消息后启动以执行所需的操作;如果消息发送者是一个独立的对象,则调用将传递从 EVM 返回的任何数据。

以太坊区块验证

在矿工挖掘后,以太坊区块在被视为有效之前要经过几轮检查;以下是它经过的检查:

  • 所有的伯爵/叔父都必须验证其身份,考虑到叔父的 PoW 是有效的。

  • 上一个区块的存在和有效性

  • 区块的时间戳有效性,即当前区块的时间戳必须高于父区块的时间戳。此外,当前区块和父区块之间的时间间隔应不超过 15 分钟。所有区块时间都以 Unix 时间计算。

如果前面的任何检查失败,则区块被拒绝。

叔父验证

在这个过程中,伯爵或叔父会被验证。首先,一个区块最多可以包含两个叔父,其次,头部是否有效以及叔父与当前区块的关系是否满足最大深度为六个区块。

区块难度

以太坊中的区块难度与比特币区块链中的区块难度计算并行。如果两个区块之间的时间缩短,则区块的难度增加。这是为了保持一致的区块生成时间。以太坊 Homestead 版本中的难度调整算法如下:

block_diff = parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99) + int(2**((block.number // 100000) - 2))

在这个算法中,区块的难度是根据区块生成时间来调整的。根据这个算法,如果父区块和当前区块的生成时间差小于 10 秒,则难度增加。如果时间差在 10 到 19 秒之间,则难度保持不变。当两个区块的生成时间差大于 20 秒时,难度降低。难度的降低与时间差成正比。

除了基于时间戳的难度增量外,根据算法,每挖掘 100,000 个区块后,难度将呈指数增长。这被称为以太坊网络中引入的难度定时炸弹,因为这将使在以太坊区块链网络上挖矿变得非常困难。这就是为什么 PoS 是以太坊在不久的将来提出的共识机制的原因。

区块最终化

以太坊区块的最终化涉及以下四个阶段的操作:

  • 伯爵的验证

  • 交易的验证

  • 奖励的应用

  • 状态和区块 nonce 的验证

基于以太坊的代币的缺点

我们在之前的章节中讨论了以太坊及基于以太坊区块链的货币的优点和用途;现在让我们讨论一下基于以太坊的代币的一些缺点:

  • 不稳定:以太坊区块链仍在经历许多变化;这也包括将共识机制从 PoW 转移到 PoS 系统。

  • 可靠性:ERC20 代币或任何其他代币都是基于以太坊构建的。这带来了威胁,因为以太坊本身大多数时候都在频繁变化。

  • 硬分叉:依赖于另一个区块链意味着,由于硬分叉,可能会出现意想不到的问题。

  • 主权:由于代币基于以太坊区块链,对这些代币未来发展没有发言权。选择是否使用 ERC20 应该基于应用和用例。

  • 支持:在智能合约发布到区块链后,对其进行改进或需要支持的任何要求都只能在以太坊区块链上完成,并且对于区块链中提出的任何改变/改进都必须得到整个以太坊社区的批准。

  • 以太作为主要货币:尽管可以创建自己的货币、符号和供应限制,但以太仍然是以太坊区块链中使用的主要货币,因此任何时候,以太都会因为你的代币所做出的努力而得到增值。

摘要

在本章中,我们讨论了以太坊状态转换函数、起源块和交易收据。我们还讨论了交易子状态。除了这些话题之外,我们还讨论了以太坊区块验证以及所涉及的步骤,正如以太坊黄皮书中所讨论的那样。最后,我们简要讨论了使用基于以太坊的代币的一些缺点。

在下一章中,我们将讨论去中心化应用程序,并学习如何创建DApp,以及如何发布一个。我们还将讨论 DApp 的未来以及其对用户的影响。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值