🎯 什麼情境該想到我

當你的 DApp 已經有智能合約(鏈上那一半),卻卡在這些問題時:

  • 大檔案放不進鏈上。書中 Ch.12 “Data Storage”(PDF p.501)直說:

    “Due to high gas costs and the currently low block gas limit, smart contracts are not well suited to storing or processing large amounts of data.”
    (譯文:由於 gas 成本高昂、且目前區塊 gas 上限偏低,智能合約並不適合儲存或處理大量資料。)

  • 使用者記不住 0x 開頭的地址。Ch.12 “The Ethereum Name Service (ENS)“(p.518)舉的例子:以太坊基金會捐款地址是 0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359,在支援 ENS 的錢包裡就只是 ethereum.eth
  • 前端還掛在自己的 web server 上,等於整個「去中心化應用」有一顆單點故障的心臟。
  • 要決定 DApp 該不該留管理員鑰匙(“DApp governance”,p.508–509)。

先記住本章對 DApp 的定義與它主張的三個優點(“What Is a DApp?”,p.497–498):

“A DApp is an application that is mostly or entirely decentralized.”
(譯文:DApp 是一個大部分或完全去中心化的應用程式。)

可被去中心化的五個面向:後端邏輯、前端、資料儲存、訊息通訊、名稱解析。三個優點小節分別是:

優點書中說法(摘要)
Resiliency(韌性)業務邏輯由智能合約掌控,後端完全分散在區塊鏈上;只要平台還在運作,DApp 就沒有停機時間
Transparency(透明)鏈上性質讓任何人都能檢視程式碼、確認其功能;所有互動永久留存於區塊鏈
Censorship resistance(抗審查)只要使用者能存取一個以太坊節點(必要時自己跑一個),就能不受任何中心化控制干擾地與 DApp 互動;部署後連合約擁有者本人都無法更改程式碼

但書也提醒,寫作當下(2018)「真正」的 DApp 極少,多數仍在某些環節依賴中心化服務與伺服器。

⚙️ 怎麼用

A. 我的 DApp 要放圖片/大檔案怎麼辦

1. 認清鏈上不是檔案系統。 “Data Storage”(p.501):

“Decentralized P2P storage is ideal for storing and distributing large static assets such as images, videos, and the resources of the application’s frontend web interface (HTML, CSS, JavaScript, etc.).”
(譯文:去中心化的 P2P 儲存最適合用來儲存與散布大型靜態資產,例如圖片、影片,以及應用程式前端網頁介面的各項資源(HTML、CSS、JavaScript 等)。)

2. 選一個內容定址(content-addressable)的 P2P 儲存。 書中給兩個選項:

  • IPFS(“IPFS”,p.501):

    “‘Content addressable’ means that each piece of content (file) is hashed and the hash is used to identify that file.”
    (譯文:「內容定址」的意思是:每一份內容(檔案)都會被雜湊,而這個雜湊值就用來識別該檔案。)
    IPFS 的目標是取代 HTTP 成為傳遞網頁應用的協定——網頁應用不再放在單一伺服器上,而是存在 IPFS 上、可從任一 IPFS 節點取回。

  • Swarm(“Swarm”,p.501–502):

    “Swarm is another content-addressable P2P storage system, similar to IPFS. Swarm was created by the Ethereum Foundation, as part of the Go-Ethereum suite of tools.”
    (譯文:Swarm 是另一套內容定址的 P2P 儲存系統,和 IPFS 類似。Swarm 由以太坊基金會打造,屬於 Go-Ethereum 工具組的一部分。)
    Swarm 自己的首頁就存在 Swarm 上(https://swarm-gateways.net/bzz:/theswarm.eth/),本身就是示範。

3. 實作步驟(書中 “Preparing Swarm” 起,p.514–517):

  1. 安裝 Swarm(Go-Ethereum 工具組的一部分),swarm version 確認可用(書中示範版本為 0.3)。
  2. 啟動 Swarm 時要告訴它怎麼連上一個 Geth 實例以存取 JSON-RPC API;啟動記錄裡會看到 connecting to ENS API url=http://127.0.0.1:8545
  3. http://localhost:8500 的本機 Swarm gateway 網頁介面,確認節點正常,並可查詢任何 Swarm hash 或 ENS 名稱。
  4. 單檔上傳:swarm up code/auction_dapp/README.md → 回傳一個 hash,之後任何 Swarm 節點都能靠這個 hash 取檔。
  5. 整個前端要先打包。因為 HTML/CSS/JS/函式庫彼此有內嵌參照,平常是 web server 幫忙把 URL 轉成本地檔案;上 Swarm 前要 npm run build 打包成 dist/
  6. 遞迴上傳並指定入口:
    swarm --bzzapi http://localhost:8500 --recursive \
      --defaultpath dist/index.html up dist/
    
    得到一個 hash,整個 DApp 就能用 bzz://<hash> 存取。

書中還提到第三個面向:訊息通訊可用 Whisper(同屬 Go-Ethereum 工具組),為每場拍賣開一間不需中央伺服器的聊天室。

B. 怎麼讓使用者不用記 0x 開頭的地址

上傳完 Swarm 後書自己吐槽:bzz://ab164cf37dc... 這種 URL 遠不如 auction_dapp.com 好記。解法是 ENS

1. 先理解 ENS 的分層(“sandwich” 三明治設計): 底層極簡、中層複雜但可替換、頂層極簡且把資金放在各自獨立的帳戶裡。規格散在三份 EIP:EIP-137(ENS 基本功能)、EIP-162.eth root 的拍賣系統)、EIP-181(地址的反向解析)。

