當 Web3 被越來越多的提及和討論,對我來說,似乎它的原意和概念變得有些模糊。之後讀到 @felixmxu 老師分享的這篇文章,從技術角度由淺入深地闡述了 Web3 的架構,非技術背景也可以讀懂。

— 導讀 by Jiawei

原文:The Architecture of a Web 3.0 application

作者:Preethi Kasireddy

翻譯:Jiawei,已獲得作者授權

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 應用開啟了一個令人興奮的新方向。在這篇文章中,我們將關注以太坊給我們帶來了什麼。

是什麼讓 Web 3.0 與眾不同

與像 Medium 這樣的 Web 2.0 應用不同,Web 3.0 消除了「中間人」的存在。沒有存儲應用狀態的中心化數據庫,也沒有存放後端邏輯的中心化 Web 服務器。

相反,你可以利用區塊鏈去中心化的狀態機上搭建應用,該狀態機由互聯網上的匿名節點所維護。

所謂「狀態機」,我指的是維護給定程序的狀態,並且可以更新未來狀態的機器。區塊鏈作為一種狀態機,由一些起始狀態實例化,並且有非常嚴格的規則(例如共識)來定義狀態如何轉換。

更棒的是,沒有單一實體可以控制這個去中心化的狀態機—— 它由網絡中的每個人共同維護。

那麼後端服務器呢?在 Web 3.0 中,你可以編寫智能合約來定義應用的邏輯,並將它們部署到去中心化的狀態機上,而非 Medium 那樣。這意味著每個想要構建區塊鏈應用的人都會在這個共享狀態機上部署他們的代碼。

那麼前端呢?它幾乎保持不變,除了一些例外,我們將在後面討論。

下圖是它的架構:

再走近些

現在,讓我們更深入地探討一下這一切是如何實現的。

區塊鏈

以太坊經常被吹捧為「世界計算機」。因為它是一個全局可訪問的、確定性的狀態機,由 P2P 網絡節點所維護,且狀態更改需要遵循網絡中的共識原則。

所以,換句話說,它被設計成一個任何人都可以訪問和寫入的狀態機。因此,這台狀態機不由任何單一實體所擁有,而是由網絡中的所有人共同擁有。

還有一件事你需要要知道:數據只能被寫入以太坊—— 而不能更新現有的數據。

智能合約

智能合約是一個運行在以太坊上的程序,它定義了發生在區塊鏈上的狀態變化背後的邏輯。智能合同是用高級語言編寫的,比如 Solidity 或 Vyper。

因為智能合約代碼存儲在以太坊上,任何人都可以查看網絡上所有智能合約的應用邏輯。

以太坊虛擬機 EVM

接下來是以太坊虛擬機,它執行智能合約中所定義的邏輯,並處理狀態機上的狀態更改。

EVM 無法直接「讀懂」Solidity 和 Vyper 等用於編寫智能合約的高級語言。而需要將高級語言編譯成字節碼,這樣 EVM 就可以執行這些字節碼了。

前端

最後,正如我們前面提到的,前端定義了 UI 邏輯,但前端還會與智能合約中定義的應用邏輯進行交互。

前端和智能合約之間的交互比上圖中顯示的稍微複雜一些。接下來讓我們仔細看看。

前端代碼如何與以太坊上的智能合約進行通信

我們希望前端與智能合約進行交互,以便它們能夠調用函數。請記住,以太坊是一個去中心化的網絡。網絡中的每個節點都保存著狀態機上所有狀態的副本,包括與每個智能合約相關的代碼和數據。

當我們想要與區塊鏈上的數據和代碼進行交互時,我們需要與其中一個節點進行交互。這是因為任何節點都可以廣播交易請求。然後,礦工將執行這筆交易並將結果的狀態更改廣播到整個網絡。

廣播一筆新的交易有兩種方式:

  1. 自己搭建一個運行以太坊的節點
  2. 使用第三方服務提供的節點,比如 Infura、 Alchemy 和 Quicknode

如果使用第三方服務,就可以省掉自己運行全節點所帶來的麻煩。畢竟,在自己的服務器上設置一個新的以太坊節點可能需要幾天時間。(需要同步的數據量很大—— 甚至可能佔用比一台普通筆記本電腦還多的帶寬和存儲空間)

此外,隨著 DApp 的擴展,存儲整條鏈的成本也隨之上升,你需要添加更多的節點來擴展你的基礎設施。這就是為什麼當基礎設施變得更加複雜的時候,你需要全職的 DevOps 工程師。它們將幫助你維護基礎設施,以確保可靠的正常運行時間和快速響應時間。

