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

去中心化應用、錢包與簽名

去中心化應用,不過是一個接到鏈上程式碼的網站。本文講清你的錢包如何為請求簽名、為什麼讀取免費而寫入要花燃料,以及一次代幣授權究竟交出了什麼。

一個應用的兩半

想像一個普通的網路銀行。你在瀏覽器裡看到一塊精緻的介面——按鈕、餘額、一個轉帳鍵——但真正的錢住在銀行的伺服器上,鎖在公司的資料庫背後。那塊介面只是一扇友好的窗,望向一個你看不見、也掌控不了的金庫。

去中心化應用保留了那扇友好的窗,卻把金庫換掉了。它的前端是一個普通網站,可以住在任何伺服器上(甚至你的筆記型電腦);而*邏輯與資金*則坐落在以太坊這類公鏈上的智慧合約裡。所以一個 dApp 其實是兩半:一半是你看著的前端,一半是無法偽造、也無法關停的鏈上程式碼。前端明天就算消失,合約——以及你的資金——也會一如既往地照常運轉。

錢包,是你的簽名筆

你的錢包並不是存放硬幣的地方——那些數字住在鏈上。錢包真正的工作,是守護一個秘密:你的私鑰。把這把私鑰想成一支只有你握著的簽名筆,它寫出的簽名,地球上沒有任何人能夠偽造。當一個 dApp 想讓你做某件事時,你的錢包就用這支筆為請求簽名,證明這道指令確實出自你手。

這支筆背後的密碼學,是數位簽章。它的奇妙之處在於單向:你的私鑰造出一個簽章,任何人都能拿它來核對你的公開地址,可無論怎麼核對,都永遠不會反推出私鑰本身。於是整個網路都能確認*「沒錯,這個帳戶的主人確實授權了此事」*,卻從不曾窺見你的秘密。先簽章,簽好的請求便能安全地穿行於開放的網際網路。

讀取免費,寫入花燃料

你與合約的每一次互動,都落進兩個籃子中的一個,而二者之別,決定了你究竟要不要打開錢包。讀取是向鏈發問——*我的餘額是多少?這件物品歸誰?*——它什麼也不改變。任何節點都能用手頭已有的資料作答,所以讀取既即時又免費;無需簽章,也無需付費。這正是為什麼頁面一載入,dApp 就能顯示你的餘額,而你還什麼都沒批准。

寫入則是另一個籃子:它*改變共享狀態*——轉出代幣、投下一票、鑄造一件物品。一次寫入必須由網路上每一個節點重新運行並達成一致,再被永久存下,因此它不可能免費。它必須是一筆簽了名的交易,並附帶一筆燃料費,為這場全球性的運算付帳。讀取是圖書館員瞥一眼書架;寫入則是館裡所有人同時改寫各自那一本書。

READ  (a question)            WRITE (a change)
  cost: free                    cost: gas fee
  signature: none               signature: required
  speed: instant                speed: wait for a block
  example: getBalance()         example: transfer(to, 10)

Flow of a write:
  front-end drafts tx  ->  wallet shows it  ->  YOU sign
        ->  broadcast  ->  a validator includes it in a block
        ->  every node re-runs it  ->  state updated forever
讀取是免費地發問;寫入會改變世界,且要花燃料。

代幣授權:交出一份支出額度

有一個動作常讓新手栽跟頭。多數合約無法伸進你的錢包、把你的代幣掏出來——而這是刻意如此設計的。於是,當一個 dApp 需要*代你*轉移代幣時(比如一個交易應用,要把一種幣換成另一種),你得先簽一筆單獨的交易,叫作授權。它告訴代幣合約:*「允許這個另外的合約,最多花掉我 N 枚代幣。」*

// Solidity: the approval lives in the TOKEN contract
function approve(address spender, uint amount) public {
    allowance[msg.sender][spender] = amount;  // set a limit
}

// Later the dApp's contract may pull tokens, but only
// up to the limit you set:
//   transferFrom(you, someoneElse, amount <= allowance)

// approve(dApp, 50)            -> safe, capped at 50
// approve(dApp, UNLIMITED)     -> convenient, but risky
一次授權設定了一個支出上限;dApp 此後最多可拉走這麼多。

授權是真正有用的——它讓一個應用順暢地行事,不必每一步都來煩你簽名。但癥結在於額度。為了省去你日後的彈窗,許多 dApp 會索要一份無上限的額度,而人們往往不看就一路點過。倘若那個支出合約日後被發現存在缺陷、或心懷惡意,這份長期有效的許可,恰恰就是讓它能抽乾已授權代幣的那把鑰匙。補救之道很簡單:盡量只授權你實際要花的數額,並撤銷那些你不再使用的舊額度。

把它們串起來

  1. 打開 dApp。它的前端載入後,免費*讀取*鏈上資料來顯示你的餘額——此刻還沒有錢包彈窗。
  2. 點擊一個動作。前端*起草*一筆交易(比如一次兌換),並把它遞給你的錢包——它自己無法發送。
  3. 讀一讀,再簽名。你的錢包顯示這份請求和燃料預估;你的簽名把它變成一筆有效且經授權的交易。
  4. 網路結清它。這筆簽好的寫入被廣播、被打包進區塊、被每個節點重新運行,並永久記錄到鏈上。

整套模式就是這樣。一個 dApp 是前端加鏈上程式碼;你的錢包是那支簽名的筆;讀取是免費的發問,寫入是付費的改動;而一次授權,是一份值得仔細設定的支出額度。接下來,我們要看代幣本身——那些標準,讓一個合約發行的一種幣或一件藏品,能被每個錢包和應用瞬間認得、知道如何處理。