輕錢包

輕錢包

輕錢包(SPV)是“Simplified Payment Verification”(簡單支付驗證)的縮寫。中本聰論文簡要地提及了這一概念,指出:不運行完全節點也可驗證支付,用戶只需要保存所有的block header就可以了。用戶雖然不能自己驗證交易,但如果能夠從區塊鏈的某處找到相符的交易,他就可以知道網路已經認可了這筆交易,而且得到了網路的多少個確認。

基本信息

簡介

輕錢包(SPV)是“Simplified Payment Verification”(簡單支付驗證)的縮寫。中本聰論文簡要地提及了這一概念,指出:不運行完全節點也可驗證支付,用戶只需要保存所有的block header就可以了。用戶雖然不能自己驗證交易,但如果能夠從區塊鏈的某處找到相符的交易,他就可以知道網路已經認可了這筆交易,而且得到了網路的多少個確認。

按照中本聰的原文,有個細節需要注意,SPV指的是“支付驗證“,而不是“交易驗證”。這兩種驗證有很大區別。

"交易驗證”非常複雜,涉及到驗證是否有足夠餘額可供支出、是否存在雙花、腳本能否通過等等,通常由運行完全節點的礦工來完成。

“支付驗證”則比較簡單,只判斷用於“支付”的那筆交易是否已經被驗證過,並得到了多少的算力保護(多少確認數)。
考慮這樣一種情況,A收到來自B的一個通知,B聲稱他已經從某某賬戶中匯款一定數額的錢給了A。去中心方式下,沒有任何人能證明B的可靠。接到這一通知,A如何能判斷B所說的是真的呢?
在比特幣系統中,這一通知是以一個固定格式的“交易"來實現的,該交易中包含B的匯款賬戶、B的簽名、匯給A的金額以及A的地址。
如果A想本人親自驗證這筆交易,首先,A要遍歷區塊鏈賬本,定位到B的賬戶上,這樣才能查看B所給的賬戶上是否曾經有足夠的金額;接下來,A要遍歷後續的所有賬本,看B是否已經支出了這個賬戶上的錢給別人(是否存在雙花欺騙);然後還要驗證腳本來判斷B是否擁有該賬戶的支配權。這一過程要求A必須得到完整的區塊鏈才行。
但是,如果A只想知道這筆支付是否已經得到了驗證(如果驗證了就發貨),他可以依賴比特幣系統來快速驗證。即,檢查發生此項支付的那筆交易是否已經收錄於區塊鏈中,並得到了多少個確認。
原理:block header中有三個關鍵欄位,一是prev_block_hash(前一區塊的hash值,確保了區塊鏈所記錄的交易次序);二是bits(當前區塊的計算難度), 三是merkle_root_hash(藉助merkle tree算法,確保收錄與區塊中所有交易的真實性)。
驗證某個交易是否真實存在時,理論上,用戶可以通過以下方式進行驗證:
0. 從網路上獲取並保存最長鏈的所有block header至本地;
1. 計算該交易的hash值tx_hash;
2. 定位到包含該tx_hash所在的區塊,驗證block header是否包含在已知的最長鏈中;
3. 從區塊中獲取構建merkle tree所需的hash值;
4. 根據這些hash值計算merkle_root_hash;
5. 若計算結果與block header中的merkle_root_hash相等,則交易真實存在。
6. 根據該block header所處的位置,確定該交易已經得到多少個確認。
優點:極大地節省存儲空間。減輕終端用戶的負擔。無論未來的交易量有多大,block header的大小始終不變,只有80位元組。按照每小時6個的出塊速度,每年產出52560個區塊。當只保存block header時,每年新增的存儲需求約為4兆位元組,100年後累計的存儲需求僅為400兆,即使用戶使用的是最低端的設備,正常情況下也完全能夠負載。

比特幣錢包



