JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

運行節點:全節點、封存節點與輕用戶端

節點是你親手從第一性原理重建出來、屬於你自己的一份真相。本篇帶你分清全節點、封存節點與輕用戶端的差異、各自如何同步,以及為何「自己跑一個節點」正是去信任的根基。

以太坊「當機」的那一天——其實它根本沒停

2020 年 11 月 11 日,全世界的 MetaMask 錢包餘額突然一片空白。幣安暫停了以太坊提幣。區塊瀏覽器停擺。對數百萬使用者來說,看起來就像以太坊本身崩潰了。但它沒有。一個潛伏的共識漏洞——早已在 Geth v1.9.17 悄悄修掉,卻在許多機器上沒被升級——在主網上被觸發了,於是每一台仍跑著舊軟體的節點都分岔到一條死掉的鏈上。其中一台機器屬於 Infura:那個 MetaMask、幣安以及一長串交易所都默默依賴的託管端點。當 Infura 眼中的鏈壞了,他們眼中的鏈也跟著壞了。與此同時,真正的以太坊網路依舊每約十二秒就產出一個有效區塊,一拍都沒漏。完全沒察覺到這場「當機」的人,正是那些自己跑著節點的人。

這個故事正是這一階存在的全部理由。一條區塊鏈的「去信任」程度,取決於用來檢驗它的軟體。比特幣與以太坊的設計哲學濃縮成一句話——別信任,要驗證——而節點就是那個負責驗證的東西。它不是一台你「連上去」的伺服器,而是一支程式:它從原始區塊出發、獨立重新推導出整條鏈的全部狀態,自己套用每一條規則,不相信任何人給的摘要。這份獨立驗證,正是無需信任這個詞真正的意思。

全節點:把現實重新執行一遍

全節點是預設且最正統的參與者。對於收到的每一個區塊,它不會對區塊產生者的任何說法照單全收。它會把區塊裡的每一筆交易重新丟進狀態轉移函式執行一遍、重新算出結果的狀態根,再核對自己算出來的根是否與區塊標頭裡寫的那個一致。它重新檢查每一個簽章、每一個 nonce、每一行 gas 帳。如果某個驗證者想偷偷塞進一筆無效交易——憑空鑄幣、花掉別人的餘額——你的全節點就只會把這個區塊拒絕掉。沒有上訴,沒有覆寫。這正是為什麼一個 51% 攻擊者可以重排或審查交易,卻依然無法讓你的節點接受一個無效狀態:規則是在本地、在你的機器上強制執行的。

全節點實際儲存什麼,比一般人想像的更微妙。它保有當前世界狀態——每個帳戶餘額、合約與儲存槽,以 Merkle-Patricia 樹組織起來——再加上足夠的近期區塊歷史,用來服務鄰居節點並處理短暫的重組。它保留的,是每一個中間的歷史狀態;預設情況下,它會修剪掉那些不再需要的舊狀態樹。以 2020 年代中期的概略數字來說,一個用 snap 同步的 Geth 全節點大約落在 1.2 TB 並持續成長;像 Erigon 或 Reth 這類更精簡的用戶端,靠著扁平的鍵值佈局把它壓得更小。重點是:「全」指的是完整驗證,而不是把所有東西永遠留著

# Two ways to run the same chain. Note the --syncmode and --gcmode flags.

# FULL node (default): validate everything, prune old state.
#   ~1.2 TB on an NVMe SSD, syncs in hours via snap sync.
geth --syncmode snap --datadir /data/eth

# ARCHIVE node: keep EVERY historical state. Disk-hungry, slow.
#   15+ TB on Geth, syncs over days/weeks (it replays from genesis).
geth --syncmode full --gcmode archive --datadir /data/eth-archive
同一個用戶端,端看它是否修剪(gcmode),就成了全節點或封存節點。

這也正是不可竄改性從一句口號,變成你親自驗證過的事實的地方。你相信這條鏈無法被竄改,不是因為哪篇部落格這麼說,而是因為你的節點一個區塊接一個區塊、一路往回,重新算過那些雜湊鏈結與狀態根並確認無誤。

封存節點:記住每一個昨天

封存節點是一個永不修剪的全節點。它保留完整的歷史狀態——第 4,000,000 個區塊當下、第 12,965,000 個區塊當下、有史以來每一個區塊當下,那一刻精確的世界狀態。這讓它能回答一般全節點答不出的問題:「這個帳戶 800 天前的餘額是多少?」,或執行一次完整的 `debug_traceTransaction`,把一筆好幾年前的交易逐個操作碼重跑一遍。這正是 Etherscan 這類區塊瀏覽器、鏈上分析、稅務工具,以及我們兩篇之後會遇到的索引器背後的引擎——任何需要透過 JSON-RPC 介面讀取深層歷史的東西。

代價是極其驚人的儲存量。一個 Geth 封存節點輕鬆超過 15 TB 且持續攀升;Erigon 的扁平儲存設計把同一份資料壓到大約數 TB,這也是多數封存節點營運者選它的原因。誠實的結論是:幾乎沒有人需要封存節點。如果你的目標是驗證自己的交易、主權地使用自己的錢包,一個經過修剪的全節點就夠了——而且便宜得多。

輕用戶端:只驗標頭,按需索取證明

