如何設計一個去中心帳本?
- Published on
在設計一個理想的 DLT 時,有三個核心問題:
- 如何設計出一個好的帳本結構?
- 如何讓此帳本上是無法被篡改的?
- 如何讓不信任的節點之間對此帳本有共識?
第一個問題在談的是 UTXO 模型與 Account 模型;第二個問題在談 Hash 跟非對稱加密;第三個在談各種 Proof of XX。
如何設計出一個好的帳本結構?
UTXO
在帳本架構的設計上,Bitcoin 採用了 UTXO (Unspend Transaction Output) 架構。先想像在 Bitcoin 上面運作的錢(BTC)都是一張張的支票,每張支票會備註未使用跟已使用。當我們去查看一個 UTXO 的帳戶地址時,並不會直接看到帳戶餘額,而是需要去追蹤每一張發送給這帳戶的支票,扣掉已使用的過後,才是一個帳戶現在有的餘額。
此外,支票還有一個無法部分兌現的特性:我想轉 5 BTC 給 A,但我手上只有一張 8 BTC 的支票,實際轉帳的時候,是會開一張 5 BTC 的支票給 A,再開一張 3 BTC 的給我自己。
衍伸下來,因為會紀錄誰擁有每一張支票的使用權,所以 UTXO 天生能處理雙花攻擊。首先是已被使用過的支票不能用,接著是如果有人想拿一張未使用的支票同時付給兩個人,節點只會認比較早發出交易請求的。再如果真的很不湊巧兩筆交易時間很近,剛好又被兩個不同的節點同時接受並出塊了,這樣最後一道防線就是,則用最長鏈法則(中本聰共識)來決定。
UTXO 架構的優點是可以平行處理多筆交易,原因是只認支票而不認帳戶,一個帳戶之下有五張支票,他就可以同時把五張支票都花掉,不需要在帳戶層面去確認餘額。另個有點是天生隱私性高,讓你查詢一個帳戶時,是無法直接看到有關這個帳戶地址的所有金流的。
相對的,UTXO 的缺點是不直覺。另外,想要實作智能合約時也比較麻煩,因為智能合約往往需要直接跟一個帳戶互動,但 UTXO 天生就沒有這種「帳戶」的概念,所以比較新的鏈基本都不採用這架構了。當然,也有人搞出一個 UTXO Pool 的優化方案:先掃過從創世到現在的所有交易紀錄,把每一個地址上現在有的餘額記錄在一個資料庫中,讓使用者不用傻傻的把整條區塊鏈從頭看過一次。
Account-Based Model
相對於 UTXO 架構,以太坊採用了相對陽間的 Account-Based Model。與人類的直覺比較相符:當你點進某一個帳戶地址查詢時,能看到帳戶餘額以及帳戶地址的每一筆交易。
這架構的優勢除了更加直覺之外,也更適用於簡單的交易:只要對兩個帳戶的餘額做增減,不用像 UTXO 一樣還要去湊到剛好金額的支票。另外也原生支持智能合約的部署,因為合約很常需要持續追蹤一個帳號的餘額。相對的,Account-Based Model 的缺點是無法進行平行化處理。
如何防止一個帳本被篡改
已經有個的帳本,也就是有了一筆資料在哪邊時,該如何做到讓它能不被隨意的竄改呢?
Hash 函數
SHA256 Hash 是一個函數,厲害的地方是可以把任意長度的 Input (又被稱作 preimage )轉換成一個固定長度,稱作 Hash 值的 Output。Hash 函數有個特性:當 Input 有些微的差異,Output 就會差很多,並且是毫無邏輯可言的,也就是說,如果想要獲得特定的 Hash 值,只能靠一直亂猜。在區塊鏈的語境之下,Input 就是各式各樣的資料(Data);在分散式帳本(DLT)的語境之下,Input 就更明確為帳本資料(Ledger),也就是,誰給了誰多少錢的一筆筆資料。
SHA256 的全稱是 Secure Hash Algorithm 256,256 指的是,這個產生的 Output 長度,固定都是 256 bits。在 16 進位(0 ~ F)之下,也就是一個長度為 64 位元的字串。
Block
每一個 Block 會有五個元素:#Block(第幾個區塊)、Nonce(一個隨機數)、Data、Previous Hash 值、Hash 值。把前四項包在一起,能視為一個 Input,通過 Hash 函數,我們可以得到第五項的這個 Hash 值。Input 在只更動 Nonce 的條件下,讓 Output(Hash 值)的前六位為零,這個「湊出符合條件的 Nonce」的過程我們稱之為 挖礦。礦工指的就是去購置算力資源,進行挖礦的人。第一個湊出正確答案的人,會把結果廣播給其他人知道。在其他人都驗證沒問題之後,大家會將這個驗證過的 Block 接到自己原先的鏈上。而那個第一個算出正確答案的人能拿到一筆獎勵。(把這句話的「人」全都替換成「節點」比較準確,但你懂我意思的)
Blockchain 顧名思義,就是很多個 Block 接起來,下一個 Block 的 Previous Hash 值會是上一個 Block 的 Hash 值。例如有一條鏈已經接了五個 Blocks 了,你去稍微更動第二個 Block 的任何資料,則後面所有的 Hash 值都會一連串的隨之改變。當然,你可以暴力去再去算出符合條件的 Nonce 值,讓二三四五的 Hash 值都符合上面要求的規則(前六位為零),但是,結尾的 Block 上的 Hash 值會跟其他人電腦上的不一樣,這樣別人就知道你動過前面的東西。想更動越早期的資料難度更高,因為需要更強的算力使其變成最長鏈。
以上的這套系統,創造了一個防止他人竄改歷史資料的系統。但注意,不能更動與防止竄改是兩個概念:不能更動是設計上直接不能有任何改變,防止竄改指的是可以改動,但我去改動的話,大家都會知道,無法偷偷來。
轉帳資料
即使一個完整的帳本是受到防篡改保護的,但由於帳本內的一筆筆交易,是由一個個有可能作惡的使用者所發起的,衍伸的就會產生以下三個問題:一是怎麼知道看到「A 給 B 發錢」的請求時,A 手上是真的有錢,而不是一時口嗨;二是如何避免雙重支付(Double-spending),也就是俗稱的雙花攻擊;三是怎麼確認這個發錢的請求,確實是由我本人發起的。不然我就能亂喊 Musk 給我一個億之類的(他肯定有 xDD)。
第一個問題好解決,就是一路往前追朔到最前面的區塊,當然,這有點沒效率,替代的解決方式就是,用一個資料庫去存最後的狀態,有點像帳戶餘額的概念。第二個問題由 UTXO 的帳本模型天生就能避免。第三個問題是透過公鑰密碼學(Public-Key Cryptography, PKC)來解決,它是一種同時使用公鑰與私鑰的機制,其核心內容為 非對稱加密 與 數字簽名。
首先,世界上所有的加密方法都只是讓密碼變很難猜罷了,如果有人硬是要花時間窮舉的話,理論上肯定還是猜的到。好的加密方法指的是,別人需要窮舉很久。而一種密碼方法被破解,指的是,有人找到一個比窮舉還要有效率的解法。例如窮舉需要猜 10000 次,有人找到個算法,去猜 9000 次就能肯定得到答案的話,那麼這個加密演算法算是被破解了。
對稱加密,意思是加密的過程中,只使用單個密鑰(例如 AES)。與之相對的,非對稱加密會同時有私鑰(private key)與公鑰(public key),其密鑰也會比較長。雖然在加密與解密的過程上需要更多的計算資源,但相對的也比較難被破解。最常見的非對稱加密算法是 RSA 算法,名字來源於它的三位發明者:Rivest、Shamir 以及 Adleman。而比特幣跟以太坊用的都是另一種稱為 ECDSA 的算法,也屬於非對稱加密家族的一個成員。
私鑰與公鑰是一組的,但是具有方向性:知道私鑰,也就知道與之相對的公鑰,但反之並不成立。私鑰像是私人印章,而公鑰能確認這個蓋過章的東西是不是贗品。
- 加密的過程:給訊息、給私鑰,可以產生數位簽章(message signature)。這過程可以理解為幫一段訊息蓋章,跟去銀行填匯款單時,要蓋印章或簽名是一個道理。
- 解密的過程:給訊息、給公鑰、給數位簽章,就能確認訊息是不是由本人發出。
公鑰就是錢包地址。(詳細來說會有一點差異,但不影響理解)
回到最一開始的問題,每個人在發出一筆交易例如「A 匯給 B 100 鎂」這訊息時,會 A 用自己的私鑰,給這訊息產生一個數位簽章,使得他人任意改動交易的內容時,即使 Nonce 值是對的,透過數位簽章也能看出有問題。
建議到 這個網站 上面去實際玩玩看,這演示是目前看過最好的區塊鏈展示。這一套防止篡改的手段,你會發現這有點像是個套娃:在交易資料時,就先有一個數位簽章的驗證程序,然後在最外面整個帳本還有一個 Nonce 跟 Hash 值的驗證。
如何讓不信任的節點之間對帳本有共識?
現在每個節點上面,都有個包含所有歷史帳目的帳本。然而,節點與節點之間是如何產生共識,來確保大家手上的帳本都是一樣的呢?
有共識是指,所有節點上的帳本是一致且大家都認同的。至於「節點」該怎麼理解呢?想像手邊的一台電腦,在上面灌上特定的軟體(例如以太坊的 Geth),它就能自動的不斷更新到最新的帳本資訊,這樣你的筆電也就是一個節點了。(節點可以單純的用來儲存帳本,跟要不要去挖礦是兩回事)
之所以要有共識機制,是要處理有壞節點存在的情況。壞節點指的是想來搞破壞的節點。畢竟真實世界是個黑暗森林,歲月靜好只存在平行世界中。假設你在自己電腦的帳本上,胡亂加入一條別人匯錢給自己的假資訊,然後廣播出去,那就是一個壞節點,Bad。
處理好共識問題,等價於做到了「去信任化(trustless)」:不用假定別人是好人,也能夠透過一套機制,去信任他人。只要細品,不難理解這是一件非常偉大的事情。
Practical Byzantine Fault Tolerance (PBFT) 實用拜占庭容錯算法
1999 年的一篇論文提出來,為的是解決拜占庭將軍問題。拜占庭將軍問題是指,節點之間想決定一件事情,例如大家往前走一步,或是大家往後退一步,同進退就能活下來,不同步的話就大家一起掛掉。每個節點都可以跟每個節點溝通,但存在壞節點想搞破壞,不知道是哪一個。
有很多人對拜占庭將軍問題提出解法,但複雜度都過高,沒那麼實用。是直到 1999 年那一篇論文才出現相對「實用」的解法的,其結論是,當壞節點不超過總結點數的 1/3,好節點之間還是能達成正確的共識活下來。但存在的限制是,節點必須是給定的,也就是不能到一半加入其他節點。加上處理問題的時間複雜度是 O(N^2),所以在現實世界的實用性不高。無論如何,它是共識機制界的 OG。數學上來說,可以理解所有的共識機制,本質都是想要解決拜占庭將軍問題。
Proof of Work (PoW) 工作量證明
概念上就是天道酬勤。之面說到挖礦就是去算出正確的 Nonce 值,讓 Hash 值去滿足對應的要求(例如最前面多少位是零),這個去「算出正確的 Nonce 值」就是工作(Work)。最先算出答案的礦工會把答案告訴其他節點,而其他節點驗證沒問題之後,Block 就會成立,接到原有的鏈上去,而這個最先算出來的礦工可以獲得一定的獎勵。平均來看,如果佔全部礦工運算資源的 X%,也對應能獲得 X% 的總獎勵。
這裡共識的邏輯是,因為你努力工作了,所以大家相信你,算是第一代區塊鏈最常見的共識機制。從另一個角度去理解,那個出塊的礦工是一個獨裁者,PoW 就是一個透過解數學問題,隨機分配讓礦工作為獨裁者的權利。要避免這個幸運的獨裁者作惡,通常會搭配「最長鏈原則」使用。也就是想作惡的人,只幸運一次是沒用的,其他人下一輪會就看出來,並選擇不認你這個有作惡過的鏈。這是一個多期的賽局。
現在使用 PoW 的主要就 Bitcoin,比較新的鏈幾乎不用,原因有很多:例如礦工們會專門製造了算 Nonce 的處理器(ASIC)去挖礦。想像一下,有一堆超級電腦,就只是在那邊算一個亂數,不只耗電不環保,也對人類文明沒有任何貢獻。但當然也有人持相反的論點:説一種貨幣想要能真正的存儲「價值」,就必須有相對應的付出。像美元那樣能靠信用直接印鈔,或是 PoS 那樣大者恆大的機制,是條錯誤的路線。有興趣的可以去看看《貨幣未來:從金本位到區塊鏈》,裡面有很多發人省思的論點。
Proof of Stake (PoS) 權益證明
在這機制之下,一個新區塊的確認,是由一位稱為「驗證者(validator)」來做確認的。想成為驗證者,你需要先質押(stake)代幣到某個網路上(例如質押 ETH 到以太坊上)。然後系統會直接用質押股權的高低,來分配給你當驗證者的機會。也就是礦工之間不用再競爭了,我們直接來比股權的多寡就行。
股權詳細來說,是基於資產加權的幣齡去決定。例如存一天的 10 ETH 跟,跟存十天的 1 ETH 會有同樣的權重。一但被選中之後,拿過獎勵的驗證者,權重會歸零。(不然某人有 51%的總資產,就都他在拿就好了)。這種有參與驗證人選拔的節點,我們稱之為「驗證節點」。驗證者的獎勵通常是這個新添區塊中的交易手續費,而不會有像 PoW 中的新區塊鑄造獎勵。這也是我們會聽到:「以太坊從 PoW 轉換成 PoS 之後,ETH 的通膨問題會大大減少」,這句話的論點來源。如果一個節點想停止驗證節點的身份,那麼它的股權和所得的獎勵將在一段時間後才被釋放,從而使網絡有時間,驗證該節點是否向區塊鏈中添加了假區塊。
PoS 這套機制的底層道理是,用戶必須先把真金白銀壓在網路上,如果敢作惡的話,網路就把你的本金沒收。PoS 的主要優點是能源消耗低和安全性高,是目前的主流。
Delegated Proof of Stake (DPoS) 委託權益證明
基於 PoS 魔改,由 Daniel Larimer 在 2014 年提出,讓用戶可以投票給幾個代表代替他們保護網絡。代表們也被稱為「見證人」,他們有責任在產生和驗證新區塊的過程中達成共識。投票權與每個用戶持有的幣數量成比例,投票系統也因項目而異。通常代表們也會收集獎勵並按比例分配給投票者們。
優點是因為節點少,所以在性能方面與 PoW 和 PoS 相比更強,也就是理論上 TPS 能更高。與 PoS 相比,這就像直接民主跟間接民主的差異:直接民主確實很民主,但很多事情決定起來很慢,也會有很多內耗。越極權處理事情效率就能更高,但有中心化的風險。而其缺點也很明顯,因為依賴特定節點,在三難問題中,犧牲了一些去中心化。
Proof of Authority (PoA) 權威證明
由 Gavin Wood 在 2015 提出。找幾個願意暴露自己真實身份,同時又是權威的人士來當作驗證者。節點數可以很少,所以 TPS 可以很好,交易費用可以很低,但缺點是過於中心化,可以理解成極端版本的 DPoS。通常會搭配多重簽證機制來防,就是需要多位權威有共識才能通過。
PoS 的假設是,當用戶壓越多資金在網路上,則越有動機維護網路的安全。但是這假設沒有考慮到的是,同樣的絕對金額,對越有錢的人來說,佔其總資金的比例就越低,那麼他的維護網路安全的動機也會越低。舉例來說,我很窮,我放一千鎂在以太坊上,佔了我總資產的一半,則我會超有動機好好做事,不然被沒收一千鎂可能就要直接去睡公園;但如果是讓 Elon Musk 來,他放一千萬鎂在以太坊上,這佔他總資產的九牛一毛,則他要任性作惡一下對他影響也不大。
PoS 抵押的是錢,而 PoA 抵押的是信用。當然,這前提是驗證者的信用是有價值的。PoA 因為不夠去中心化,無法被大規模的採用。所謂知人知面不知心,王力宏都可以一夜身敗名裂,誰來當這個權威早晚感覺都會出事。不過,它的用途是在一些去中心化不是特別重要的情境:例如企業內部使用時,因為不想承受公鏈過高的手續費時,自架自己的私有鏈,這時候用 PoA 則很常見。
Proof of History (PoH) 歷史證明
共識機制從更高的角度去理解,它是想要建立一個時間的概念,就是想要分清楚兩個事件的先來後到。共識上有衝突,也可以被理解成時空上有矛盾。PoH 用了一個叫做 VDF (Verifiable Delay Function) 的函數,可以幫每一筆交易加上了一個加密不可更動的時間戳。
相較的,其他共識機制的時間戳是放在區塊上的,所以需要讓每個節點都確認新區塊,有全局的共識之後,時間才會往後走一步,而這個等待,正是很多鏈 TPS 上不來的主因。嚴格來說,PoH 不是一個共識機制,它是一套建立時間概念的手段:直接讓交易有了先後順序,一條鏈就可以省略「節點之間全局共識」的過程,能讓鏈作到異步更新,這也能讓 TPS 大大的提高。