綜上,避免這些麻煩是許多 DApps 選擇使用像 Infura 或 Alchemy 這樣的服務來管理他們的節點基礎設施的原因。當然,由於這會造成一個中心化的阻塞點,因此需要權衡利弊。但我們以後再討論它吧。

接下來,讓我們談談「提供商」(Provider)。當你需要與區塊鏈交互時(無論你是自己設置還是使用第三方服務的現有節點),你連接的節點通常被稱為 Provider。

每個以太坊客戶端(即 Provier)都實行 JSON-RPC 規範。這確保當前端應用想要與區塊鏈交互時,有一套統一的方法可以遵照。如果你需要了解 JSON-RPC 的入門知識:它是一個無狀態、輕量級的遠程過程調用(RPC)協議,定義了一些數據結構和處理規則。它與傳輸無關,因此這些概念可以在同一個過程中使用,通過 sockets、HTTP 或是許多不同的消息傳遞環境。它使用 JSON(RFC 4627)作為數據格式。

一旦通過 Provider 連接到區塊鏈,你就可以讀取存儲在區塊鏈上的狀態。但是如果你想寫入狀態,在提交交易到區塊鏈之前,還需要使用你的私鑰為交易簽名。

例如,假設我們有一個 DApp,讓用戶在區塊鏈上閱讀或發布博客文章。前端可能有一個按鈕,允許任何人查詢特定用戶寫的博客文章。(回想一下,從區塊鏈讀數據並不需要用戶對交易進行簽名)

然而,當用戶想要在區塊鏈上發布一個新帖子時,我們的 DApp 會要求用戶使用他們的私鑰對交易進行簽名,只有這樣 DApp 才會將交易轉發給區塊鏈。否則,節點將不會接受這筆交易。

交易簽名正是 Metamask 的用武之地。

Metamask 是一個工具,使應用輕鬆地處理密鑰管理和交易簽名。它非常簡單:Metamask 在瀏覽器中存儲用戶的私鑰,當前端需要用戶對交易進行簽名時,它會調用 Metamask。

Metamask 還提供與區塊鏈的連接(作為一個 Provider),它需要簽名交易,因此連接了 Infura 提供的節點。Metamask 既是 Provider,也是簽名者。🤯

區塊鏈中的存儲

當然,如果你在構建一個所有智能合約和數據都存儲在鏈上的應用,這種架構是可行的。但是任何一個在以太坊上開發過應用的人都知道,在區塊鏈上存儲雖然取用方便,但卻非常昂貴。

請記住,用戶每次需要添加新的數據到以太坊上時都需要支付費用。這是因為向去中心化的狀態機添加一個狀態會增加維護該狀態機的節點的成本。

如果你的 DApp 要求用戶為每筆需要新增狀態的交易支付一筆額外費用,顯然這並不是好的用戶體驗。解決這個問題的一種方法是,使用去中心化的鏈下存儲方案,如 IPFS 或 Swarm。

IPFS 是一個支持存取數據的分佈式文件系統。因此,IPFS 系統不是將數據存儲在中心化數據庫中,而是將數據分發並存儲在一個 P2P 網絡中。這樣,在需要的時候你可以很容易地找到它。

IPFS 還有一個叫做「Filecoin」的激勵層,它通過激勵機制使世界各地的節點來存儲和檢索這些數據。你可以使用一個 Provider,比如 Infura(提供了 IPFS 節點)或 Pinata(提供了易用的服務,你可以將你的文件「Pin」到 IPFS 上,然後獲取 IPFS 的哈希值,並將其存儲在區塊鏈上)

與之類似,Swarm 是一個去中心化的存儲網絡,但也有一個顯著的區別。Filecoin 是一個單獨的系統,而 Swarm 的激勵系統是內置的,通過在以太坊上的智能合約來實現數據的存儲和檢索。

這樣,在使用 IPFS 或 Swarm 後,我們應用的架構看起來會是這樣:

一些敏銳的讀者可能已經註意到,前端代碼是沒有存儲在區塊鏈上。我們可以在 AWS 上託管這些代碼,就像通常在 Web 2.0 中做的那樣。但這會給 DApp 帶來中心化的阻礙。如果 AWS 癱瘓了怎麼辦?如果它審查你的應用怎麼辦?

這就是為什麼,如果你想建立一個真正的 DApp,你可能會選擇將前端也託管在去中心化存儲解決方案上,比如 IPFS 或 Swarm。

所以現在你的應用架構看起來更像這樣:

區塊鏈上的查詢

到目前為止,我們已經討論瞭如何對交易進行簽名,然後發送交易來對區塊鏈進行寫入。但是從區塊鏈上的智能合約中讀取數據又該怎麼做呢?有兩種主要的方法可以實現這一點:

  1. 智能合約事件(Events)你可以使用 Web3.js 庫查詢和監聽智能合約事件。在每次觸發事件時指定調用一個回調函數。例如,如果你有這麼一個智能合約,它在每個區塊都會從 A 發送持續的付款流給 B,那麼每次向 B 付款時,你就可以發送一個事件。前端代碼可以監聽由智能合約所觸發的事件,並據此進行響應。
  2. The Graph 上述方法是有效的,但也有一些局限性。例如,如果你部署完一個智能合約,隨後才意識到需要發出的事件沒有被包含進去,該怎麼辦?不幸的是,你只能使用該事件和數據重新部署一個智能合約。此外,使用回調函數來處理各種 UI 邏輯也非常複雜。

這就是 The Graph 用武之地。

The Graph 是一個鏈下的索引方案,簡化了以太坊上的數據查詢。借助 The Graph,你可以定義哪些智能合約需要索引、哪些事件和函數調用需要監聽,可以規定如何將傳入的事件轉化為前端邏輯(或是使用 API 的程序)可處理的實體。它使用 GraphQL 作為查詢語言,這種語言深受前端工程師的喜愛:因為與傳統的 REST API 相比,它能表示更多的信息。

通過索引區塊鏈數據,The Graph 實現了鏈上數據查詢的低延遲。

現在,你的 DApp 架構看起來像這樣:

我們已經快討論完了,只剩一個主要的話題:擴容。

為你的 DApp 擴容

正如你可能已經聽說的那樣,以太坊並不具備可擴展性—— 至少現在並不。

以太坊平均 gas 價格
平均交易費用
平均區塊大小

很明顯的一個問題是,由於以太坊的高額 gas 費和飽和的區塊,在上面部署 DApp 會導致非常糟糕的用戶體驗。值得慶幸的是,一些解決方案正在開發中。

一個流行的擴容方案是 Polygon,一個 L2 擴容方案。與在主鏈上執行交易不同,Polygon 擁有處理和執行交易的「側鏈」。側鍊是一條與主鏈相連接的次級區塊鏈。每隔一段時間,側鏈就會將其近期區塊聚合在一起,並提交回主鏈。

其他 L2 解決方案還有 Optimistic Rollups 和 zkRollups。它們的想法是類似的:我們使用一個「Rollup」智能合約來對鏈下交易進行批量處理,然後定期將這些交易提交給主鏈。

L2 方案在鏈下執行交易(交易執行在鏈上需要花許多時間),只將交易數據存儲在鏈上。這實現了區塊鏈的擴容,因為我們不需要在鏈上執行每一筆交易。這也使得交易更快更便宜—— 並且在必要的時候仍可以與以太坊進行交互。

把所有這些都整合在一起!

如果這一切讓你感到頭暈目眩,那麼你並不孤單。整合所有這些工具無疑是複雜的,並且可能會導致痛苦的開發體驗。但不要擔心,我們開始看到一些新的開發框架,它們真正改善了開發者的體驗。

例如,Hardhat 是一個開發者框架,使得以太坊開發者更容易構建、部署和測試他們的智能合約。安全帽提供了「Hardhat Network」,開發人員可以使用該網絡將他們的智能合約部署到本地網絡上,而無需處理實時環境。更棒的是,它提供了一個很讚的插件生態系統,使開發更便利。Hardhat 還提供類似於 JavaScript 的 console.log () 功能,用於調試。

當然,這僅僅是個開始,我希望將來能夠看到更好的開發工具。

結論

大多數人花費了幾個月的時間來弄清楚區塊鍊是如何工作的,所以如果你是一個新的 DApp 開發人員,我希望這篇文章能為您節省一些時間。是時候開始 Build 了!

如果你對構建 Web 3.0 應用感興趣,那麼請註冊我們的下一批 DApp 開發訓練營,在這裡你將學習到如何在以太坊上構建和部署您你的第一個 DApp。

像往常一樣,如果你有任何問題或發現這篇文章的任何錯誤,歡迎評論!:)

免責聲明:作為區塊鏈信息平台,本站所發布文章僅代表作者及嘉賓個人觀點,與 Web3Caff 立場無關。文章內的信息僅供參考,均不構成任何投資建議及要約,並請您遵守所在國家或地區的相關法律法規。