大家對于區塊鏈、智能合約、IPFS、錢包、節點等這些名詞都不陌生,也大概明白他們都是做什么的,然而他們是如何聯動起來服務于 Web3.0 去中心化應用的搭建的呢?
展現在我們眼前的僅僅是應用的前端,我們很難窺探到應用背后究竟是如何實現的。應用架構中的每一個組件都決定著應用的底層屬性,若想真的理解 Web2.0 與 Web3.0 應用之間的本質差異,我們需要從應用的架構入手,
本文作者 Preethi Kasireddy 曾在 2013 至 2015 年擔任 a16z 合伙人,隨后在 2016 年入職 Coinbase 擔任軟體工程師并在同期以智能合約工程師身份活躍在以太坊網路中。本文從應用框架維度對 Web3.0 應用進行了深度解析。律動 BlockBeats 對全文進行了翻譯:
Web 3.0 的應用架構
Web 3.0 應用程式(或”DApps”)的架構與 Web 2.0 應用程式完全不同。
以 Medium,一個簡單的部落格網站為例子。Medium 允許用戶發布自己的內容并與其他人的內容進行交互,
Medium 是一個 web 2.0 應用程式,架構聽起來很簡單。但實際上在 Medium 的架構中,需要大量工作使這一切成為可能,
首先,Medium 需要一個地方來存儲像用戶,帖子,標簽,評論,贊之類的基礎數據。這些工作需要不斷地更新資料庫,
其次,像 Node.js, Java, or Python 后端代碼語言決定了 medium 的商業邏輯。例如,當新用戶注冊、發布新部落格或在他人部落格上發表評論時會發生什么情況?
還有,像 JavaScript, HTML, and CSS 之類的前端代碼語言決定了 Medium 的 UI 邏輯。例如,網站是什么樣子的,當用戶與頁面上的每個元素交互時會發生什么?
當你在 Medium 上寫部落格時,這些所有的東西會整合起來聯動。你與它的前端互動,前端和后端交互,后端再與它的資料庫交互,所有這些代碼都托管在中心化服務器上,并通過互聯網瀏覽器發送給用戶。這是對當今大多數 Web 2.0 應用程式的工作原理的一個高度總結。
現在這些全變了,
區塊鏈技術為 Web 3.0 應用開啟了令人興奮的新方向,在本文中,我們將重點討論以太坊帶來的改變,
是什么讓 Web 3.0 如此不同?
與 Medium 這類 web2.0 程式不同是,Web3.0 去除了中間層。這中間沒有存儲應用程式狀態的中心化資料庫,也沒有中心化網站服務器用于存儲后端邏輯。
你可以利用區塊鏈構建程式在去中心化的狀態機構建應用程式,這一系統是由互聯網上的匿名節點在維護。
狀態機是指一種可維持程式狀態并允許新的狀態寫入的「機器」,區塊鏈就是一種虛擬機,其以創世狀態作為示例,隨后狀態根據具體規則進行轉換,
更重要的是,沒有單一實體控制這個去中心化的狀態機,它由網路中的每個人共同維護,
在 Web 3.0 中,你可以編寫智能合約來定義應用程式的邏輯并將它們部署到去中心化的狀態機上,這意味著每個想要構建區塊鏈應用程式的人都在這個共享狀態機上部署他們的代碼。這與 Medium 的后端十分不同。
Web3.0 的前端和 Web2.0 的前端基本相同,有一些特例我們將在后文中講解。
下圖是 Web3.0 的架構
深度解析
那么,讓我們更深入地了解是什么讓這一切成為可能
1)區塊鏈
以太坊是全球都可以參與維護的,點對點具有確定性的狀態機,這讓以太坊經常被吹捧為「世界電腦」。狀態機上的狀態更改由網路中的遵循共識規則的節點控制。
換句話說,它實際上被設計為世界上任何人都可以訪問和寫入的狀態機,因此,這臺機器不屬于任何單一實體,而是由網路中的每個人共同擁有,
還有一件事要知道:數據只能寫入以太坊區塊鏈,你永遠無法更新現有數據。
2)智能合約
智能合約是運行在以太坊區塊鏈上的程式,用于定義區塊鏈上發生的狀態變化背后的邏輯。智能合約通常都用 Solidity 或者 Vyper 這類的高級語言編寫。
由于智能合約代碼存儲在以太坊區塊鏈上,任何人都可以檢查網路上所有智能合約的應用邏輯,
3)以太坊虛擬機(EVM)
虛擬機是用來執行智能合約中定義的邏輯并處理狀態機上發生的狀態變化。
以太坊虛擬機不理解像 Solidity 或 Vyper 的這種高階語言。你需要將這些高階語言編譯成以太坊虛擬機可以執行的字節碼。
4)前端
正如我們之前提到的,前端定義了 UI 邏輯,但前端也與智能合約中定義的應用程式邏輯進行交互。
前端和智能合約之間的交互比上圖中顯示的要復雜一些,接下來讓我們詳細說明一下這部分。
以太坊上前端代碼如何與智能合約進行交互
我們想讓前端和智能合約交互時能夠觸發程式的特定功能,但不要忘記,以太坊是一個去中心化的網路,所有每一個以太坊的節點都需要保存一份以太坊狀態機上所有狀態的副本,這個副本包括所有與智能合約相關的代碼和數據。
當我們想和區塊鏈上的數據和代碼進行交互的時候,我們要和區塊鏈中的某一節點進行通信,因為任何節點都可以廣播在以太坊虛擬機上進行交易的請求,在這之后礦工將執行交易并將結果狀態更改廣播到網路的其他節點上,
有兩種方式廣播新的交易:
1. 自己設立一個運行以太坊程式的節點
2. 使用 Infura 或者 Alchemy 第三方提供的節點
使用第三方節點,能讓你免去自己運行全節點所帶來的麻煩,因為有大量數據需要同步的關系,設立一個以太坊的節點通常需要好幾天的時間,并且同步所需的帶寬和存儲容量超過了一般筆記本電腦的處理能力,所以你同時需要一臺性能強勁的設備。
此外,存儲完整以太坊區塊鏈的成本隨著 DApp 的擴容而增加,你需要添加更多節點來擴張你的基礎設施。當你的基礎設施變得復雜到一定程度后,你將需要一個全職 DevOps 工程師(可編程運維工程師),他們將幫助你維護基礎設施,以確保你的基礎設施有著可靠的正常運行時間和快速的響應時間。
綜上所述,為了避免這些麻煩,許多 DApp 選擇使用 Infura 或 Alchemy 之類的服務商來管理他們的節點。但凡事有利有弊,這也造成了一個中心化的阻塞點,但我們先不談這個問題。
不管是你自己設置還是使用來自第三方服務的節點,這些節點通常被稱為「提供商」(Providers),我們接下來好好說說這些「提供商」,
每個以太坊客戶端(提供者)實行 JSON-RPC 規范。這確保了前端應用程式想要與區塊鏈交互時有一組統一的方法,JSON-RPC 是一種無狀態、輕量級的遠程應用程式調用 (RPC) 協議,它定義了多個數據結構及其處理規則。因為它具有傳輸不可知性(transport-agnostic),因此這些概念可在同一進程中被使用、穿梭在 sockets、 HTTP 或許多不同的消息傳遞環境中,它使用 JSON (RFC 4627) 作為數據格式,
當你通過提供商連接到區塊鏈后,你就可以讀取存儲在區塊鏈上的狀態,但是,如果你想寫入狀態,你需要在將交易提交到區塊鏈之前,使用你的私鑰對交易進行「簽名」。
舉個例子,假設我們運行了一個 DApp,它可以讓用戶閱讀或發布部落格文章到區塊鏈。你在前端設置了一個按鈕,允許任何人查詢特定用戶撰寫的部落格文章。但要記得,閱讀區塊鏈中的文章并不需要用戶對交易進行簽名,
但是,當用戶想要在區塊鏈上發布新的文章時,DApp 會要求用戶使用他們的私鑰「簽署」交易,只有這樣 DApp 才會將交易傳播到區塊鏈上,否則節點不會接受這筆交易,
簽署交易這個環節通常是需要使用 Metamask(小狐貍)的時候,
Metamask 是一種工具,可讓應用程式輕松處理密鑰管理和交易簽名。它原理非常簡單,Metamask 將用戶的私鑰存儲在瀏覽器中,每當前端需要用戶簽署交易時,它都會調用 Metamask。
Metamask 也會作為提供商與區塊鏈進行鏈接,因為 Metamask 需要簽署交易,所以它與 Infura 提供的節點建立了連接。在某種程度上說,Metamask 既是提供者又是簽名者。
在區塊鏈上存儲
當然,如果你所搭建的應用中所有智能合約和數據都存儲在以太坊上的話,那么這種架構還算合理,然而,在以太坊上搭建過應用程式的人都知道,在區塊鏈上存儲雖然快捷,但價格也不菲。
我們要明白,用戶每次在以太坊上添加新數據都要付費。這是因為去中心化的狀態機是由節點來維護的,而在狀態機上每新增一個狀態,都會增加節點的成本。
如果你的 DApp 每次在用戶交易需要添加新狀態時,都要求他們支付額外費用的話,那么用戶體驗是很差的,不過,使用去中心化鏈下存儲方案,如 IPFS 或 Swarm,便可以解決這一問題。
IPFS 是一個用于存儲與訪問數據的分布式文件系統。也就是說,IPFS 系統并不是將數據存儲在一個中心化的資料庫中,而是將數據分布式存儲在 P2P 網路中,讓你隨時可以對數據進行檢索,
「Filecoin」是 IPFS 的激勵層,其作用是激勵世界各地的節點來存儲和檢索這些數據,你可以使用像 Infura 或 Pinata 這樣的提供商,因為 Infura 可以為你提供 IPFS 節點,而 Pinata 則可以讓你將文件在 IPFS 中「定位」,繼而得到 IPFS 的哈希值并將其存儲在區塊鏈上,且整個操作過程相當簡單,
Swarm 是一個去中心化的存儲網路,和 IPFS 有很多相似之處,但二者也有一個明顯區別,那就是,Filecoin 系統相對獨立,Swarm 的激勵系統是內置的,由以太坊上的智能合約來執行,用于數據的存儲與檢索,
所以現在,有了 IPFS 或 Swarm,我們的應用架構會是這樣的:
在下圖當中,機智的你可能會注意到,前端代碼并沒有存儲在區塊鏈上。其實我們完全可以和我們在 Web 2.0 中所做的一樣,將代碼存儲在 AWS 上面,但這樣做也意味著你的 DApp 會受到來自中心化的制約,比方說,如果 AWS 癱瘓了怎么辦?如果它對你的應用程式進行審查又該怎么辦?
這也就是為什么,如果你想搭建一個真正的去中心化應用程式,你會選擇像 IPFS 或 Swarm 這樣的去中心化存儲方案來儲存前端了。
所以現在你的應用架構會變成這樣:
在區塊鏈上進行查詢
到目前為止,我們已經探討了如何通過簽署交易并將它們發送到區塊鏈上來完成交易的寫入。但從區塊鏈上的智能合約中讀取數據又該如何操作呢?主要有以下兩種方式:
1)智能合約事件
你可以利用 Web3.js 庫來查詢和監聽智能合約事件。你也可以使用 Web3.js 監聽特定事件,并指定一個回調函數在每次事件觸發時進行調用,比如說,現在假設有一個智能合約可以在每個區塊中的發送者與接收者之間發送連續支付流,那么每次向接收者支付款項時,你都可以發出一個智能合約事件,前端代碼可以監聽由智能合約所觸發的事件,并據此采取相應行動,
2)The Graph
上述方法的確可行,但它同時也有一定的不足。比如說,你可能在智能合約部署完成后才發現,自己要發送的事件并沒有包含在合約當中,這該如何是好?不幸的是,你只能重新部署一個新的智能合約,并將該事件與相關數據放入新的合約當中。不僅如此,回調函數也很難處理不同的 UI 邏輯,
這時就該讓「The Graph」上場了。
The Graph 是一個鏈下數據索引方案,可以方便人們在以太坊上查詢數據。在 The Graph 中,你既可以定義哪些智能合約需要索引、哪些事件與函數調用需要監聽,也可以規定如何將傳入的事件轉化為前端邏輯(或任何正使用 API 的程式)可處理的實體,它使用 GraphQL 作為查詢語言,這種語言深受前端工程師的喜愛,因為與傳統的 REST API 相比,它能傳達更多資訊,
通過索引區塊鏈數據,The Graph 可以讓我們在應用邏輯中查詢鏈上數據,并且幾乎不會出現延遲的情況。
現在,你的 DApp 架構大概是這樣:
現在只剩下最后一個重要問題:擴容,
DApp 的擴容
你可能已經聽說了,以太坊不具備可擴展性,至少目前還沒有,
以太坊 Gas 平均價格
平均交易費用
平均區塊規模
顯然,問題在于,以太坊上 Gas 費用高昂且區塊幾近飽和,在它上面搭建 DApp 會給用戶帶來非常不好的體驗。不過值得慶幸的是,一些相關方案正在開發當中,
Polygon 便是一個很受歡迎的 L2 擴容方案,在 Polygon 中,交易的處理與執行是由「側鏈」而非主鏈來完成的,這些側鏈是與主鏈相連的二級區塊鏈。每隔一段時間,側鏈就會將其最近的區塊聚合起來提交給主鏈。
同樣,Optimistic Rollup 和 zkRollup 也屬于 L2 方案,工作原理也都類似:他們用「Rollup」智能合約在鏈下將大量交易進行捆綁,然后定期將這些交易提交給主鏈,
我們需要知道的是:L2 方案是將交易的執行(即速度較慢的部分)放在鏈下進行,而在鏈上只儲存交易數據。這樣一來,區塊鏈就能得以擴容,因為我們不用再在鏈上執行每筆交易了。同時,這也讓交易進程加快、成本降低,而且在必要時,L2 方案還可以與以太坊主鏈進行通信。
全貌
如果到此你感覺頭暈目眩、迷惑不解,也屬于正常現象,因為將所有這些工具整合在一起本來就十分復雜,容易讓開發者感到焦頭爛額,但是不用擔心,開發框架的不斷問世將會切實提升開發者的工作體驗,
比如說,Hardhat 就是一個能方便以太坊開發者搭建、部署并測試智能合約的開發框架,Hardhat 內置了「Hardhat 網路」,開發者可以用此網路將智能合約部署到本地網路上,而無需處理實時環境。不僅如此,它還搭載了一個強大的插件生態系統,可以為開發者提供更大的便利。同時,Hardhat 還具備 console.log() 功能,和 javascript 一樣可以用于調試,
當然,這僅僅只是開始,我希望開發者工具在未來能有更好的發展,
總結
很多人花了幾個月的時間才搞清楚工具型區塊鏈是什么,所以如果你是一個入門級的 DApp 開發者,那么我希望這篇文章能為你省去部分時間。既然如此,那就開始 DApp 的搭建吧!
如果你對搭建 Web 3.0 應用程式感興趣,那么就請報名參加我們下一期的以太坊開發訓練營(Ethereum bootcamp),在那里你將學習如何在以太坊上搭建并部署你的首個 DApp,
像往常一樣,如果你有任何問題或在這篇文章中發現任何錯誤,歡迎在評論區中和我交流!