輕用戶端是給你口袋裡那台裝置用的。它不下載、也不重新執行每一筆交易,而是只下載區塊標頭構成的鏈——每個標頭只有幾百位元組——並驗證產出這些標頭的共識。在以太坊的權益證明下,它靠的是同步委員會:一組會輪替的 512 名驗證者,他們聚合後的 BLS 簽章為每個標頭背書。輕用戶端只需要核對那一個聚合簽章,這在手機上也便宜到做得到。它從不重跑 EVM。

那麼,一個從不儲存餘額的輕用戶端,又是怎麼讀到餘額的?它向某個全節點索取,並要求附上證明。它已經信任的那個標頭裡含有狀態根;全節點回傳餘額,外加一條把該餘額連回狀態根的 Merkle-Patricia 分支。輕用戶端沿著這條分支一路往上做雜湊,核對結果是否正好落在那個受信任的根上。如果全節點對餘額說謊,這份證明就根本雜湊不到那個根,謊言便被拒絕。這正是優雅之處:輕用戶端在正確性上不信任任何人——數學會逮住任何假答案。

不過,要誠實面對這個取捨。證明保護你免於收到錯的答案,卻不保證你收得到任何答案:輕用戶端仍仰賴找到某個願意為它服務的誠實全節點,因此它的存活性與抗審查能力都比全節點弱。而且它在標頭有效性上承襲了整條鏈「多數誠實」的假設——倘若同步委員會本身被攻陷,標頭就可能說謊。輕用戶端是一個出色的「信任最小化」折衷,而不是「信任」。

把節點同步起來:full、snap 與檢查點

一個全新的節點,一開始只認得創世區塊,卻得想辦法追上幾百萬個區塊之外的鏈頂端。它怎麼追——也就是同步模式——是你會做的最務實的選擇之一,因為它是在「驗證的徹底程度」與「所需時間」之間做權衡。

  1. Full 同步(從創世開始):從第 0 個區塊一路重播並重新執行每一個區塊直到鏈頂。最偏執也最徹底——整段歷史都由你親自驗證——但可能耗時數天到數週。搭配封存模式,這正是封存節點的建立方式。
  2. Snap 同步(Geth 的預設):直接下載某個近期區塊的狀態樹快照(以原始的帳戶/儲存範圍形式),再「修補」任何缺口,並從那裡往前驗證。你省去重跑遠古歷史,但最終仍完整驗證當前這條活鏈。所需是數小時而非數週——這也是幾乎所有人實際在跑的方式。
  3. 檢查點(弱主觀性)同步:在共識層那一側,節點不是從創世、而是從一個近期的已最終化檢查點——一個你從可信來源取得的區塊根——開始,再從那裡向外同步。這讓共識用戶端能在數分鐘、而非數天內啟動。

最後這個模式藏著一個值得點明的微妙之處。在權益證明裡,你無法只靠協定本身、安全地從創世開始啟動,原因是長程攻擊:一個握有舊的、早已贖回的驗證者金鑰的攻擊者,能偽造出一段看似可信的另類歷史。對策就是弱主觀性——一個新的(或長時間離線的)節點,必須被交予一個近期且可信的檢查點來錨定。這是一次性的、極小的信任輸入,換來能在數分鐘內同步,相當划算;只是務必從你信得過的來源取得檢查點(朋友的節點、或數個你彼此交叉核對的獨立瀏覽器),而不是隨便一個陌生人。

# Ask YOUR OWN node whether it has finished syncing (JSON-RPC over HTTP).
curl -s -X POST http://localhost:8545 \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_syncing","params":[]}'

# While syncing -> an object with progress:
# {"result":{"currentBlock":"0x10a3f0","highestBlock":"0x12c4b8", ...}}

# Fully synced and verifying at the tip -> literally the boolean false:
# {"jsonrpc":"2.0","id":1,"result":false}
一旦你的節點追上進度,eth_syncing 就回傳 false——從那一刻起,它給你的每個答案都是它親自驗證過的。

底層管線:鄰居節點、流言傳播,以及它跑在哪台機器上

沒有哪個節點是孤島——每個節點都是一個沒有中央伺服器的點對點網路的成員。啟動時,它先從少數幾個眾所周知的節點引導,接著跑一個探索協定(以太坊用的是 discv5,一種架在 UDP 上、類 Kademlia 的 DHT)去找到更多鄰居,最後穩定在大約 25 到 100 個鄰居節點的集合。這裡沒有主控名單,也不需要向誰請求許可;當鄰居來來去去,整個網路拓樸會自我修復。

在這些連線上,一切都靠流言傳播擴散。當你廣播一筆交易,你的節點把它交給鄰居,鄰居再交給他們的鄰居,幾秒之內它就淹沒了整個網路、躺進每個人的記憶池裡——這就是交易傳播,與承載新區塊的,是同一套像傳染病般的洪泛機制。關鍵在於:你的節點在轉發每一項東西之前都會重新驗證它——它不會轉發無效的交易或無效的區塊。整個網路的完整性,正是「每個節點都自私地保持懷疑」所湧現出來的結果。

而這一切總得跑在某個地方。2020 年代中期的務實規格:一顆 4 核心 CPU、16 到 32 GB 記憶體,以及——沒得商量的——一顆 2 TB 以上的 NVMe 固態硬碟。固態硬碟比什麼都重要:驗證鏈會用大量微小的隨機讀寫去猛敲狀態資料庫,這正是傳統機械硬碟最束手無策的工作型態;用機械硬碟撐起來的節點,只會永遠追不上鏈頂。再準備一條穩定約 25 Mbps 的網路,以及每月數百 GB 的流量。