討論SPV的實現之前,先要說明一下比特幣的錢存放的是什麼,錢包和私鑰之間是什麼關係?
既然用到“錢包”一詞,那么應該與我們日常生活中使用的錢包有一定的相似之處。為了更直觀說明,我們與日常生活中所使用的錢包做一下對比。
日常生活中裡面存放的可能是紙幣、支票、印鑑等等(為了簡化說明,我們把銀行卡排除在外,使用銀行卡涉及到很多中間環節,增加表述上的複雜度)。
用紙幣購物時,
1. 從錢包中湊足若干張不同面值的紙幣,計算總面值是否大於所需金額以及應找回多少零錢;
2. 將這些紙幣直接交給賣方;
3. 賣方驗證這些紙幣的真偽;
4. 賣方計算這些紙幣的面值是否大於或等於商品價格,並找回相應的零錢。
5. 將收到的零錢放回錢包。
比特幣的錢包里存放的相當於是一張張標有面值的“一次性支票”和對應的“印鑑”。支付時:
1. 用戶從錢包中取出若干張“一次性支票”,自己計算總面值是否大於所需金額以及應找回多少零錢,注意要扣除比特幣系統所收取的手續費;
2. 給賣方開一張支票,註明賣方地址和支付金額;如果需要找零,給自己開一張找零支票(寫上自己的地址和找零金額);
3. 在每張從錢包中取出的支票上加蓋對應的印鑑,確認支付權;
4. 將這些票據提交給比特幣系統,比特幣系統驗證支票的真偽和支付是否有效;
5. 若比特幣系統驗證通過,收款方將收到的支票放入錢包。用戶則將自己錢包中的已支付的支票丟棄(這些支票已經被比特幣系統視為無效了,無法繼續使用),即使是剛接觸比特幣的人,估計也能猜出“印鑑”指的是“私鑰”。

一次性支票

比特幣系統中,這種“一次性支票”的術語是UTXO,全稱是Unspent Transaction Outputs(未花費的交易輸出)。區塊鏈是一個收錄所有歷史交易(Transaction)的總帳,每個區塊(block)中包含若干筆交易記錄。
每個交易記錄由兩部分構成:資金來源(可以有多個來源)和資金去向(可以有多個去向),術語為Tx_in(交易輸入)和Tx_out(交易輸出)。也就是說,每筆交易TX包含有若干個Tx_in和若干個Tx_out。
除創世區塊中的交易(genesis block)外,每筆交易必須要有資金來源。資金來源有兩種,一種是挖礦獎勵(依照固定算法實現的貨幣發行),出現在每個block的第一筆交易中;另一種是先前的交易中未曾使用的某個Tx_out(交易輸出),即UTXO。支出方要出示證據來證明自己對該Tx_out擁有所有權,而比特幣系統則要驗證該Tx_out是否真的未被花費(是否是UTXO)以及支出方是否有權將其花費。
資金去向(TX_out)包含兩個部分,一是傳遞的金額,二是支配權(誰可以動用)。取款權通過比特幣的腳本系統來實現。若收款方地址是以1開頭的普通地址,則腳本中會包含地址所對應公鑰的hash值(hash160),動用款項時一般需要用對應的私鑰進行簽名;若收款方地址是以3開頭的多重簽名地址,則腳本中會包含某個特定腳本的hash值(hash160),動用款項時,一般需要依照特定的腳本,用多個私鑰來簽名。
用戶錢包中的比特幣實際上是用戶擁有支配權的、且尚未花費的Tx_out中記錄的金額總和,即用戶可支配的所有UTXO金額之和。
完整的錢包中應存有若干個UTXO和支配每個UTXO時所對應的私鑰。當然,有時從安全形度出發,可能會把錢包劃分為兩個部分,線上錢包中只有UTXO,而離線錢包只存私鑰。

用戶如何收錄自己的UTXO

