Mastering Bitcoin — CH6 The Bitcoin Network

徐粲邦
Taipei Ethereum Meetup
13 min readApr 12, 2017

--

Outline

本篇是 Mastering Bitcoin 這本書的第五章心得,如果你沒有這本書的話可以去這邊,書跟心得都不會講的太深入,我的目標是希望不懂寫程式的都能看得懂 (順便幫自己做筆記),希望這目標不會太困難。

本篇主要在探討比特幣的網路,一開始會先介紹比特幣節點的四個功能,然而也不是每個節點都需要同時具備所有功能。再來會介紹到如果一個新的節點想要加入比特幣網路,那他會經過什麼樣的流程?最後在介紹,因應現在社會平板、智慧型手機和嵌入式裝置的普及,比特幣後來發展出來 (也可以說是簡化成 )的一種節點,他的特色又是什麼?

本篇跟其他篇比較沒有相依賴,也講的比較 high level 不會太深入,但仍然建議讀者已經看過第二章了解整個比特幣的概覽,第二章連結在這邊。

最後本章最常用到的字,比特幣交易 (transaction) 和地址 (address) 我都用英文來表達而不用中文。

  1. 比特幣的節點是由四個部分所組成,分別是掌管網路的、記錄整條區塊鏈的、挖礦產生新區塊的跟使用者的錢包。
  2. 當一個新比特幣節點產生時,他是如何跟其他節點溝通的?當連結上其他節點時,他又是如何更新到和大家一樣的?
  3. 什麼是 Full nodes,什麼又是 Simplified Payments Verification (SPV) nodes?他有什麼優點和缺點呢?

Nodes Types and Roles

比特幣的網路是 P2P 的,意思就是整個網路上沒有誰比較特別,沒有一個中央節點,大家都是平等的,而雖然比特幣節點都是平等的,但因為功能上的需求,每個節點之間仍然可以有一些差異,一個比特幣節點基本上可以由以下四個功能所組成

  1. Network,任何一個比特幣節點都一定會要有這個功能,所有節點都會驗證和傳遞區塊 (block) 跟 transaction,節點和節點之間的溝通和連接都需要透過這個功能來完成。
  2. Blockchain,有些節點會擁有完整的區塊鏈 (blockchain) 紀錄,這些節點又稱為 Full node,他可以驗證新來的 transaction 而不需要透過外界幫助,因為他自己就有完整的資料了,而反之有些節點又沒有保存完整的區塊鏈,又稱為 Simplified Payments Verification (SPV) node,第三節會介紹他是什麼。
  3. Mining,以前我們提到的礦工 (miner),就是指那些有這個功能的節點,他可以去解決 Proof of Work 的問題來幫忙產生新的區塊,而下一章才會介紹到底挖礦 (mining) 是怎麼進行的。
  4. Wallet,使用者的錢包,如我們第四章介紹過的,這個功能會幫忙保管使用者的密鑰 (private key)、私鑰 (public key) 以及 address。

然而不是每個比特幣節點都需要具備上述四個功能,依照功能不同也可以選擇不同的組合,而像上圖如果全部功能都包含了,這就是一般說的比特幣核心 (Bitcoin core)。又例如我自己有參與過的一個專案,我們在 Gcoin (由比特幣衍生的區塊鏈系統) 上架一層 stateless server 來包住區塊鏈,這樣的架構下我們就選擇把區塊鏈的 Wallet 抽掉,讓上層的服務自己去維護自己的錢包。又例如我可能也會想架一個節點,純粹讓大家可以看區塊鏈上的資料,所以這個節點就只需要有 Network 和 Blockchain 兩個功能。說了這麼多只是想表達這四個功能是可以依據需求而有不同的設定的,如下圖就是本書給的一些例子。

Network Discovery

假設現在你創了一個新的比特幣節點,他要怎麼找到其他的比特幣節點?在比特幣節點內部存了一串長久且穩定的節點位址,叫做 seed node,它可以幫助新節點快速找到其他節點,一旦與其他節點建立了連線,新節點就會斷開原本與 seed node 的連接。

而節點與節點之間的連接,最一開始一定會有握手 (handshake) 的階段,這是在計算機網路裡面兩方溝通的起手式,一方會先發送訊息到另一方,而對方需要有所回應 (ack),在比特幣節點,握手則是傳送 version 給對方,如下圖。

而這個新節點會馬上把自己的 IP 地址告訴與它相連的鄰居 (在網路世界裡,鄰居不一定是真的在附近,地理位置上他們可能很遠),而鄰居們一收到新的 IP 位址,他也會把他繼續傳送給他的鄰居,此外,他也會跟他的鄰居要他們的 IP 位址,如此一來網路就更加穩固了。

