區塊鏈鼻祖比特幣之12:(SPV) 節點與Bloom 過濾器
(SPV) 節點
並非所有的節點都有能力儲存完整的區塊鏈。許多比特幣客戶端被設計成運行在空間和功率受限的裝置上,如智慧電話、平板電腦、嵌入式系統等。對於這樣的裝置,通過簡化的支付驗證(SPV)的方式可以使它們在不必儲存完整區塊
鏈的情況下進行工作。這種型別的客端被稱為 SPV 客戶端或輕量級客戶端。隨著比特幣的使用熱潮,SPV 節點逐漸變成比特幣節點(尤其是比特幣錢包)所採用的最常見的形式。SPV 節點只需下載區塊頭,而不用下載包含在每個區塊中的交易資訊。由此產生的不含交易資訊的區塊鏈,大小隻有完整區塊鏈的 1/1000。SPV 節點不能構建所有可用於消費的 UTXO 的全貌,這是由於它們並不知道網路上所有交易SPV 節點一直等待,直到序號從 300,001 到 300,006 的六個區塊堆疊在該交易所在的區塊之上,並通過確立交易的深度是在第 300,006 區塊~第 300,001 區塊之下來驗證交易的有效性。事實上,如果網路中的其他節點都接受了第300,000 區塊,並通過足夠的工作在該塊之上又生成了六個區塊,根據代理閘道器協議,就可以證明該交易不是雙重支付。如果一個交易實際上不存在,SPV 節點不會誤認為該交易存在於某區塊中。SPV 節點會通過請求 merkle 路徑證明以及驗證區塊鏈中的工作量證明,來證實交易的存在性。可是,一個交易的存在是可能對 SPV 節點“隱藏”的。SPV 節點毫無疑問可以證實某個交易的存在性,但它不能驗證某個交易(譬如同一個UTXO 的雙重支付)不存在,這是因為 SPV 節點沒有一份關於所有交易的記錄。這個漏洞會被針對 SPV 節點的拒絕服務攻擊或雙重支付型攻擊所利用。為了防御這些攻擊,SPV 節點需要隨機連線到多個節點,以增加與至少一個可靠節點相連線的概率。這種隨機連線的需求意味著 SPV 節點也容易受到網路分割槽攻擊或 Sybil 攻擊。在後者情況中,SPV 節點被連線到虛假節點或虛假網路中,沒有通向可靠節點或真正的比特幣網路的連線。在絕大多數的實際情況中,具有良好連線的 SPV 節點是足夠安全的,它在資源需求、實用性和安全性之間維持恰當的平衡。當然,如果要保證萬無一失的安全性,最可靠的方法還是執行完整區塊鏈的節點。
Bloom 過濾器
Bloom 過濾器是一個允許使用者描述特定的關鍵詞組合而不必精確表述的基於概率的過濾方法。它能讓使用者在有效搜尋關鍵詞的同時保護他們的隱私。在SPV 節點裡,這一方法被用來向對等節點發送交易資訊查詢請求,同時交易地址不會被暴露。我們之前的例子,一位手中沒有地圖的遊客需要詢問去特定地方的路線。如果他向陌生人詢問“教堂街 23 號在哪裡”,不經意之間,他就暴露了自己的目的地。Bloom 過濾器則會這樣問,附近有帶‘堂’字的街道嗎?”這樣的問法包含了比之前略少的關鍵詞。這位遊客可以自己選擇包含資訊的多少,比如 “以‘堂街’結尾”或者“‘教’字開頭的街道”。如果他問得越少,得到了更多可能的地址,隱私得到了保護,但這些地址裡面不乏無關的結果;如果他問得非常具體,他在得到較準確的結果的同時也暴露了自己的隱私。Bloom 過濾器可以讓 SPV 節點指定交易的搜尋模式,該搜尋模式可以基於準確性或私密性的考慮被調節。一個非常具體的 Bloom 過濾器會生成更準確的結果,但也會顯示該使用者錢包裡的使用的地址;反之,如果過濾器只包含簡單的關鍵詞,更多相應的交易會被搜尋出來,在包含若干無關交易的同時有著更高的私密性。首先,SPV 節點會初始化一個不會匹配任何關鍵詞的“空白”Bloom 過濾器。接下來,SPV 節點會建立一個包含錢包中所有地址資訊的列表,並建立一個與每個地址相對應的交易輸出相匹配的搜尋模式。通常,這種搜尋模式是一個向公鑰付款的雜湊指令碼、,該指令碼是一個會出現在每一個向公鑰雜湊地址付款的交易中的鎖定指令碼。如果 SPV 節點需要追蹤 P2SH 地址餘額,搜尋模式就會變成 P2SH 指令碼。然後,SPV 節點會把每一個搜尋模式新增至 Bloom 過濾器裡,這樣只要關鍵詞出現在交易中就能夠被過濾器識別出來。最後,對等節點會用收到的 Bloom 過濾器來匹配傳送至 SPV 節點的交易。Bloom 過濾器的實現是由一個可變長度(N)的二進位制陣列(N 位二進位制數構成一個位域)和數量可變(M)的一組雜湊函式組成。。這些雜湊函式的輸出值始終在 1 和 N 之間,該數值與二進位制陣列相對應。並且該函式為確定性函式,也就是說任何一個使用相同 Bloom 過濾器的節點通過該函式都能對特定輸入得到同一個的結果。Bloom 過濾器的準確性和私密效能通過改變長度(N)和哈希函式的數量(M)來調節。
Bloom 過濾器數組裡的每一個數的初始值為零。關鍵詞被加到 Bloom 過濾器中之前,會依次通過每一個雜湊函式運算一次。該輸入經第一個雜湊函式運算後得到了一個在 1 和 N 之間的數,它在該陣列(編號依次為 1 至 N)中所對應的位被置為 1,從而把雜湊函式的輸出記錄下來。接著再進行下一個雜湊函式的運算,把另外一位置為 1;以此類推。當全部 M 個雜湊函式都運算過之後,一共有 M 個位的值從 0 變成了 1,這個關鍵詞也被“記錄”在了 Bloom 過濾器裡。圖顯示簡易 Bloom 過濾器新增關鍵詞“A”。
增加第二個關鍵是就是簡單地重複之前的步驟。關鍵詞依次通過各雜湊函式運算之後,相應的位變為 1,Bloom 過濾器則記錄下該關鍵詞。需要注意的是,當Bloom 過濾器裡的關鍵詞增加時,它對應的某個雜湊函式的輸出值的位可能已經是 1 了,這種情況下,該位不會再次改變。也就是說,隨著更多的關鍵詞指向了重複的位,Bloom 過濾器隨著位 1 的增加而飽和,準確性也因此降低了。該過濾器之所以是基於概率的資料結構,就是因為關鍵詞的增加會導致準確性的降低。準確性取決於關鍵字的數量以及陣列大小(N)和雜湊函式的多少(M)。更大的陣列和更多的雜湊函式會記錄更多的關鍵詞以提高準確性。而小的陣列及有限的雜湊函式只能記錄有限的關鍵詞從而降低準確性。
圖顯示了向該簡易 Bloom 過濾器裡增加第二個關鍵詞“B”。
為測試某一關鍵詞是否被記錄在某個 Bloom 過濾器中,我們將該關鍵詞逐一代入各雜湊函式中運算,並將所得的結果與原陣列進行對比。如果所有的結果對應的位都變為了 1,則表示這個關鍵詞有可能已被該過濾器記錄。之所以這一結論並不確定,是因為這些位元組 1 也有可能是其他關鍵詞運算的重疊結果。簡單來說,Bloom 過濾器正匹配代表著“可能是”。下圖是一個驗證關鍵詞“X”是否在前述 Bloom 過濾器中的圖例。相應的位元位都被置為 1,所以這個關鍵詞很有可能是匹配的。
若結果為或然正匹配,則表示“可能是”。另一方面,如果我們代入關鍵詞計算後的結果某位為 0,說明該關鍵詞並沒有被記錄在過濾器裡。負匹配的結果不是可能,而是一定。也就是說,負匹配代表著“一定不是”。下圖是一個驗證關鍵詞“Y”是否存在於簡易 Bloom 過濾器中的圖例。圖中某個結果欄位為 0,該欄位一定沒有被匹配。
Bloom 過濾器被用來過濾 SPV 節點從對等節點裡收到的交易資訊。SPV 會建立一個只能和 SPV 節點錢包裡的地址匹配的過濾器。隨後,SPV 節點會向對等節點發送一條包含需在該連線中使用的過濾器的 filterload 訊息。當過濾器建好之後,對等節點將每個交易的輸出值代入過濾器中驗證。那些正匹配的交易會被傳送回 SPV 節點。為迴應來自 SPV 節點的 getdata 資訊,對等節點會發出一條只含有和過濾器匹配的區塊的區塊頭資訊,以及與之相匹配的交易的 merkle 樹。這一對等節點還會發出一條相匹配的交易的 tx 訊息。這個節點能夠通過傳送一條 filteradd 資訊來向它的 Bloom 過濾器增加關鍵詞,也能夠傳送 filterclear 資訊來清除整個過濾器。因為不能直接從過濾器裡刪除關鍵詞,所以如果某關鍵詞不再需要,節點必須通過清除和增加來替換原有的過濾器。
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN