跳转至

区块链架构

区块链架构涵盖了理解区块链内部工作方式的基础知识。能够从事使用以太坊不同领域的不同项目是至关重要的,因为一旦你对所有事物如何协同工作有了坚实的理解,你的思维就会开始以不同的方式看待事物。当您使用它和为它编程时,您将获得区块链中发生的事情的高层次概述。一旦你阅读完这一章,这个复杂生态系统的移动部分将开始变得非常有意义,因为你将获得智能合约如何工作以及它们如何与底层结构相关的高层次概述。

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

  • 超越以太坊
  • 欧洲经济区
  • 了解以太坊区块链
  • 智能合同工作原理的高级概述
  • 基本智能合约编程

超越以太坊

你可能知道以太坊是什么,但为了确保我们在同一页上,你有一些关于以太坊的背景知识是很重要的,以便在没有太多干扰的情况下进一步发展。

解释以太坊

以太坊首先是一个区块链。以太坊是一种运行在许多计算机上的技术,它向消费者提供了一种保证,即他们相信一个可靠的系统会像预期的那样工作。

"以太坊是世界计算机."

-维塔利克·布特林

要了解更多以太坊的核心理念,请查看他们的官方网站:https://ethereum.org

由遍布世界各地的数千台计算机组成的网络被称为节点,它们允许其他人获得他们需要的信息,同时信任代码,目标是分散我们所知的互联网。

为什么去中心化对互联网如此重要?因为我们已经到了一个地步,少数大公司控制着你我可以生产或消费的信息。

政府拥有如此大的权力,以至于他们的规则越来越不受控制。他们偏向于对他们和他们的统治者有利的事情。这是可以理解的——每当一些实体处于食物链的顶端,它们迟早会不可避免地控制其下方的整个系统。

以太坊的目标是创建一个抗审查的开放平台,让人们信任智能合同,这些合同执行第三方实体无法控制的规则。

当你发布一个智能合同时,你有 100%的保证代码将在任何时候运行,没有人能够干扰它,除非它的规则这样说。

以太坊的历史

Vitalik Buterin 在 2013 年的白皮书中描述了以太坊,该白皮书位于:https://github.com/ethereum/wiki/wiki/White-Paper他谈到需要一种运行在比特币之上的脚本语言,因为他参与了比特币杂志的工作,他了解比特币区块链的局限性。

他看到了一个机会,可以创建一个基于分散技术的平台来创建新型应用。

没有多少人相信他的愿景,所以他决定自己和一个小团队创造一个全新的区块链,这个小团队看到了 Vitalik 想法中的潜力。他创建了以太坊瑞士集团,并决定在 2014 年 7 月运营一个初始硬币发行 ( ICO ),在那里他出售以太以换取比特币,总共筹集了大约 1800 万美元。

他创造了智能合同技术,这基本上是程序,它们自己运行,不需要可信的实体来执行它们。它们总是可用的,并且它们运行没有失败。

以太坊提供了一个系统,允许人们在区块链的基础上创建自己的应用程序,这是它成功的原因。在以太坊之前,没有简单的方法在一个去中心化的平台中创建去中心化的 应用 ( dApps )。比特币有一个协议,可以使用操作码和一种叫做脚本的编程语言来创建简单的应用程序,但它没有太多能力,因为它非常低级,并且受到块大小的限制。

以太坊的发展

以太坊的发展计划分为四个不同的阶段,每个阶段都有重大的变化:

  • 边界
  • 农场
  • 大都市
  • 宁静

它用于根据需要交付和研究创新的解决方案,并为不向后兼容的功能提供了一个硬分叉。2015 年,Frontier 作为以太坊的第一个版本推出。一年后,Homestead 推出,其中包括许多改进,并使以太坊成为一个有能力的系统,有足够的能力处理智能合同。

以太坊上最大的 ICO 之一是分散自治组织 ICO,也称为 the DAO,它筹集了 1.5 亿美元,有超过 11,000 人捐款。问题是它被一群不明身份的人攻击了,他们把资金转移到了另一个 DAO 上。有趣的是,一群被称为白帽组的程序员看到了黑客行为的发生,并提取尽可能多的资金到一个被称为白帽道的独立分散组织中,他们在那里储存人们的钱,以便以后分发。

这一事件在社区中引发了一场激烈的辩论,导致以太坊分为两派,其中一些人认为以太坊必须是不可变的,不应该被修改,而另一些人则认为应该有一个硬分叉来恢复所造成的损害。

这就是我们所知的以太坊经典和以太坊的开始。以太坊经典版的用户群明显较小,但它保留了最初的不变性理念,他们认为这是区块链的本质。2017 年 3 月,几家公司联手创建了以太坊企业联盟 ( EEA ),这是一个目前由 500 多名成员组成的非营利组织,其目标如下:

创建开源的、基于标准的区块链规范

——以太坊企业联盟

换句话说,他们创造了一群人,共同为未来的区块链寻求解决方案,这样他们会更好、更快、更有能力。

它遭受了几次黑客攻击,数百万美元被盗。他们不得不做一个艰难的分叉来拯救人们的资金,并有一个臭名昭著的价格波动,但未来看起来是光明的,它将继续,随着需求的增加而改善。

欧洲经济区

以太坊核心团队正在开发的EEA(【entethalliance.org】T2)是最令人兴奋的项目之一,因为他们打算帮助世界各地的公司从分散化技术中受益。通过了解这个项目,当你成为一名 EEA 专家时,你将处于有利的位置。

在本节中,我们将讨论以下主题:

  • 欧洲经济区的愿景
  • 欧洲经济区成员
  • EEA 架构

Vitalik 资助了该组织,因为他收到了高管们的巨大需求,要求他开发可用于大公司处理高要求 dApps 的软件。这些公司现在想建立一个私人版本的以太坊来满足他们的研发需求。

这项计划的有趣之处在于,他们与数百家公司合作,研究和开发在他们之间共享的解决方案。例如,如果 EEA 的一个公司成员为更好更快的 dApps 创建了一个新的实现协议,他们将与其他成员共享它,以便他们也可以从这一前沿研究中受益,同时共同发展以太坊生态系统。

欧洲经济区的愿景

EEA 设想他们将在更长时间内实现的四大公共目标如下:

  • 成为开源标准,而不是产品:

他们只使用开源代码,这些代码可以不受限制地与任何人公开共享,以传播开发进展,这些进展可能会也可能不会帮助其他人改进他们的区块链产品。你看,他们是一个非营利组织,希望通过联合许多对私人区块链解决方案感兴趣的公司的努力来进一步推动区块链(正如我们所知)。

  • 解决企业发展需求:

EEA 帮助公司免费整合他人正在发现的新创新,以便他们可以享受最新要求带来的好处。

  • 在公共和私人以太坊之间分享改进:

他们希望通过从公共区块链获得改进来改进他们正在构建的东西,这样他们就可以更快地发展,同时还能记住一个伟大的产品。

  • 利用现有标准:

说到区块链技术,还有很多有待研究和发现。许多关于可伸缩性、安全性和透明性的问题正在被研究,因为这种类型的分散结构对于现代计算来说是新的。所以,我们的想法是从现有的标准中学习,比如利害关系证明 ( PoS ),以比其他人更快的速度提高。

本质上,他们试图满足许多公司对私人企业和个人应用的快速区块链的需求。

欧洲经济区成员