(一)去中心化方式:
實現方法:
1. 在本地建立一個用於存儲UTXO的資料庫;
2. 設定區塊掃描起始點(區塊鏈上的掃描起始高度),從該點開始,依次下載該點之後所有區塊(block)的完整數據。
3. 解析每個block的所有TX數據,依次讀取每個Tx_in的prev_Tx_out([tx hash] + [tx_out的序號]),檢索UTXO資料庫中是否存在這個Tx_out,如果有,則從UTXO資料庫中刪除(或標記刪除)。
4. 依次解析每個Tx_out的腳本,若與用戶相關,則將[tx hash] + [Tx_out的序號]以及整個tx_out的內容記錄到UTXO資料庫;
備註:如果錢包中只有新創建的私鑰,可以從最新的區塊開始掃描(由於私鑰發生碰撞的可能性可以視為0,在你告知他人比特幣地址之前,該私鑰對應的地址上不會有任何收入)
優點:不依賴於信任;數據準確。
缺點:速度慢,需要從比特幣網路下載大量數據,對網路造成的壓力大。
(二)中心化方式:
1. 某箇中心化機構(或個人)運行完整的比特幣節點,建立一個收錄所有UTXO的資料庫。
2. 用戶用中心化機構提供的api來請求與自己有關的UTXO數據。
優點:速度快,不拖累比特幣網路;
缺點:依賴於信任;數據不一定準確(有可能中心化伺服器出現故障,或是與中心伺服器的會話被劫持,數據遭篡改)。

瘦客戶端、SPV輕錢包和SPV節點

瘦客戶端:參考了SPV的機制,在監聽收款地址時,客戶端在本地只需保存與用戶可支配交易相關的數據。因為本地沒有完整的區塊鏈,缺少傳送方的相關數據,客戶端無法親自驗證交易是否合法,只能判斷交易是否是被收錄,並且得到了幾個確認。這與SPV有很多相似之處,因而很多場合下這種瘦客戶端也常被成為是“SPV客戶端”,不過,與SPV的區別是,在去中心化方式下,這些客戶端仍需下載每個新區塊的全部數據並進行解析,只是無需在本地保存全部數據而已。
“輕錢包”是用瘦客戶端模式實現的錢包,因為不存儲完整區塊鏈,就涉及到如何獲取UTXO的問題。不同的開發者可能有各自的實現方法,但從效率上考慮,往往多用中心化的方式來實現。
SPV節點:支持使用布隆過濾器(Bloom filter)在快速檢索並返回相關數據的節點。這樣的節點可以為去中心化方式SPV查詢提供必要的支持。
SPV在實現上涉及到一個問題,如何才能通過tx_hash來定位到該支付交易所在的區塊?用中心化方式來實現很好解決,但用去中心化就不那么簡單了,因為以往的比特幣系統協定中缺少對SPV的支持。原有協定中,可以通過getheaders命令來獲取block headers,可以通過getdata命令支持獲取指定的block, 但不支持通過tx_hash反向查找所在的block。為了定位block,客戶端往往不得不下載整個區塊鏈。Bloom filter解決了客戶端檢索的問題,原理是Bloom filter可以快速判斷出某檢索值一定不存在於某個指定的集合,從而可以過濾掉大量無關數據,減少客戶端不必要的下載量。
SPV的用途是驗證某個支付是否確實存在,並得到多少個確認。而錢包的用途則是用於管理自己的資產以及進行支付。簡言之,SPV的套用場合往往是為發貨做準備(知道錢到帳了),“輕錢包”的套用場合往往是數錢或花錢。雖然“輕錢包”中部分借鑑了SPV的機制,但和SPV是完全不用的套用方向,直接把這兩個詞連起略顯牽強。這種錢包要么採用中心化的方式——提高了效率,但引入了信任的風險;要么採用去中心化方式——無需信任,但效率低,且增加網路的負擔。
SPV節點的出現使以去中心化方式來實現高效、低負荷的“輕錢包”成為了可能。將基於SPV節點來實現的"輕錢包"簡稱為“SPV輕錢包”可能會更為合適些。

相關詞條

相關搜尋

熱門詞條

聯絡我們