當節點收集到夠多的鄰居之後,也就變得更加穩固了,而他也會將最近幾個成功連結過的鄰居給記起來,所以在重開機之後他也能夠很快速地重新建立連線,如果舊的連線均失敗了才會重新去跟 seed node 要位址。

Exchanging Inventory

在建立連線之後,這個新的節點只會有一個區塊,叫做創世區塊 (genesis block),顧名思義就是第一個區塊,那他該如何同步成跟大家一樣的進度?在相連的節點之間,會互相交換著 getblocks 這個訊息,而這個訊息裡面包涵我這個節點當前最新的區塊 hash (BestHeight),以這個新節點來說他發出去的 getblocks 就會是創世區塊的 hash,因為他目前就只有一個區塊。

而相鄰的節點間,會有一個節點發現他所獲得的 getblocks 資訊並不等於自己的資訊,反而是一個已經出現過的區塊 hash,因此他就可以推定自己所擁有的區塊鏈是比較長的,然而他並不會就這樣把別人所沒有的區塊 hash 都通通傳回去讓他更新,反而是回傳一份清單 (inventory),告訴他他缺少了哪些區塊,而原節點就可以根據這份清單,重複的呼叫 getdata 來跟他要區塊資料。

以剛剛的新節點來說,他會得到一個清單是他所沒有的接下來 500 個區塊 hash (當該節點落後超過 500 個區塊時,就先給他前 500 個不一次給太多,而 500 只是一個預設值),他獲得這份清單後,他可以跟所有他相連的節點要資料而達到分流的效果,而這會持續下去直到這些相鄰的節點們都有一樣最新的區塊 hash,代表高度都一樣了。流程如下圖。

Simplified Payments Verification (SPV) nodes

在第一節我們提過,擁有 Blockchain 功能的節點就叫做 Full node,也因此 full node 才會有上一節末的事情發生,早期的比特幣節點全部都是 Full node,他們記載著完整的區塊鏈資訊,且因為上一節提到的,他們會互相交換 getblocks,所以也都會時時保持著自己的區塊鏈是最新的。

也因為他有完整的區塊鏈歷史,所以 Full node 可以驗證任何一個 transaction 的正確性,因為他可以一路從創世區塊開始直到找到這個 transaction 為止,但他最大的缺點就是很佔空間,因為需要完整的區塊鏈資訊,硬碟需要至少空出幾十 GB,而且在同步的過程也會花上好幾天的等待。隨著手機、平板、嵌入式裝置等的出現,於是就發展出了一個輕量級的節點,叫做 Simplified Payments Verification (SPV) nodes。

SPV node 只下載 block header 而不像 Full node 會下載每個區塊裡面的所有 transaction,如此可以省下將近千倍的空間,而這麼做是有代價的,舉個例子來說,如果我們要檢查一個在區塊 #300,000 的 transaction 正確性,在 Full node 之下我們可以從創世區塊開始,一步步的建構整個區塊鏈來確認這筆 transaction 是花費還沒被用掉的 UTXO,而在 SPV node 就不能這樣,他必須仰賴他的 Full node 鄰居驗證,等到區塊高度到達 300,006 時,他才可以確認這筆 transaction 是合法的。

從上面論述可以知道,SPV node 會有安全性問題,因為他畢竟沒有完整的區塊鏈資料,所以必須確保他至少有一個誠實的鄰居,不過在現實生活上,SPV node 多半有充足的鄰居來保持他的穩定度及安全性。

雖然 SPV node 不能驗證 transaction 的合法性,必須仰賴 Full node 驗證後透過網路傳輸過來才知道,但是 SPV node 是可以證明某一筆 transaction 是否存在的,因為在 block header 裡面有個資訊叫 merkle root,可以想像成他是這個區塊裡面所有transaction 的 hash 總和。詳細下一章會介紹。

而因為 SPV node 只需要 block header,所以在溝通上當然也不會像 Full node 傳輸 getdata 來要資料了,改用 getheader 這個訊息,如下圖。

在 SPV node 裡,我們可能會想要拿取特定的 transaction,例如我只在乎跟我這個節點裡的錢包有關的 transaction,這樣就暴露了潛在的安全風險,如果我持續偵測這個 SPV node 都去要哪些 transaction,交叉比對一下就會知道在這個錢包裡面的 address 是哪些,雖然不會暴露公鑰 (public key) 跟私鑰 (private key),但這個錢包就損失了匿名性,對此,比特幣的開發者多加了一層過濾在 address 上,來維持 SPV node 錢包的匿名性,而這層過濾叫做 bloom filter。