2. Namehash:名字先變成 node。(“Bottom Layer” / “The Namehash algorithm”,p.521–522)ENS 底層操作的是「node」而非人類可讀的名字,兩者靠遞迴的 Namehash 演算法轉換:

namehash([]) = 0x0000000000000000000000000000000000000000000000000000000000000000
namehash([label, ...]) = keccak256(namehash(...) + keccak256(label))

遞迴的 base case 就是 root node:

“The root node is defined as 0x0000000000000000000000000000000000000000000000000000000000000000 (32 zero bytes).”
(譯文:root node 被定義為 0x000…000(32 個零位元組)。)

所以 subdomain.example.eth 的 node 是 keccak(keccak(keccak(0x0...0 + keccak('eth')) + keccak('example')) + keccak('subdomain'))。實務上的好處:Namehash 只取決於名字本身,可以預先算好塞進合約,省掉字串處理,不論名稱有幾層都能立即查表。

3. 取名要合法(“How to choose a valid name”,p.522–523)。大小寫都允許,但所有 label 應先做 UTS #46 正規化(case-fold 後才雜湊),所以拼字相同、大小寫不同的名字會得到同一個 Namehash。為了和既有 DNS 相容,書建議:

  • 每個 label 不超過 64 字元
  • 完整 ENS 名稱不超過 255 字元
  • label 不可以連字號開頭或結尾,也不可以數字開頭

4. 註冊:.eth 走改良版 Vickrey 拍賣(“Vickrey auctions”,p.525–526)。傳統次價密封拍賣的性質:

“In a traditional Vickrey auction, every bidder submits a sealed bid, and all of them are revealed simultaneously, at which point the highest bidder wins the auction but only pays the second-highest bid.”
(譯文:在傳統的 Vickrey 拍賣中,每位競標者提交一份密封標,所有標同時揭曉,此時出價最高者贏得拍賣,但只需支付第二高的出價。)

為什麼選它:因為出價者被誘導不要低於名字對自己的真實價值去出價——照真實價值出價會提高中標機率,卻不影響最終要付的金額。

放到區塊鏈上必須改三件事:(a) 出價者必須事先鎖入等於或高於其出價的金額,確保不會亂喊不付;(b)

“Because you can’t hide secrets on a blockchain, bidders must execute at least two transactions (a commit–reveal process), in order to hide the original value and name they bid on.”
(譯文:因為在區塊鏈上藏不住秘密,出價者必須執行至少兩筆交易(一個 commit–reveal 流程),才能隱藏他們原本的出價金額與所競標的名稱。)

(c) 去中心化系統無法「同時」揭曉所有標,只能由出價者自己揭標;不揭標就沒收鎖定的資金——否則有人會廣撒標單、只挑一兩個揭曉,把密封標拍賣變成傳統的加價拍賣。

因此拍賣是四步:開標(名稱經雜湊,只有字典裡有該名字的人才知道開了哪場;還可同時開多個假標混淆跟蹤者)→ 密封出價(把一筆 ether 綁到一段秘密訊息的雜湊上,內含名稱雜湊、實際出價與 salt;可以鎖超過實際出價來掩飾真實估值)→ 揭標(每次揭標都重算當前贏家,揭標期限前最後被設定的那個成為最終贏家;未中標者退款)→ 收尾(贏家 finalize 拿回出價與次高價的差額;忘記揭標可補晚揭回收一小部分)。

書中實作示範是用 MyCrypto 介面搭 MetaMask 標下 ethereumbook.eth,並附了血淚警告:出價後 48 小時內必須揭標,否則資金沒收——作者自己就這樣賠掉 0.01 ETH。