EEA 的有趣之处在于,任何公司都可以免费加入,只需在网站上填写表格,缴纳年费就可以成为该组织的成员。这种开放性有助于许多人与以太坊区块链的新改进保持联系。

以下是成为会员的年度费用明细:

  • 少于 50 名员工:每年 3000 美元
  • 51 至 500 名员工:每年 10,000 美元
  • 501 至 5000 名员工:每年 15000 美元
  • 超过 5000 名员工:每年 25000 美元

非营利组织每年只支付 3000 美元,不管公司规模如何。成为该联盟的成员,您可以享受一系列的一般好处,例如能够参与讨论、投票、开放源代码、聚会,以及在您的网站上使用 EEA 徽标所带来的声望。作为一家区块链的大公司,成为会员仅仅是因为你的网站上有 EEA 的标志,你就可以获得声誉。

这些好处取决于您所在公司的类型,您可以在以下部分看到这些好处:

  • A 类成员是管理与联盟相关的公司的董事。他们在做出决定时有优先权,并能获得所有的利益。
  • B 类成员是那些拥有正常公司的人,因此他们获得标准福利而没有排他性。

  • C 类成员是律师和律师事务所,当涉及到在欧洲经济区所做的研究时,他们负责法律挑战。

  • D 类成员是非营利性公司和学术机构。他们以最低的价格获得基本的利益,却没有投票权。

欧洲经济区拥有约 500 家公司,包括英特尔、微软和摩根大通等巨头。如果你经营一家相当规模的公司,你可能会有兴趣成为欧洲经济区的一员,成为这场区块链企业革命的一部分。

EEA 架构

用 EEA 的工具构建的企业级应用程序有一个非常有趣的结构,它构建在现有以太坊结构之上。他们开发了企业以太坊架构栈 ( EEAS ),这是一个指定这种新型以太坊区块链如何在私人环境中工作的设计,具有为隐私设计的功能。从事以太坊企业项目的团队详细描述了这种类型的私有区块链的功能,而不考虑它下面的底层技术,例如软件代码、API 和通信协议。EEA 打算做的是专注于创建他们的规范中所描述的东西,以便人们可以为他们的公司享受私人区块链。

该工具将受益于区块链以太坊公司独有的创新解决方案,例如:

  • 硬件安全模块 ( HSM ):这是一个物理计算设备,它以最大的安全特性安全地存储数字密钥,如您的私人加密货币密钥。例如,Ledger 和 Trezor 是硬件钱包,也称为 HSM,因为它们在物理设备中为您的区块链私钥提供安全性。
  • 许可和认证:这对于以一种更加结构化的方式为用户提供对特定区域的有限访问权限的特定角色非常有用。
  • 企业管理系统:这是用来帮助公司控制他们的私人区块链内部运作。
  • Oracle:这些对于在企业私有区块链之上编写的定制智能契约与外部服务的通信很有帮助。它们对于与外界交换关键信息至关重要。

关于隐私和扩展,我们知道许多不同的团队正在致力于创建独特的解决方案,这可能会使整个社区受益。然而,我们知道,最初,区块链将使用两个主要系统来扩展现有 dApps 的容量:

  • 可信执行的离链事务:等离子体和状态通道等协议正在开发中,以利用可由用户计算机本地执行的离链事务来降低主区块链的计算负荷。
  • 私有事务:使用零知识证明、环签名和许多其他著名协议来保证与公共区块链交换的数据的私密性的事务。这是公司要求的一个重要方面,因为他们拥有不能公开共享的私有数据和内部流程。我们不知道他们会选择哪种解决方案,所以由他们来决定。他们还将实现私有代码执行,这将允许公司在一个安全的环境中执行某些智能合同交易,用户将看到一个编码的散列。

EEA 正在现有核心区块链的基础上构建三个附加元素:

  • 链上私有状态(On-chain private state):这是一个单独的存储隔间,用于存储智能合约的私有状态。它将为我们,开发者,提供真正私有的变量和存储函数,我们可以用它们来保证信息的安全,不让公众看到。对于企业级 dApps 来说非常强大。
  • 可信执行(Trusted execution):这些系统将提供一个可信的执行环境,在这个环境中,代码将在不干扰公共进程的情况下执行。
  • 私人共识:公司将有能力为自己的系统使用自己的私人区块链来达成协议,类似于我们在第三章以太坊资产中的去中心化自治组织部分看到的投票系统。

最后,区块链的网络层将受益于企业 P2P,这将用于在该公司建立的较小节点网络中交换交易,以便他们享受更快的处理速度和确认时间的好处。“区块链企业”将能够与包括公共区块链在内的其他网络进行互动,以交换信息。

了解以太坊区块链

以太坊区块链是一个复杂的系统,由几个重要的组件组成,它们协同工作,实现一个令人印象深刻的平台,每个人都可以用它来创建不可阻挡的应用程序。您将了解区块链内部运作的复杂性,从而更好地了解它是如何制作的。

区块链分权背后的原因

在最基本的层面上,以太坊区块链是一组包含许多节点共享的信息的连接块,因此有一个不可改变的数据结构来永久保存信息。任何区块链的目标都是保存信息,而不可能更改或删除信息,以避免外部实体的审查或操纵。

因此,以太坊区块链通过实现几个众所周知的工具来建立这一概念,这要归功于比特币和之前的研究,以创建在这些模块上运行的程序。

要了解以太坊区块链的内部工作原理,我们必须了解组成区块链的每个组件。首先,我将向您提供区块链作为一组节点的高层次概述,然后我们将从较高到较低的层次逐一介绍构成区块链的金字塔中的每个组件。

作为一组节点的区块链

以太坊是一个分散的平台,这意味着两个或多个节点以协调的方式一起工作,以最终用户视为单一操作的方式实现共同的结果。节点根据它决定扮演的角色执行各种类型的功能。它可以使用挖掘软件提议和验证交易,以达成共识,同时使用工作证明 ( PoW )协议保护区块链,或者作为一个轻量级节点,执行支付验证和许多其他可以用有限资源完成的任务。

以太坊区块链是基于比特币的,因为中本聪创建的系统是一个非常强大的去中心化解决方案。事实上,它使用一个系统来执行分散的代码,这些代码使用操作码,可以在成千上万台计算机的网络上以安全的方式处理基本指令。他们必须简单,以维护安全高于一切。

尽管两个区块链的系统非常相似,但它们也有明显的差异,例如:

  • 比特币和以太坊使用 PoW 来生成区块,而以太坊打算在未来转移到 PoS 作为区块生成系统,以避免浪费计算能力。
  • 以太坊使用 Ethash 算法,而比特币使用 SHA256 来处理交易和生成区块。
  • 以太坊的封锁时间大概是 15 秒,比比特币快 100 倍左右。这给了人们更好的确认时间。

以太坊区块链是去中心化和分布式的,这意味着连接的节点彼此独立地具有若干关系,同时在不同的位置运行相同的软件。这对于保证区块链不可阻挡的一面非常重要。以下是每个术语的含义:

  • 去中心化网络:这是一个没有单点控制的计算机运行的网络,没有实体控制整个系统,每个节点以点对点 ( P2P )的关系直接与其他节点相连。如果区块链不是分散的,一些政府或实体可以找到主控制器节点并立即停止整个系统。
  • 分布式网络:这是一个网络,许多不同的计算机在不同的位置运行相同的软件。如果区块链不是分布式的,某个实体可以到达所有节点所在的位置并停止整个操作,因为它们都在同一个地方,所以没有一个实体可以免受这样的攻击。

