Web 3.0 应用程序(或“DApps”)的架构与 Web 2.0 应用程序完全不同。
以 Medium 为例,它是一个简单的博客网站,允许用户发布自己的内容并与他人的内容进行交互。
作为一个 web 2.0 应用程序,它可能听起来很简单,但在 Medium 的架构中有很多东西来实现这样的效果:
首先,必须有一个地方来存储基本数据,例如用户、帖子、标签、评论、喜欢、等等。这需要不断更新的数据库。
其次,后端代码(用 Node.js、Java 或 Python 等语言编写)必须定义 Medium 的业务逻辑。例如,当新用户注册、发布新博客或评论其他人的博客时会发生什么?
第三,前端代码(通常用 JavaScript、HTML 和 CSS 编写)必须定义 Medium 的 UI 逻辑。例如,网站是什么样的,当用户与页面上的每个元素交互时会发生什么?
总而言之,当你在 Medium 上写一篇博文时,你会与它的前端进行交互,前端与后端进行交互,后端与数据库进行交互。所有这些代码都托管在中央服务器上,并通过互联网浏览器发送给用户。这是对当今大多数 Web 2.0 应用程序如何工作的很好的总结,如下:
但这一切都在改变。
区块链技术为 Web 3.0 应用开启了一个令人兴奋的新方向。在本文中,我们将重点关注以太坊区块链带来了什么。
与像 Medium 这样的 Web 2.0 应用程序不同,Web 3.0 消除了中间人。没有存储应用程序状态的集中式数据库,也没有后端逻辑驻留的集中式 Web 服务器。
相反,您可以利用区块链在由互联网上的匿名节点维护的去中心的状态机上构建应用程序。
我所说的“状态机”,是指维护某些给定程序状态和该机器上允许的未来状态的机器。区块链是使用某些创世状态实例化的状态机,并且具有非常严格的规则(即共识)来定义该状态如何转换。
更好的是,没有单个实体控制这个去中性的状态机——它由网络中的每个人共同维护。
那么后端服务器呢?在 Web 3.0 中,你可以编写智能合约来定义应用程序的逻辑并将它们部署到分散的状态机上,而不是考虑如何控制 Medium 的后端。这意味着每个想要构建区块链应用程序的人都将他们的代码部署在这个共享状态机上(即区块链)。
前端呢?它几乎保持不变,但有一些例外,我们将在后面介绍。
这是架构的样子:
现在,让我们更深入地探讨是什么让这些过程成为可能。
区块链
以太坊区块链经常被称为“世界计算机”。那是因为它是一个全局可访问的确定性状态机,由对等节点网络维护。此状态机上的状态更改由网络中的对等方遵循的共识规则控制。
因此,换句话说,它实际上被设计为世界上任何人都可以访问和写入的状态机。因此,这台机器不属于任何单个实体——而是由网络中的每个人共同拥有。
还有一件事要知道:数据一旦被写入以太坊区块链——你永远无法篡改现有数据。
智能合约
智能合约是一个运行在以太坊区块链上的程序,它定义了区块链上发生的状态变化背后的逻辑。智能合约是用高级语言编写的,例如 Solidity 或 Vyper。
由于智能合约代码存储在以太坊区块链上,任何人都可以检查网络上所有智能合约的应用逻辑。
以太坊虚拟机(EVM)
接下来,你有以太坊虚拟机,它执行智能合约中定义的逻辑并处理在这个全局可访问状态机上发生的状态变化。
EVM 不理解用于编写智能合约的 Solidity 和 Vyper 等高级语言。相反,您必须将高级语言编译成字节码,然后 EVM 才能执行。
前端
最后,我们有前端。正如我们之前提到的,它定义了 UI 逻辑,但前端也与智能合约中定义的应用程序逻辑进行通信。
前端和智能合约之间的通信比上图中显示的要复杂一些。接下来让我们仔细看看这个。
我们希望我们的前端与我们的智能合约进行通信,以便他们可以调用函数,但请记住,以太坊是一个去中心化的网络。以太坊网络中的每个节点都保存了以太坊状态机上所有状态的副本,包括与每个智能合约相关的代码和数据。
当我们想要与区块链上的数据和代码进行交互时,我们需要与这些节点之一进行交互。这是因为任何节点都可以广播要在 EVM 上执行的事务的请求。然后,矿工将执行交易并将结果状态更改传播到网络的其余部分。
有两种方法可以广播一个新的交易:
如果您使用第三方服务,则不必自己处理运行完整节点的所有麻烦。毕竟,在您自己的服务器上设置新的以太坊节点可能需要数天时间。(有大量数据需要同步——它甚至会占用比普通笔记本电脑更多的带宽和存储空间。)
此外,存储完整以太坊区块链的成本随着你的 DApp 的扩展而增加,你需要添加更多节点扩展您的基础设施。这就是为什么随着您的基础架构变得更加复杂,您将需要全职 DevOps 工程师。他们将帮助您维护基础设施,以确保可靠的正常运行时间和快速的响应时间。
总而言之,避免这些令人头疼的问题就是为什么许多 DApp 选择使用 Infura 或 Alchemy 之类的服务来为他们管理节点基础设施的原因。当然,有一个权衡,因为这会创建一个集中的阻塞点,即Infura和Alchemy过度集中。
继续,让我们谈谈提供者(Provider)。当您需要与区块链交互时连接的节点(无论是您自己设置还是使用来自第三方服务的现有节点)通常被称为“Provider”。
每个以太坊客户端(即提供者Provider)都实现了 JSON-RPC 规范。这确保了前端应用程序想要与区块链交互时有一组统一的方法。关于 JSON-RPC 的简单理解,它就是一种无状态、轻量级的远程过程调用 (RPC) 协议,它定义了多个数据结构及其处理规则。它与传输无关,因此可以在同一进程中、通过套接字、通过 HTTP 或在许多不同的消息传递环境中使用这些概念。它使用 JSON (RFC 4627) 作为数据格式。
一旦您通过提供商连接到区块链,您就可以读取存储在区块链上的状态。但是,如果您想写入状态,在将交易提交到区块链之前,您还需要做一件事——使用您的私钥对交易进行“签名”。
例如,假设我们有一个 DApp,允许用户阅读或发布博客文章到区块链。您可能在前端有一个按钮,允许任何人查询特定用户撰写的博客文章。(回想一下,从区块链读取数据不需要用户签署交易。)
然而,当用户想要在链上发布新帖子时,我们的 DApp 会要求用户使用他们的私钥“签署”交易——只有这样 DApp 才会将交易发生到区块链。否则,节点不会接受交易。
这种交易的“签名”是Metamask通常出现的地方。
Metamask 是一种工具,可让应用程序轻松处理密钥管理和交易签名。非常简单:Metamask 将用户的私钥存储在浏览器中,每当前端需要用户签署交易时,它都会调用 Metamask。
Metamask 还提供与区块链的连接(作为“提供者-Provider”),因为它已经可以与 Infura 提供的节点建立连接,因为它需要它来签署交易。这样,Metamask 既是提供者又是签名者。🤯
当然,如果您正在构建一个应用程序,其中所有智能合约和数据都完全存在于以太坊区块链上,那么这种架构是有意义的。但是任何在以太坊上构建应用程序的人都知道,将所有内容存储在区块链上会变得非常昂贵,非常快。
请记住,使用以太坊,用户每次向区块链添加新数据时都要付费。这是因为向分散状态机添加状态会增加维护该状态机的节点的成本。
要求用户在每次交易需要添加新状态时为使用您的 DApp 支付额外费用并不是最好的用户体验。解决这个问题的一种方法是使用去中心化的链下存储解决方案,如IPFS或Swarm。
IPFS 是一个分布式文件系统,用于存储和访问数据。因此,IPFS 系统不是将数据存储在集中式数据库中,而是在对等网络中分发和存储数据。这使您可以在需要时轻松检索它。
IPFS 还有一个称为“Filecoin”的激励层。该层激励世界各地的节点存储和检索这些数据。您可以使用像 Infura(为您提供 IPFS 节点)或 Pinata(提供易于使用的服务,您可以将文件“固定”到 IPFS 并获取 IPFS 哈希并将其存储在区块链上)等提供商.
Swarm 的相似之处在于它是一个去中心化的存储网络,但有一个显着的区别。虽然 Filecoin 是一个单独的系统,但 Swarm 的激励系统是内置的,并通过以太坊区块链上的智能合约执行,用于存储和检索数据。
所以现在,使用 IPFS 或 Swarm,我们的应用程序架构如下所示:
细心的读者可能还注意到下图中的前端代码没有存储在区块链上。我们可以在 AWS 上托管此代码,就像我们通常在 Web 2.0 中所做的那样,但这会为您的 DApp 创建一个集中化的阻塞点。如果 AWS 出现故障怎么办?如果它审查您的应用程序怎么办?
这就是为什么,如果您想构建一个真正去中心化的应用程序,您可能会选择将前端托管在去中心化存储解决方案上,例如 IPFS 或 Swarm。
所以现在你的应用程序架构看起来更像这样:
到目前为止,我们已经讨论了如何通过签署交易然后将它们发送到区块链来写入区块链。但是如何从区块链上的智能合约中读取数据呢?有两种主要方法可以做到这一点:
智能合约事件(Event)
您可以使用 Web3.js 库来查询和侦听智能合约事件。您可以侦听特定事件并在每次触发事件时指定回调。例如,如果你有一个智能合约,它在每个区块向人 B 发送一个连续的支付流,那么你可以在每次向人 B 进行新的支付时发出一个事件。你的前端代码可以监听被触发的事件通过智能合约并基于它执行特定操作。
The Graph
上述方法有效,但有一些局限性。例如,如果您部署了一个智能合约,后来意识到您需要发出一个您最初没有包含的事件,该怎么办?不幸的是,您必须重新部署具有该事件和数据的新智能合约。此外,使用回调来处理各种 UI 逻辑很快就会变得非常复杂。
这就是“The Graph”的用武之地。
Graph 是一种链下索引解决方案,可以更轻松地查询以太坊区块链上的数据。Graph 允许您定义要索引的智能合约、要侦听的事件和函数调用,以及如何将传入事件转换为前端逻辑(或使用 API 的任何内容)可以使用的实体。它使用 GraphQL 作为查询语言,许多前端工程师喜欢这种语言,因为与传统的 REST API 相比,它的表现力很强。
通过索引区块链数据,The Graph 让我们可以在我们的应用程序逻辑中以低延迟查询链上数据。
现在,您的 DApp 架构如下所示:
Graph的介绍我们快完成了,但我们还剩下一个主要主题: 拓展。
您可能听说过,以太坊无法扩展——至少目前还没有。
显然,我们这里有问题。在以太坊上以高昂的 gas 费用和完整的区块构建 DApp 会导致非常糟糕的用户体验。值得庆幸的是,有一些解决方案正在开发中。
一种流行的拓展解决方案是Polygon,一种 L2 拓展解决方案。Polygon 没有在主区块链上执行交易,而是拥有处理和执行交易的“侧链”。侧链是与主链接口的二级区块链。侧链每隔一段时间就会将其最近区块的聚合提交回主链。
L2 解决方案的其他示例是Optimistic Rollups 和 zkRollups。这里的想法是相似的:我们使用“汇总”智能合约在链外批量交易,然后定期将这些交易提交到主链。
L2 解决方案在链外执行交易(即慢速部分),仅将交易数据存储在链上。这让我们可以扩展区块链,因为我们不必在链上执行每一笔交易。这也使交易更快、更便宜——并且在必要时他们仍然可以与主要的以太坊区块链进行通信。
如果所有这些都让您头晕目眩,那么您并不孤单。将所有这些工具拼凑在一起很复杂,可能会给开发人员带来痛苦的体验。但别担心——我们开始看到新的开发者框架,它们真正改善了开发者的体验。
例如,Hardhat是一个开发人员框架,使以太坊开发人员可以更轻松地构建、部署和测试他们的智能合约。Hardhat提供了“Hardhat Network”,开发人员可以使用它来将他们的智能合约部署到本地网络上——而无需处理实时环境。更好的是,它提供了一个很棒的插件生态系统,使开发人员的生活更加轻松。Hardhat 还提供了 console.log() 功能,类似于 javascript,用于调试目的。
当然,这只是开始。我希望我们在未来继续看到更好的开发人员工具。
大多数人会花费几个月的时间来弄清楚工具链是如何工作的,所以如果你是一个新的 DApp 开发人员,希望这篇文章可以为你节省一些时间。是时候开始建造了!
如果您对构建 Web 3.0 应用程序感兴趣,请关注我们的推特 @AntCaveClub,您将学习如何深度参与更多的Web 3.0 应用程序。