Bloom Filters

SPV node 不直接跟鄰居要特定的某些 address 相關的 transaction,反而是給定一個特徵 (pattern),符合的就給我,例如我要所有符合 address 結尾是 1234 的 transaction。可以知道如果特徵給的越詳細,就等於符合的 address 可能性就越少,這樣找到的 transaction 多半都是自己真正想要的,但代價就是匿名性降低了。

上圖是一個長度為 16 bit 的陣列外加三個 hash function 所組成的 bloom filter,初始的陣列是空的,而我們會依序將特徵加入陣列,例如第一個特徵 A 依序送入三個 hash function 會個得到一個數值,就去把對應在陣列上面的值改成 1,例如下圖。

在這個結構底下,有比較大的陣列和比較多的 hash function 會有比較高的精準度,因為每個不同的特徵近來都會輸出到不同的陣列位子上。當然我們會加入不只一個特徵,所以可以想像的是越來越多的特徵加入時,可能會重複指到同一個陣列的位子,也就是發生碰撞 (collision) 了,而當陣列的 1 越來越多,這個 bloom filter 的精準度也會隨之下降。

下圖我們再加入一個特徵 B 進去這個 bloom filter。

由上圖可以注意一下,有發生了一個碰撞,在陣列位子 1 的地方,兩個特徵都有對應到。現在我們給定一個輸入 X 想知道他在不在這個 bloom filter 裡面,因此把 X 也送進那三個 hash function。

結果出來了,三個結果都指向陣列為 1 的地方,因此我們可以說這個 X 可能是我們要的結果,會說可能的原因很簡單,像剛剛 A 出來的結果是 (1, 3, 14) 而 B 是 (1, 7, 16),如果現在有一個 Y 出來的結果是 (1, 3, 16),他其實不是我們要的答案 (非 A 也非 B),但他也會被這個 bloom filter 認為是我們要的結果,因為他仍然都指向陣列為 1 的地方。不過如果是另外一種情況,三個結果只要一個不是指到 1 的地方,我們就可以保證確定他一定不是我們要的,如下圖。

看出來效果了嗎?假設我們現在只想要 A 和 B 兩個結果,在這套 bloom filter 之下,我們除了一定會找 A 和 B 之外,還會找到一些不相干的例如 C D E,如此魚目混珠可以讓別人不知道我們到底是要找 A B C D E 當中的哪些。如果我們把陣列變長,hash function 變多,每個特徵出來的結果就越來越獨特,不相干的可能結果也會越來越少,但也就有更高的機會被別人知道你要找的是 A 和 B 了。

回去 SPV node 的情況,我們現在的目的是希望 SPV node 在跟鄰居要 transaction 時不要暴露自己的目標 address,有了 bloom filter,他就不需要擔心他跟鄰居要的 transaction 會透露出節點裡面錢包所含的 address 了,因為 bloom filter 會讓我們多得到一些不相干的 transaction。

Conclusion

雖然比特幣的世界裡,節點有四種功能,分別是 Network、Blockchain、Mining 和 Wallet,基本上也不需要每個節點都同時有這四個功能。

當一個新的節點出現之後會發生什麼事?首先他會先透過 seed node 找到一些節點,這些節點會給他很多 IP 讓他去連結,而這些節點一但收到新的節點的 IP 也會幫忙傳遞下去,如此下來不用幾秒這個新節點就穩固的存在在整個網路之中了。

節點有開啟 Blockchain 功能就叫做 Full node,這個新節點如果為 Full node,他就會四處去跟剛建立好關係的鄰居去要一些他現在所缺少的區塊清單,有了清單之後他就可以慢慢建立自己的區塊鏈,直到追上大家的進度。然而並不是每種節點都有內建完整的區塊鏈,例如 SPV node 就只下載 block header,為輕量級的節點,好處是可以省下大量的硬碟空間,缺點就是他無法自行驗證某筆 transaction 的正確性,而必須仰賴其他 Full node 的幫助。

如果 SPV node 只想存跟自己錢包有關的 transaction,很可能會因為頻繁的索取某些特定 address 的 transaction,導致洩漏了 address 給外人知道,因此有一個叫做 bloom filter 的機制來達到魚目混珠的效果。

最後如果有還是不懂的或是講不清楚的地方歡迎來找我討論~如果有講錯的也請見諒並歡迎大力的更正我 Orz

雖然文章都只是一些我的閱讀心得,但如果你覺得我寫的文章有幫助到你踏入比特幣的世界,也歡迎透過比特幣贊助我 :D 1FwXwuNBA25fuJNBQ1L2iXnx23VHQBch3m

Reference

  1. Mastering Bitcoin

--

--