在下图中,您可以看到这些技术类型的结构如何将节点连接在一起,以便它们能够以自己的方式进行完全安全的通信,因为当试图理解分布式系统和分散式系统之间的差异时,这往往是一个令人困惑的点:

这两个特征赋予以太坊网络无需依赖任何人就能工作的能力,因为成千上万的节点能够以安全和独立的方式相互通信。请注意,以太坊是一个完全开放的区块链,这意味着任何人都可以自由加入和参与所发生的决策,例如块创建和事务处理。它允许人们在没有任何要求的情况下作为参与者加入节点网络,因为整个结构由密码安全算法保护。

节点可以一起工作,或者通过执行意外的代码变得恶意。那些表现出任意行为的节点被称为拜占庭节点。主要目标是创建一个系统,其中节点即使在最糟糕的情况下也能合作,并提供容错保护以避免破坏整个结构。但是,如果构成区块链的节点因为是拜占庭节点而可以随机运行,那么它们是如何协同工作的呢?

说到底,这是一组自愿为同一个目标工作的计算机。没有什么能阻止他们做出意想不到的举动。这就是区块链面临的最有趣的问题之一。有几种解决方案,但仍在进行研究,以在分散式系统中获得性能和安全性之间的完美平衡。

CAP 定理

上限定理最初是由 Eric Brewer 在 1998 年提出的,它指出任何分布式系统都不能同时拥有这三个属性:

  • 一致性:这是节点网络的一种能力,可以同时在它们的计算机中保持区块链数据的一致副本。
  • 可用性:这意味着连接节点的系统在任何时候都是在线的和可用的,同时所有用户都可以访问该系统,以便在需要时无故障地响应请求。
  • 分区容忍度:如果整个网络的一组节点因为任何原因停止工作或失去连接,系统应该不会受到影响,应该会像什么都没发生一样继续正常工作。

已经证明,分布式或分散式系统无法同时拥有所有这三个属性,这很有趣,因为以太坊就像比特币一样,在看起来相同的时间实现了所有这些属性。事实是,一致性并不是与分区容差和可用性同时实现的,而是在以后实现的。你看,为了在如此多种多样的计算机中保持有序,我们只能希望随着时间的推移,每当区块链以既定的速度增长时,数据达到相同的水平。它落后于其他的。这被称为最终一致性,随着时间的推移,通过验证多个节点来实现目标。由于这个原因,在比特币和以太坊中引入了挖掘的概念,以与 PoW 协议达成共识。

最终,以太坊计划转向 PoS,PoS 由一个节点或用户在系统中保持股份、一定数量的以太或任何类型的有价值投资的想法组成,以便任何恶意活动的负面后果将超过攻击网络的好处。

例如,如果我想成为一名矿工,用我的时间和资源换取一些乙醚,我必须在运行 PoS 协议的智能合同中锁定 100 乙醚。如果我决定验证无效的块或事务,并且有人通过几种安全机制注意到我的恶意行为,我将失去所有这些 100 以太网,并且将无法再次攻击。成功处理一个块的回报是所投入资源的百分比,例如 0.1 ETH。这迫使节点相互合作,负责任地行动,以避免失去一大笔赌注,即使他们同意攻击系统。

或者,委托利益证明(dpo)可以在以太坊的后续版本中使用。它包括通过投票将事务的验证委托给其他节点。它被用于区块链的 BitShares。

以太坊虚拟机简介

以太坊虚拟机 ( EVM )是一种虚拟机,它允许代码在气体成本和价格方面受到限制的情况下执行,其中每个与它交互的人都必须支付一笔费用,以保护网络免受垃圾邮件攻击,以便许多分散的节点可以使用相同的软件相互交互。它处理用汇编代码生成的字节码,汇编代码反过来使用称为操作码 ( 操作码)的指令。这是一台图灵完全计算机。