5. 頂層 The Deeds:資金怎麼放。 得標後資金不是付給誰,而是鎖定在你持有名字的期間(至少一年),像有保證的買回機制:不想要名字時賣回系統就能取回 ether,持有成本等於這筆錢的機會成本。為避免單一合約握有數百萬美元的風險,ENS 為每個新名字建立一份約 50 行的 deed 合約,只允許把資金退回單一帳戶(deed 擁有者)、只能被單一實體(registrar 合約)呼叫,大幅縮小攻擊面。

6. Resolver:名字要指向什麼,由解析器決定(“Resolvers”,p.523–524):

“The basic ENS contract can’t add metadata to names; that is the job of so-called ‘resolver contracts.’”
(譯文:基本的 ENS 合約無法為名稱附加中繼資料,那是所謂「解析器合約」的工作。)

解析是兩步:先把名稱雜湊後呼叫 ENS registry,若記錄存在就回傳其 resolver 的地址;再呼叫該 resolver,用對應資源的方法取得結果。這種分離讓你可以自訂 resolver 回答任何型別的資源(書舉例:未來想把經緯度地理位置綁到 ENS 名稱,寫個新 resolver 即可)。一般情況用預設的 public resolver 就好,它支援 address(錢包或合約)與 content(DApp 的 Swarm hash 或合約原始碼)。

7. 串起來:subdomain + content。ENS Manager 建子網域(書中示範 auction.ethereumbook.eth),設好 public resolver,再把 content 設成前端的 Swarm hash。結果從:

bzz://ab164cf37dc10647e43a233486cdeffa8334b026e32a480dd9cbd020c12d4581

變成:

http://swarm-gateways.net/bzz:/auction.ethereumbook.eth/

也能直接在任何支援 ENS 的錢包或 DApp 瀏覽器裡搜尋這個名字。

C. 決定治理:要不要留特權帳號

“DApp governance”(p.508–509)把這件事講成雙面刃:有特權帳號很危險,一旦被攻破就能顛覆整個 DApp 的安全性;完全沒有特權帳號,則在發現 bug 時毫無補救手段。書舉兩個反面案例:The DAO 的「curators」權限太有限,擋不住攻擊者提走資金;去中心化交易所 Bancor 則因為一個特權管理帳號被攻破而遭鉅額竊盜——「結果證明 Bancor 並沒有它最初被認為的那麼去中心化」。書的結論是:

“Either choice carries risk, but in the long run, true DApps cannot have specialized access for privileged accounts — that’s not decentralized.”
(譯文:兩種選擇都有風險,但長遠來看,真正的 DApp 不能為特權帳號保留特殊存取權——那不叫去中心化。)

🧪 我實際套用的紀錄

  • (待填)

⚠️ 注意 / 什麼時候不適用

  • 本卡完全依據《Mastering Ethereum》(O’Reilly, 2018) Ch.12 原文。 ENS 的 .eth 註冊機制在本書之後已經改版,書中描述的 Vickrey 密封拍賣+deed 鎖定資金是 2017–2018 年當時的做法,實際要註冊名字前必須查現行規格,不要照書操作。書中自己也標明「at the time of writing」。
  • root node 的治理是有名有姓的中心化風險(“Root node ownership”,p.523):整個階層系統依賴 root node 擁有者來建立頂級域名(TLD),而「寫作當下 root node 由一個 4-of-7 多重簽章控制」,由分散在不同國家的人持有(比照 DNS 的 7 位金鑰持有者設計),任何變更都需要 7 人中至少 4 人同意。書列出的目標包含把 .eth TLD 遷移到更永久的合約、必要時新增 TLD、把 root multisig 遷到更去中心化的合約,以及在頂層註冊系統出現漏洞時作為最後手段。長期目標是去中心化,但當下不是。
  • .eth 幾乎是唯一選項(“Middle Layer: The .eth Nodes”,p.525):寫作當下唯一能在智能合約中唯一註冊的 TLD 就是 .eth。讓傳統 DNS 域名持有者認領 ENS 所有權的工作仍在進行中,理論上 .com 可行,但目前只對 .xyz 實作,而且只在 Ropsten 測試網
  • 拍賣合約是複雜度熱區:書明說 .eth 拍賣系統超過 500 行,ENS 早期的開發心力(與 bug!)多半集中在這一塊;好在它可替換、可升級且不危及資金。
  • 48 小時揭標期限會吃掉你的錢,這是流程性的操作風險,不是技術問題。
  • 鏈下運算=信任外部資源:書在 “Backend (Smart Contract)“(p.499)提醒,若把核心業務邏輯依賴外部資料(例如中心化伺服器),使用者就必須信任這些外部資源。搬到鏈下省 gas 的同時,信任模型也一起改變了。
  • 不要把「有網頁前端的智能合約」當成 DApp:本章開頭的 WARNING 直接造了個詞——這類高度中心化的應用該叫 CApp,「小心假的 DApp!」

🔗 相關工具