当我说图灵完成时,我的意思是运行在以太坊之上的智能契约编程语言具有以下特性:

  • 他们可以无限制地访问随机存取存储器 ( RAM
  • 他们可以根据记忆中的信息做出决定
  • 借助whileforrecursive循环,它们可以永远运行
  • 他们可以使用函数

这意味着,如果有足够的时间和资源,智能合约能够执行你给它们的任何操作。当有人说以太坊是图灵完全区块链时,理解这一点很重要,可以避免混淆。

介绍状态机

状态机是一种跟踪区块链上发生的状态变化的机制。例如,正常的一天有两种简单的状态,白天或夜晚。状态机将记录每天每时每刻的情况,以便当太阳下山时,白天的状态变为夜晚。一周中的每一天都是如此。每天可以是七种不同状态中的一种,比如星期一或星期五。每当它在凌晨 12 点改变时,跟踪一周中某一天的状态就会在状态机中得到更新。

状态机实施共识规则,以确保用户在拜占庭抵抗系统中处理有效的事务:

  • 一个 P2P 网络:连接参与者,传播交易和验证交易的块。这是区块链的节点用来在它们之间传播信息以达成共识的网络。

  • 一个激励方案:在以太坊的例子中,这个方案是创建一个经济安全的状态机的动力。以太坊开发商计划转向 PoS 系统,在该系统中,用户将使用基于矿工当时锁定的以太网数量的被动交易验证系统来处理交易。

  • 一个开源客户端:这个客户端是节点用来与区块链交互的客户端。在以太坊中,我们有 Geth、Parity 和许多其他工具,允许您在下载区块链后连接到区块链进行挖掘和处理交易以及各种任务。

您可以通过下载客户端 Geth 并运行geth --fast来下载区块链的轻量级版本,它只跟踪每个块的引用号以限制区块链的下载大小,因为它可以达到数百 GB。轻型客户端的目的是使以太坊区块链可用于存储和计算能力有限的低规格计算机。

P2P 网络

区块链运行在 P2P 网络之上,在 P2P 网络中,节点相互连接以交换数据和状态更新。由于这项技术,我们能够直接与其他计算机进行交互,以便处理订单,这样我们都同意块生成系统。它允许矿工因完成战俘挑战而获得奖励。

共识规则

当我们说共识时,我们指的是在有许多参与者的系统中使用的一组技术,这些参与者就有益于整个底层系统的决策达成一致。虽然投票赋予满足一组要求的少数几个选定个人决定权,但共识考虑到每一个参与者,以就全球思维方式达成一致。

当涉及到区块链技术时,实现任何形式的共识的每个算法必须提供以下特征:

  • 就有益于整个系统的决策达成一致:这个想法是做出不仅有益于个人,而且有益于整个网络的选择,这样每个人都有一个更好的平台。

  • 允许公开参与:每个人都应该完全自由地参与并做出他们认为积极的决定。

  • 足够安全,使恶意行为者无法损害系统:所有的共识协议都必须朝着改善系统的方向发展,恶意用户没有足够的权力为许多其他人做决定。

达成共识的问题始于所谓的拜占庭将军问题,这个问题存在于这样一个事实上,即许多计算机不容易就预先确定的顺序达成一致。一些计算机会很晚收到命令,另一些计算机会忽略它,因为它们不会从执行命令中受益,而另一些计算机会尽可能地遵循命令。

实质上,共识规则是强制性的,以实现所有人都同意的全球状态,同时以有益的方式参与决策过程会得到回报。

工作证明

这是一种保证任务结果难以实现的方法。为什么我们要让处理任务变得困难?奖励那些最擅长完成它的人。在区块链中,处理个人通过网络进行的交易需要耗费处理能力,也就是硬件、能源和时间。它用于在一个简单的过程中生成块:

  • 挖掘器提出一个新的块,该块包含由最近块的报头和随机数计数器组成的散列数。
  • 然后,挖掘器将散列与由挖掘难度确定的目标值进行比较。
  • 如果散列是目标难度,用户通过得到 ETH 得到解决方案的奖励。如果没有,nonce 将递增,直到用期望的解决方案生成散列。

由于挖掘者将与许多其他人竞争,所以必须有一个系统来确保块时间是一致的,因为即使当新节点加入挖掘网络时,我们也希望保持以相同的周期生成块。为了保证相似的封锁时间,挖掘难度被创造出来。

利害关系证明

PoS 是一种新的算法,用于在分散式区块链中的节点之间达成共识,重点是消除 PoW 的高计算性能要求,同时仍然保持网络安全,免受攻击和恶意行为。它的工作方式是基于锁定以太作为一个股份和验证块的风险,失去你的股份,如果你行为不端。流程是这样的:

  • 想要参与 PoS 流程的人被称为验证者。他们首先锁定特定数量的硬币作为他们的赌注(例如,100 以太),他们在采矿时不能碰这些硬币。它应该足够昂贵,以保证人们不会同意攻击系统,如果他们不成功,就有失去他们股份的风险。
  • 然后,他们开始从使用以太坊区块链的人那里接收交易。验证器运行程序来验证它们正在接收的事务是有效的,这样它们就可以通过按顺序对事务进行分组来创建新的块。当他们有足够的交易来支付每个区块的天然气限额时,他们就在这些区块上下赌注——例如,从最初的 100 个乙醚赌注中下注 20 个乙醚。
  • 赌注最多的街区被选为获胜者。
  • 当从生成区块池中选择获胜区块时,在该有效区块上下注的矿工根据他们的赌注获得该区块中使用的总天然气的百分比。他们的报酬不是整体奖励,而是交易费。例如,如果所选择的块有 100 次交易,累积的交易成本总计为 0.5 乙醚,那么这 0.5 乙醚将必须在下注于该块的所有验证器之间分配。如果该区块有来自 10 个用户的 1000 个以太的总赌注,而你下注 20 个以太,你将得到 0.5 个以太的 2%,因为这是你为该区块下注的金额。总的来说,你会得到 0.01 乙醚。

当你为区块下注时,你不会损失任何钱,这只是一个指标,表明你对该区块有效性的信任程度。考虑到没有方块奖励,只有费用,这似乎是一个小奖励,但你必须考虑到这些方块是在几秒钟内产生的。甚至每个街区一秒钟,这最终会在一天内产生很多钱。

理论上看起来很棒,但是有一个主要的障碍阻止了 PoS 完全可行。这被称为无风险问题,显示在以下场景中,其中有一个主链和一个使用 PoS 创建的新链:

说到力量,你可以在任何你想要的叉子上挖矿而没有任何风险,因为你可以在你觉得好的每一个方块上下注。是什么阻止你决定把所有的鸡蛋放在一个新的链条上,从而产生一个硬叉子?

如果我们使用 PoW,只要人们决定接受它作为新的区块链,你就不能移动到一个新的链,而不必花费大量的处理能力和时间来生成新的块。你可能要开采好几个月,创造出一条可以被接受为新硬币的新链条的机会微乎其微,因为它的使用减少了,所以价值更低。

但有了 PoS,你可以简单地分散你的投资组合,在所有看起来有吸引力的板块上下注,而不会有任何后果,因为只要你在验证好的交易,你就不会失去你的股份。你可以毫无风险地在几个不同的区块链上生成积木。这种可能性最终会创造出数百个不同的区块链,因为人们可以同时在所有这些地方采矿。这就是为什么它被称为无利害关系问题,因为当你参与采矿过程时,你不会失去任何东西。

这也是最近一段时间以太坊无法全面切换到 PoS 的主要原因之一。

以太坊的研究人员长期以来一直致力于解决这个问题。其中一项名为 Casper 的提议旨在通过惩罚那些盲目地在新链条上采矿的用户来解决这个问题,方法是剥夺他们的股份,这样用户就可以专注于赌最长的链条。Casper 还惩罚不积极参与网络的节点,这样它们就不会在不提供价值的情况下开始消耗资源。

最终,鉴于许多大型矿池开始获得过多的电力,PoW 必须改善或彻底改变才能变得可持续。我们现在的情况是,四家矿业公司可以获得约 60%的总交易能力,这让他们可以选择运行 51%的攻击,并迫使所有用户根据自己的条件用自己的腐败区块链进行开采。PoS 将会继续存在并再次带来平衡。

智能合同的运作

智能合约是区块链应用程序,可以执行代码并完成各种各样的任务。这些是矿工在开采区块时执行的程序。它们是安全的、不可阻挡的协议,会自动执行和实施。你可能对它们很熟悉,因为这本书是针对以太坊开发者的;然而,如果你不知道如何使用它们,或者如果你想了解更多,你可以放心,因为在适当的时候你会得到详细的解释,你会明白一切。

与传统的纸质合同不同,智能合同在以太坊上不产生现实世界的法律后果,当它们违约时,无法由一个法律实体强制执行。相反,它们依赖于代码即法律的原则,这意味着代码是管理契约行为的准则。您不能执行智能合约中未定义的功能,您必须尊重每个功能的要求。

智能合约的有趣之处在于,它们允许创建不可阻挡的应用程序,这些应用程序将保持数据和功能在区块链上运行,无论底层 web 界面是否不可用或出于任何原因受到指责。智能合约为您打开了一个新的应用程序类型的世界,您可以部署并忘记它,知道它将在任何情况下工作。

关于该守则是否可以作为真正的合同在法庭上被接受,一直存在争议。一方认为,智能合同必须更进一步,并在法律上得到执行,以获得更广泛的应用,而另一方认为,作为法律的代码足以保证协议的安全性和执行。

智能合约是在软件层的区块链之上运行的程序。它们允许开发人员创建分散的无信任程序,这些程序具有管理个人之间事务的特定功能。它们不是依赖于集中式服务器,而是分散式应用程序中的数据库和服务器。

本质上,智能合约的容量必须受到限制,因为我们正在执行的代码将作为事务永久保留在区块链上,这意味着您执行的每个函数都将在区块链中注册,并且不能撤销已经完成的操作。这强加了一些自然的限制,因为你不能仅仅修改公共数据库,以太坊的每个节点都必须无限制地下载。每个改变都必须由网络的所有对等体下载。

它们的目的是解决许多公司在处理投票、银行业务以及人们被期望盲目信任公司而不披露他们用你的数据和钱做什么的情况时所面临的信任问题。它们还提供了可访问性,因为任何有互联网连接的人都能够访问它们并检索存储在其中的数据。

然而,智能合约的功能有限。在许多情况下,它们不是很好的解决方案,例如:

  • 需要能够快速处理信息的执行后端的应用程序,例如创建用户和与应用程序交互。它们天生就很慢,因为它们依赖以太坊的闭塞时间,并且不能在实时情况下工作。
  • 在数据库中存储大量数据的应用程序。智能合约像数据库一样工作,因为它们允许任何人在区块链上存储某些信息,但它们是有限的,并且这样做的成本很高。

气体是另一个需要正确理解的概念。它的创建是因为智能合约是 Turing complete,这意味着它们可以无休止地执行循环,如whilefor,直到任务完成。开发人员可能会创建永无止境的循环,永远停留在同一个状态。为了避免数千个节点无上限地处理一个事务的情况,每个事务都有一个 gas 开销,该开销取决于执行它所需的处理能力。

因此,他们创建了一个系统,在这个系统中,你必须为你使用区块链的每一个行为付费。您可以在区块链上存储信息,但是您必须支付一笔重要的费用,因为使用它的每个节点都必须下载您的更改。计算天然气成本的方法很简单:

  1. 你支付你愿意为你的交易花费的一定的最大限度的汽油。
  2. 您的本地以太坊节点通过检查用于生成所需计算能力的精确近似值的操作码来计算执行您的交易的成本。你看,使用区块链的每个小操作都可以被测量,因为我们使用一种汇编语言来告诉我们这台超级计算机何时被使用以及如何被使用。
  3. 用了适量的气,剩下的退给你。

你还必须确定一个从 1 英镑到通常 100 英镑或更高的天然气价格,以告诉矿工们先处理哪些交易,因为每种天然气越贵,他们得到的报酬就越多。

智能合同部署流程

智能合约运行在以太坊区块链之上,类似于服务器端 web 应用程序的工作方式。然而,向 it 部门部署智能合同的过程却大不相同。为了成为一名专业的以太坊开发人员,您必须了解智能合约代码是如何处理和存储在区块链块中的,以便能够使用它们,因为这将使您了解在推送您新编写的智能合约代码时为什么以及如何出错。

在尝试将代码部署到区块链时收到错误并不罕见,因此为了能够成功地调试它,您需要了解幕后发生了什么。

以太坊交易

要理解智能合约是如何在网络上部署的,首先理解事务是如何工作的是很重要的,因为当您部署智能合约时,您实际做的是用您刚刚构建的应用程序的字节码生成一个事务。

构成以太坊交易的消息由以下编码成分组成:

  • 接收者:这是将获得交易的接收者以太坊地址。
  • :表示传送到接收地址的乙醚量。这个值可以为零,你可以用全局msg.value变量在 Solidity 中访问它。值总是以为单位,以太坊中的最小单位。
  • 数据:这是一个十六进制字节码字符串,主要用于调用带有所需参数的特定函数。这是您需要智能合约来执行的特定信息。当智能合约相互通信时,它们需要一种方法来告诉何时用一组给定的变量执行特定的函数。由于有了这个数据参数,我们可以对在处理事务时希望在契约中调用的函数进行编码。另一方面,当智能合约第一次部署到区块链时,数据参数包含转换为字节码的智能合约,以便机器能够理解它。一般来说,它包含矿工在下一个块中执行的智能合同功能。
  • 汽油限额:这代表汽油限额,即您愿意花费多少汽油来处理您的功能交易。气体极限用魏表示,强制给矿工尽可能多的气体来处理你的代码。
  • 气价:气价决定了你提供的每一种气的价格。如果你的油费是一元,你就要付一元钱。如果是 20 元,你每 1 元汽油要付 20 元。它用于帮助矿工处理交易,因为他们将部分获得交易费。
  • Nonce:Nonce 是一个唯一的计数器号,用于识别交易。这个唯一的计数器用于识别每个块,并帮助挖掘者识别无效块,因为 nonce 必须总是比前一个块大一个数字。
  • 签名:这是一个由三个自变量组成的参数,称为 vrs 。这些变量用于用你唯一的以太坊地址数据签署交易,这样人们就可以确认你就是创建它的人。

当用户对智能合约进行交易时,它被称为消息而不是交易。事务和消息之间存在这种差异,因为消息没有签名数据,因为它们不需要由另一方签名。nonce 是防止重放攻击所必需的,在重放攻击中,外部用户可以获取相同的事务数据并为了自己的利益再次执行它。

当您部署一个智能契约时,您实际上是用一个特殊的字节码标识符向地址0x0发送一个事务,以便矿工理解您正在创建一个新的智能契约。这种情况下的数据参数包含所有智能协定逻辑,包括函数名和参数。

总之,创建和使用智能合约是一个透明的过程,您可以告诉矿工处理您的数据。然后,他们将理解其背后的字节码,并用所需的参数对区块链进行所需的更改。

基本智能合约编程

在理解了智能合同是如何创建的以及它们在区块链系统中的集成位置之后,您现在将获得关于如何使用两种最流行的 it 语言来创建智能合同的更实际的见解— SolidityVyper

固态

Solidity 是为在以太网上开发智能合约而创建的最先进的编程语言。它的语法类似于 JavaScript,但是有静态类型的变量和函数。它提供简单的功能,如函数、循环和几种类型的变量,以及复杂的功能,如汇编、加密功能和签名验证系统。

它已经在许多项目中使用,尤其是 ICOs,取得了巨大的成功,因此它已经足够成熟,可以被任何一种对开发分散应用程序和安全智能契约感兴趣的开发人员使用。

它的主要缺点是更难保护,因为它提供了一套更完整的功能,如果不进行审核,可能会导致安全问题。

文件结构

对于本书中的所有示例,我们将使用 0.5.0 版本的 Solidity。Solidity 中的智能合约总是从文件中使用的版本开始,以确保合约与较新的版本不兼容,因为新添加的功能可能会破坏合约。

让我们通过以下步骤来看看 Solidity 中的合同结构:

  1. 您可以在文件的开头用pragma语句定义版本:
pragma solidity 0.5.0;
  1. 然后你就可以开始写合同了。Solidity 中的所有语句必须以分号(;)结尾才有效。在定义了文件中使用的版本之后,您必须创建合同,如下所示:
pragma solidity 0.5.0;
contract Example {}
  1. 您可以在一个文件中定义多个合同:
pragma solidity 0.5.0;
contract Example {}
contract Another {}
contract Token {}
contract ICO {}
  1. 在契约中,您将拥有状态变量、函数、修饰符和一个构造函数。稍后我会详细解释它们的用法:
pragma solidity 0.5.0;
contract Example {
    uint256 counter;
    modifier onlyOwner {}
    constructor() {}
    function doSomething() {}
}
  1. 在契约中直接定义的变量,意味着它们在函数之外,被称为状态变量。这些是特殊的变量,即使在执行了合同之后,它们的值也会保存下来。请将它们视为您可以随时读取和修改的特殊永久变量:
pragma solidity 0.5.0;
contract Example {
    uint256 myStateVariable;
    string myOtherStateVariable;
    function example(){
        uint256 thisIsNotAStateVariable;
    }
}

如您所见,它们在函数之外,但在契约之内,它们在文件的顶部定义,就在契约开始的时候。正如我所说,它们永远保持其价值,即使在你的合同发生变化之后。所以,如果你的myStateVariable有一个值5,只要你不修改它,你就可以在它被修改几天或几个月后读取这个变量的值。

它们将值直接存储在区块链存储中,而不是内存中。内存中的变量,您将在后面了解到,会在契约执行后丢失它们的值并被重置。

最后,Solidity 文件使用.sol扩展名,例如example.sol。您将学习如何使用Chapter 3【掌握智能合约】Chapter 9分散交换工作流中的 Remix IDETruffle来部署它们。

变量

Solidity 是一种静态类型语言,这意味着你必须定义你创建的每个变量的类型。

让我们定义一下这种编程语言中可用的变量类型,以便稍后理解如何使用它们,但在此之前,您需要理解变量的可见性。

变量的可见性

Solidity 中的每个变量和函数都有特定的可见性。可见性是您在变量类型后使用的关键字,用于定义谁应该可以访问它:

  • Public :这意味着变量可以被任何契约读取或写入,包括外部契约,只要有更新它们的函数。
  • 私有:私有变量不能被派生的智能契约访问,那些用is关键字实现你的契约的;比如contract Example is Another {},其中Another是一个智能合约,私有变量不能被Example访问。
  • 外部:这些变量和函数不能被包含它们的契约访问。只有外部合同和用户可以使用它们。
  • Internal :这些变量和函数不能被外部实体读取或写入,只能被契约本身或继承的契约读取或写入,正如你在私有变量的例子中看到的。

为了简单起见,我建议你总是为你的变量写public,除非它是一个特殊的变量,这并不经常发生。如果你没有定义任何可见性,默认情况下变量将是public,尽管最好在每个变量中只写public关键字,以确保你理解变量的可见性,这不是一个错误。

Uints

Uints 是无符号整数,这意味着它们是从零开始的不能为负的数字。

您可以按如下方式定义它们:

uint public myNumber;

正如您所看到的,首先定义变量的类型,然后是可见性,最后是变量的名称。记住,如果不定义变量的可见性,变量将是public

单元可以是以下类型:

  • uint8
  • uint16
  • uint24
  • uint32
  • uint64
  • uint128
  • uint256

每个变量的数字表示uint的大小。一个uint8类型的变量将能够存储多达 256 个。所以,uint8变量的最大变量是256。如果你想存储数字 255,变量将正常工作,但是,如果你想存储数字256如下,那么变量将溢出,它将重置为零而不是256,因为它超过了该类型变量的容量:

uint8 public myNumber = 256;

当您试图存储一个值256时,该变量会重置,因为它从零开始,所以容量是计算出的数字减一。

当你试图存储另一个超过变量容量的数,比如300,会发生什么?然后,变量的值将是44。因此,输入以下内容:

uint8 public myNumber = 300;

它将变成以下内容:

uint8 public myNumber = 44;

请注意,您不能分配一个大于变量容量的值,因为在某些情况下,当您试图部署您的契约时,您会得到一个编译错误。当您有一个接收uint8的函数,但是用户输入了一个大于 255 的值时,就会发生溢出问题。

这个跟uint16是一回事,最大值 65536 - 1 。同样,uint24的最大值为 16777216 - 1uint32变量的最大值为 4294967296 - 1uint64变量的最大值为1844674407370955 e19-1uint128变量的最大值为3402823669209385 e38-1uint256变量的最大值为1157920892373163 e77-1

如您所见,最大数量增长非常快。这对于在处理大数字时避免溢出非常有用。

另一方面,你有下溢的问题。当您试图将一个负数存储到uint中时,就会发生这种情况。例如,尝试这样做:

uint8 public myNumber = -5;

您将得到以下内容:

uint8 public myNumber = 251;

这与溢出的原因相同;你将从零到这个变量所能容纳的最大值。

这些问题会导致严重的脆弱性。这就是为什么检查用户在函数中输入的值是否在可接受的范围内很重要。稍后您将看到如何使用名为require()的全局函数来验证函数的输入。

地址

在 Solidity 0.4.0 中,只有一种类型的地址。现在,我们有两种类型来定义以太坊地址是否应该付费。

一个地址包含以太坊中每个用户的账号。它是一段 42 个字符的十六进制文本,就像这样:

0xeF5781A2c04113e29bE5724ae6E30bC287610007

要在合同中创建一个address变量,您必须将其定义如下:

pragma solidity 0.5.0;
contract Example {
    address public myAddress = 0xeF5781A2c04113e29bE5724ae6E30bC287610007;
}

地址没有引号,因为它们不是文本字符串。在此版本的 Solidity 中,您必须定义地址类型,可以是以下类型之一:

  • 地址 payable : 可支付地址是 Solidity 0.5中引入的一种新型变量,允许地址在内部接收和存储以太。以前,所有的地址都是payable,现在只有那些明确标记为payable的地址才能接收或发送以太,并使用处理以太的功能,如.transfer().send()
  • 地址:不能收发以太的正常地址,防止用户收发以太。

您按如下方式定义payable地址:

address payable public myAddress;

当你想把以太网发送到那个地址时,有可支付地址是有用的。例如,假设用户 A 希望从存储在智能合同中的余额中获得 10 以太网。他们会做如下事情:

pragma solidity 0.5.0;
contract TransferExample {
    address payable public userAAddress;
    function transferFunds() public {
        userAAddress.transfer(10 ether);
    }
}

因此,用户 A 将从该智能合约中存储的资金中获得 10 乙醚。

地址的另一个重要方面是,您有时需要访问当前智能合约的地址,因为如您所知,智能合约内部可以包含以太。

要获取智能合约的地址,请使用以下代码:

address public myContractAddress = address(this);

这里,this是用来引用当时正在使用的活动智能合约的特殊关键字。但是因为它是智能合约的实例,所以您需要使用类型转换函数将该实例转换为地址,这实质上是获取这个智能合约的地址。

您还可以使用.balance功能访问该智能合约的余额,如下所示:

uint256 public myContractBalance = address(this).balance;

这将返回智能合约中的 wei 的数量,对于使用transfer()函数进行转账非常有用:

myUserAddress.transfer(address(this).balance);

那将会发送myUserAddress这个契约里面储存的所有乙醚。

您可以将可支付地址转换为普通地址,但不能反过来,因为可支付地址是一个带有附加功能的增强版本,不能轻易传递。

字符串和字节

字符串和字节包含单引号或双引号中的文本,如下所示:

string public myText = “This is a long text”;
bytes public myTextTwo = “This is another text”;

它们可以让你储存大约 1000 个单词,本质上是一样的。您可以有更小的字节变化,如bytes1bytes2bytes3,直到bytes32

现在,bytes32是一个有趣的变量类型,因为它允许您以一种非常紧凑和高效的方式存储大约 32 个字符的文本。它们在许多需要简短文本的情况下使用:

bytes32 public shortText = “Short text.”;

它们在许多其他高级用例中使用,例如检查字符串或字节的文本是否为空。例如,如果您有一个接收文本的函数,您可能希望确保文本不为空。你应该这么做:

function example(string memory myText) public {
 require(bytes(myText)[0] != 0);
}

不要担心函数的技术细节。如果您不知道或不记得它们,要检查字符串是否为空,您必须执行以下操作:

require(bytes(yourString)[0] != 0);

这告诉协定确保字符串的第一个字母不为空。这是检查空字符串的正确方法。我们对字节做同样的事情,但是没有转换成字节。

当你需要在以太坊的字符串中添加特殊字符时,可以使用它们。

结构

如果您熟悉 JavaScript,您可以将结构视为具有属性和值的对象。一个struct看起来类似如下:

struct Example {
    propertyOne;
};

枚举数

枚举是固定大小的列表,具有您定义的唯一名称。您可以将它们用作特定对象的自定义修饰符,或者在智能合约中保存特定状态。这对于控制 ico 的状态非常理想。

您将它们声明如下:

enum Trees { RedTree, BlueTree, GreenTree, YellowTree }

然后,创建enum变量:

Trees public myFavoriteTree = Trees.RedTree;

注意,您不必在enum声明的末尾添加分号,但是您必须为您刚刚创建的enum类型的变量添加分号。

布尔运算

布尔变量可以是truefalse:

bool public isValid = true;

数组

数组允许你在一个地方存储大量相同类型的变量。它们用作包含智能合约特定类型信息的列表,以便您可以有序地存储数据。可以通过简单的for循环获取它们的长度来访问它们。

您可以创建单元、字符串、结构、地址以及几乎任何其他类型的数组:

uint256[] public myNumbers;
string[] public myTexts;

您也可以使用以下关键字从数组中删除元素:

delete myTexts[2];

您还可以使用.push().pop()在动态调整大小的数组中添加或删除元素。

绘图

映射是一种特殊类型的变量,因为它们可以保存无限量的数据。这就像数组和结构的组合。您可以向其中添加一组类型的元素:

mapping(string => bool) public validStrings;

映射将信息存储为无限数组。它们的工作方式类似于 JavaScript 中的对象,每个键都有一个相关的值,可以随机访问。它们没有固定的长度,你也不能像数组一样得到它们的长度来循环它们的值。相反,您必须做的是保存映射的最新更新的键,并从那里开始。

您可以按如下方式设置映射值:

validStrings['example'] = true;

在我们的例子中,validStrings的所有值都将是false,直到您将它们设置为true

数据单元

在 Solidity 中,您可以选择定义变量的存储位置。您可以决定将它们存储在以下位置:

  • 这是一个永久的地方,写在区块链上,所以使用起来很贵
  • 内存:这是一个非永久的地方,变量只在智能合约运行期间保存
  • Calldata :这是存储msg对象数据信息的地方,一个专用于全局变量的地方

下面的代码就是一个例子:

uint256 memory myNumber;
string storage myText;

事件

事件是一种特殊类型的函数。它们的目的是记录区块链和操作的数据,以便日后检索。他们可以通过订阅,以便在新事件发生时几乎实时地接收更新。

本质上,您希望他们保留您的智能合约中正在发生的事情的注册表,以便稍后分析它们,从而修复错误并了解发生了什么,如果您需要以一种简单的方式阅读过去。

以下是如何在 Solidity 中声明智能合约内的事件:

pragma solidity 0.5.0
contract EventsExample {
    event LogUserAddress(address userAddress);
    function registerUser() public {
        emit LogUserAddress(msg.sender);
    }
}

在这个示例中,您可以看到事件是如何声明和发出的。当您声明您的事件时,您必须决定它将能够接收的参数;它们都是可选的,所以你可以省略它们。

当在函数内部发出事件时,必须确保它们是正确的类型。在声明中,可以为每个参数添加一个名称,也可以只保留类型,如下所示:

event LogUserAddress(address);

命名事件中的参数是一个很好的做法,可以帮助其他人理解每个参数的用途。

你也可以添加一个可选的关键字叫做indexed。它是事件参数的修饰符,允许您搜索特定事件的过去事件。将indexed参数视为数据库中可搜索的条目:

event LogUserAddress(address indexed userAddress);

注意,您必须命名为indexed的参数。稍后,您将看到如何检索这些事件,并使用 web3.js 搜索特定的事件。

修饰语

修饰符是一种特殊类型的函数,作为中间件在当前函数执行之前用来验证数据或执行某些东西。它们主要用于验证执行该功能的用户是否具有所需的权限,以及验证参数:

address public owner;
modifier onlyOwner() {
    require(msg.sender == owner, ‘You must be the owner');
    _;
}

function doSomething() public onlyOwner {}

如您所见,onlyOwner修饰符用于检查doSomething函数是由合同的所有者还是由另一个用户执行的。如果调用者是所有者,则执行函数,如果是外部地址,则契约将恢复,并抛出异常。

注意,require()函数是一个全局断言函数,用来验证它内部的条件是真还是假。如果没有,它将抛出,并停止执行智能协定。

_修饰符中的下划线语句用于指示函数代码将被执行的位置。有时,你想在修改器检查之前执行函数。下划线声明在修饰符中是必需的。还要注意,修饰符可以有可选的参数。如果不需要,可以按如下方式删除括号:

modifier onlyOwner { ... }

修饰符是非常强大的工具,每当您看到重复的代码对几个函数进行相同的验证时,您会经常用到它们。

在下一节中,您将看到函数为了可见性和支付可以采用的特殊修饰符的类型。

功能

Solidity 中的函数在语法上与 JavaScript 中的非常相似,但是它们有一些您必须了解的关键区别,例如您必须指定返回类型、函数的可见性以及应用于每个特定函数的修饰符(如果有的话)。语法如下:

function example() public returns(uint256) { }

函数和变量一样具有可见性,其中公共函数可以由外部用户、契约以及在契约本身中执行。外部功能只能由外部实体实现,而不能由契约本身实现。内部函数只能由包含协定执行。私有函数只能在当前协定内部执行,或者由继承的协定执行。

现在,一个函数可以有特殊的修饰符来决定它是什么类型的函数。这包括以下修饰符:

  • 视图:视图函数不修改状态变量,但是可以读取它们。请记住,状态变量是在契约开始时声明的,它们用于直接在区块链上存储信息。所以,如果你的函数没有修改任何状态变量,你必须把它标记为view
  • :纯函数的限制性更强。它适用于那些甚至不读取状态变量的函数。纯函数通常是在内部进行某种计算而不依赖外部数据的函数。这通常包括数学函数或格式化函数。

  • 应付:一个payable函数在执行时能够接收以太。它会将以太存储在合约中,因此创建系统来提取发送到智能合约的以太非常重要,否则资金将永远卡在里面。如果您的函数没有被标记为payable,当您在函数执行的同时发送 Ether 时,您将会收到一个错误,并且事务将会恢复。

它看起来是这样的:

string public myStateString = 'Hi';
function exampleOfView() public view returns(string memory) {
    return myStateString;
}

在该函数中,我们只是读取并返回myStateString状态变量,所以我们可以将其标记为view。注意,我们必须对字符串类型使用memory关键字,因为它们在内部是一种数组类型,就像每个单独字符的数组一样。

另一个例子如下:

function sumTwoNumbers(uint256 numberA, uint256 numberB) public pure returns(uint256) {
    uint256 result = numberA + numberB;
    return result;
}

这个pure函数只是简单地将两个数相加,并将结果返回给调用者。它不修改状态,也不读取状态变量。

这里有一个payable函数:

function receiveDonation() public payable {}

receiveDonation函数是空的,因为我们只需要接收以太。我们不需要做任何事情。

回退功能

这是一种没有名字的特殊类型的函数。每当有人对这个契约地址使用.send().transfer()函数时,它就会被执行,类似于默认函数。它通常在 ICOs 中用于接收以太,并返回所接收以太的指定数量的令牌。这使得任何人都可以购买令牌,而不必了解和部署契约实例,只需知道契约的地址。

它看起来是这样的:

function () external payable {}

回退函数必须被标记为external,以帮助人们理解它不应该在这个契约中被错误地执行。如果不添加payable修饰符,它将拒绝所有发送给它的事务。

我建议您使用remix.ethereum.org IDE 编写并尝试不同的函数,它会向您显示必须验证的错误和通知。这样,您将能够安全地编写自己的合同。

把衣服洗了

Vyper 是一种新的智能合约编程语言,语法类似于 Python。它是由 Vitalik 自己创建的,它是新的分散化应用程序的最有趣的选择之一,因为它提供了一种不同于传统 Solidity 智能合同的方法。

它的目标是成为一种简单的编程语言,在简单的基础上增加安全性,其中代码应该容易理解,即使是非开发人员也能理解。这就是语法如此简约的原因。他们还希望它成为一种编程语言,在这种语言中,编写有错误或易受攻击的代码变得越来越困难,这样开发人员就不会花费无数时间来分析每个应用程序的安全性,同时避免意外的默认漏洞。

这就是 Vyper 增加几个有趣功能的主要原因,例如:

  • 知道每次调用函数会花费多少汽油:精确地指出汽油的花费是很重要的,因为你希望用户能够精确地计算出他们每笔交易会投入多少乙醚。它节省了人们的钱,同时使程序可预测。
  • 自动漏洞检查:上溢、下溢、重入攻击和许多其他众所周知的漏洞在 Vyper 中自动修复,无需人工关注您的智能合约的每一个功能。

另一方面,他们删除了其他智能合约编程语言中的重要特征,例如可靠性:

  • 没有更多的修饰符:在 Vyper 中不允许使用修饰符,因为它们会使代码难以阅读,因为你必须在修饰符的定义和使用之间来回切换。此外,它们还可以通过意外执行代码而被恶意使用;例如,创建一个名为onlyOwner的修饰符,然后执行一个与其名字完全不相关的transfer()函数。
  • 没有汇编:汇编代码很难理解,即使对有经验的开发人员来说也是如此,因为你处理的是非常低级的函数,可能会产生误导。这意味着您将无法创建使用签名、状态通道和依赖于程序集的类似应用程序的智能协定。
  • 不再有递归函数:为了避免重入攻击,同时保证精确计算天然气成本,他们删除了递归功能,其中函数可以不确定地调用自己的次数。

一般来说,Vyper 是一种强大的语言,非常适合小型项目,并且不需要高级功能,比如汇编。您可以快速创建一个易于维护的智能契约,用户可以在几分钟内通过其简洁的语法和最少的代码理解它。

Vyper 举例

为了快速掌握这种令人兴奋的新语言,我们将通过一个简单的 smart 契约让您了解 Vyper 的全部复杂性。我们将在一个智能契约中看到所有类型的变量和函数。

继续创建一个新的example.vy文件。如你所见,Vyper 智能合约有.vy终止。在其中,键入以下代码;我们稍后将解释每个变量的含义以及如何使用它们。这只是一个快速练习,让您的编程人员熟悉 Vyper 是如何编写的。这段代码将是您熟悉 Vyper 语法的指南:

# Events
LogTransfer: event({from: indexed(address), to: indexed(address), amount: uint256})

# Custom units
units: {
    kg: "kilogram"
}

# Numbers
myPositiveInteger: uint256
myDecimalNumber: decimal
myInteger: int256

# Addresses
owner: address

# Strings
myName: bytes32
myLongArticle: bytes[1000]

# Booleans
isThisTrue: bool

# Mappings
todoList: map(uint256, bytes32)

# Structs
struct Client:
    name: bytes32
    age: uint256

myClients: Client[100]

# Timestamps
myBirthday: timestamp
expirationTime: timedelta

# Wei value
etherToSpend: wei_value

# Custom unit types
myKilo: uint256(kg)

# Public functions
@public
def subNumbers(first: int128, second: int128) -> int128:
    return first - second

# Payable functions
@public
@payable
def transferFunds(_from: address, to: address, amount: uint256):
    log.LogTransfer(_from, to, amount)

# Functions that update state
@public
def updateBoolean(result: bool):
    self.isThisTrue = result

# Constructor
@public
def __init__():
    self.owner = msg.sender

# Fallback function
@public
@payable
def __default__():
    self.myBirthday = now

以下是一些帮助您理解正在发生的事情的说明:

  • 事件必须在 Vyper 文件的顶部声明,并且必须放在花括号内,就像这样:({})
  • 无符号整数只能是正数,最大值是 2**256。不能有uint8或同等;所有的单位必须是uint256
  • 有符号整数,正常整数,可以是正的,也可以是负的,最大值为两边 2**128。它们只能是int128,所以你不能有更小的尺寸。
  • 小数的精度为 10 个小数位,这意味着您可以在点号后添加多达 10 个字符,例如,1.2394837662
  • 字符串可以是自定义大小的bytes32byte数组,比如bytes[2000]。注意,您没有string类型的变量,所以您的字符串在上传后将被存储为十六进制文本。此外,你不能有可变大小的字节,如bytes[],因为它们在计算天然气成本时会产生不确定性。
  • 映射必须用map()函数声明,它们可以用括号访问,例如todoList[3] = "Start something"
  • Timestamp是你生日等事件的固定日期,或是未来的某个特定时间。这主要用作日期容器。timedelta更像是日历中没有精确日期的计数器。例如,timedelta可以存储2 months,而时间戳可以存储January 1 2019,都是数字格式。
  • 卫值是用于在卫中存储乙醚的类型。
  • 自定义单元类型是您在文件顶部定义的个性化类型,然后您可以将其用于变量。它们必须转换为单位、整数或小数。
  • 函数可以是公共的,也可以是私有的。公共函数上必须有@public装饰器。函数的返回值用箭头符号->指定。

  • Payable 函数必须使用@payable装饰器,它们可以访问用msg.value发送的以太(如果有的话)。

  • 要更新函数内部的状态变量,必须在它们前面使用self.关键字,将它们更新为状态变量。在 Vyper 中,你不需要在参数名前面加下划线_,因为你可以很容易地在 state 中引用同名的变量,而在 Solidity 中则不能,所以你必须用下划线来区分它们。
  • 构造函数叫做__init__(),回退函数叫做__default__()

就是这样!几页就能掌握 Vyper 的最快方法。确保你把这份指南放在一个特别的地方,这样无论你什么时候写 Vyper 合同,你都可以省去几个小时的头痛和不舒服的时刻。

摘要

在这一章中,我们首先对以太坊的历史做了一个高层次的概述,以了解它的来源和发展方向。然后,我们转移到具体的主题,如 EEA,因为了解以太坊技术如何应用于不同的现实世界场景是很棒的。在那之后,我们讨论了许多关于以太坊区块链的细节的不同主题,以便从一个开发者的角度更好地理解它,因为我们将处理与它的区块链相关的所有方面。接下来,我们转到了关于智能合约的更多技术主题,因为它们是以太坊开发人员工作的核心,所以您可以清楚地看到它们是如何在大计划中实现的。最后,我们转到 Solidity 和 Vyper 的基本智能合约编程,以启动您对最流行的语言在现实世界中如何使用的理解,为未来的项目奠定坚实的基础,开始您成为以太坊开发大师的旅程。

如果你还不熟悉 Vyper,你现在应该能够使用在线编译器编写简单的合同,可以在:https://vyper.online/找到。确保自己练习本章中描述的功能,并在对所解释的概念有了直观的理解后继续阅读。

在下一章中,我们将深入探索以太坊架构,了解每个组件如何在基础层面上工作,以及区块链技术背后的主要驱动力。


我们一直在努力

apachecn/AiLearning

【布客】中文翻译组