SPV、SPV节点和SPV钱包
一、什么是SPV
SPV是“Simplified Payment Verification”(簡(jiǎn)單支付驗(yàn)證)的縮寫。中本聰論文簡(jiǎn)要地提及了這一概念,指出:不運(yùn)行完全節(jié)點(diǎn)也可驗(yàn)證支付,用戶只需要保存所有的block header就可以了。用戶雖然不能自己驗(yàn)證交易,但如果能夠從區(qū)塊鏈的某處找到相符的交易,他就可以知道網(wǎng)絡(luò)已經(jīng)認(rèn)可了這筆交易,而且得到了網(wǎng)絡(luò)的多少個(gè)確認(rèn)。
按照中本聰?shù)脑?#xff0c;這里有個(gè)細(xì)節(jié)需要注意,SPV指的是“支付驗(yàn)證“,而不是“交易驗(yàn)證”。這兩種驗(yàn)證有很大區(qū)別。
“交易驗(yàn)證”非常復(fù)雜,涉及到驗(yàn)證是否有足夠余額可供支出、是否存在雙花、腳本能否通過等等,通常由運(yùn)行完全節(jié)點(diǎn)的礦工來完成。
“支付驗(yàn)證”則比較簡(jiǎn)單,只判斷用于“支付”的那筆交易是否已經(jīng)被驗(yàn)證過,并得到了多少的算力保護(hù)(多少確認(rèn)數(shù))。
考慮這樣一種情況,A收到來自B的一個(gè)通知,B聲稱他已經(jīng)從某某賬戶中匯款一定數(shù)額的錢給了A。去中心方式下,沒有任何人能證明B的可靠。接到這一通知,A如何能判斷B所說的是真的呢?
在比特幣系統(tǒng)中,這一通知是以一個(gè)固定格式的“交易”來實(shí)現(xiàn)的,該交易中包含B的匯款賬戶支票、B的簽名、匯給A的金額以及A的地址。
如果A想本人親自驗(yàn)證這筆交易,首先,A要遍歷區(qū)塊鏈賬本,定位到B的賬戶上,這樣才能查看B所給的賬戶支票上是否曾經(jīng)有足夠的金額;接下來,A要遍歷后續(xù)的所有賬本,看B是否已經(jīng)支出了這個(gè)賬戶支票上的錢給別人(是否存在雙花欺騙);然后還要驗(yàn)證腳本來判斷B是否擁有該賬戶的支配權(quán)。這一過程要求A必須得到完整的區(qū)塊鏈才行。
但是,如果A只想知道這筆支付是否已經(jīng)得到了驗(yàn)證(如果驗(yàn)證了就發(fā)貨),他可以依賴比特幣系統(tǒng)來快速驗(yàn)證。即,檢查發(fā)生此項(xiàng)支付的那筆交易是否已經(jīng)收錄于區(qū)塊鏈中,并得到了多少個(gè)確認(rèn)。
原理:block header中有三個(gè)關(guān)鍵字段,一是prev_block_hash(前一區(qū)塊的hash值,確保了區(qū)塊鏈所記錄的交易次序);二是bits(當(dāng)前區(qū)塊的計(jì)算難度), 三是merkle_root_hash(借助merkle tree算法,確保收錄與區(qū)塊中所有交易的真實(shí)性)。
驗(yàn)證某個(gè)交易是否真實(shí)存在時(shí),理論上,用戶可以通過以下方式進(jìn)行驗(yàn)證:
(為了簡(jiǎn)化模型,我們假設(shè)用tx_hash來定位block。這種方法有被“交易可鍛性”攻擊的風(fēng)險(xiǎn),實(shí)際應(yīng)用中可以根據(jù)output_point來定位。)
0. 從網(wǎng)絡(luò)上獲取并保存最長(zhǎng)鏈的所有block header至本地;
1. 計(jì)算該交易的hash值tx_hash;
2. 定位到包含該tx_hash所在的區(qū)塊,驗(yàn)證block header是否包含在已知的最長(zhǎng)鏈中;
3. 從區(qū)塊中獲取構(gòu)建merkle tree所需的hash值;
4. 根據(jù)這些hash值計(jì)算merkle_root_hash;
5. 若計(jì)算結(jié)果與block header中的merkle_root_hash相等,則交易真實(shí)存在。
6. 根據(jù)該block header所處的位置,確定該交易已經(jīng)得到多少個(gè)確認(rèn)。
優(yōu)點(diǎn):極大地節(jié)省存儲(chǔ)空間。減輕終端用戶的負(fù)擔(dān)。無論未來的交易量有多大,block header的大小始終不變,只有80字節(jié)。按照每小時(shí)6個(gè)的出塊速度,每年產(chǎn)出52560個(gè)區(qū)塊。當(dāng)只保存block header時(shí),每年新增的存儲(chǔ)需求約為4兆字節(jié),100年后累計(jì)的存儲(chǔ)需求僅為400兆,即使用戶使用的是最低端的設(shè)備,正常情況下也完全能夠負(fù)載。
問題:如何才能通過tx_hash定位到該交易所在的區(qū)塊? 以往的比特幣協(xié)議中缺少對(duì)此的支持。
?
二、比特幣錢包
在進(jìn)一步討論SPV的實(shí)現(xiàn)之前,先要說明一下比特幣錢包存放的是什么,錢包和私鑰之間是什么關(guān)系?
既然用到“錢包”一詞,那么應(yīng)該與我們?nèi)粘I钪惺褂玫腻X包有一定的相似之處。為了更直觀說明,我們與日常生活中所使用的錢包做一下對(duì)比。
日常生活中里面存放的可能是紙幣、支票、印鑒等等(為了簡(jiǎn)化說明,我們把銀行卡排除在外,使用銀行卡涉及到很多中間環(huán)節(jié),增加表述上的復(fù)雜度)。
用紙幣購物時(shí),
1. 從錢包中湊足若干張不同面值的紙幣,計(jì)算總面值是否大于所需金額以及應(yīng)找回多少零錢;
2. 將這些紙幣直接交給賣方;
3. 賣方驗(yàn)證這些紙幣的真?zhèn)?#xff1b;
4. 賣方計(jì)算這些紙幣的面值是否大于或等于商品價(jià)格,并找回相應(yīng)的零錢。
5. 將收到的零錢放回錢包。
比特幣的錢包里存放的相當(dāng)于是一張張標(biāo)有面值的“一次性支票”和對(duì)應(yīng)的“印鑒”。支付時(shí),
1. 用戶從錢包中取出若干張“一次性支票”,自己計(jì)算總面值是否大于所需金額以及應(yīng)找回多少零錢,注意要扣除比特幣系統(tǒng)所收取的手續(xù)費(fèi);
2. 給賣方開一張支票,注明賣方地址和支付金額;如果需要找零,給自己開一張找零支票(寫上自己的地址和找零金額);
3. 在每張從錢包中取出的支票上加蓋對(duì)應(yīng)的印鑒,確認(rèn)支付權(quán);
4. 將這些票據(jù)提交給比特幣系統(tǒng),比特幣系統(tǒng)驗(yàn)證支票的真?zhèn)魏椭Ц妒欠裼行А?br style="max-width:100%;" />5. 若比特幣系統(tǒng)驗(yàn)證通過,收款方將收到的支票放入錢包。用戶則將自己錢包中的已支付的支票丟棄(這些支票已經(jīng)被比特幣系統(tǒng)視為無效了,無法繼續(xù)使用),
即使是剛接觸比特幣的人,估計(jì)也能猜出“印鑒”指的是“私鑰”。但“一次性支票”是什么?
比特幣系統(tǒng)中,這種“一次性支票”的術(shù)語是UTXO,全稱是Unspent Transaction Outputs(未花費(fèi)的交易輸出)。區(qū)塊鏈?zhǔn)且粋€(gè)收錄所有歷史交易(Transaction)的總帳,每個(gè)區(qū)塊(block)中包含若干筆交易記錄。
每個(gè)交易記錄由兩部分構(gòu)成:資金來源(可以有多個(gè)來源)和資金去向(可以有多個(gè)去向),術(shù)語為Tx_in(交易輸入)和Tx_out(交易輸出)。也就是說,每筆交易TX包含有若干個(gè)Tx_in和若干個(gè)Tx_out。
除創(chuàng)世區(qū)塊中的交易(genesis block)外,每筆交易必須要有資金來源。資金來源有兩種,一種是挖礦獎(jiǎng)勵(lì)(依照固定算法實(shí)現(xiàn)的貨幣發(fā)行),出現(xiàn)在每個(gè)block的第一筆交易中;另一種是先前的交易中未曾使用的某個(gè)Tx_out(交易輸出),即UTXO。支出方要出示證據(jù)來證明自己對(duì)該Tx_out擁有所有權(quán),而比特幣系統(tǒng)則要驗(yàn)證該Tx_out是否真的未被花費(fèi)(是否是UTXO)以及支出方是否有權(quán)將其花費(fèi)。
資金去向(TX_out)包含兩個(gè)部分,一是傳遞的金額,二是支配權(quán)(誰可以動(dòng)用)。取款權(quán)通過比特幣的腳本系統(tǒng)來實(shí)現(xiàn)。若收款方地址是以1開頭的普通地址,則腳本中會(huì)包含地址所對(duì)應(yīng)公鑰的hash值(hash160),動(dòng)用款項(xiàng)時(shí)一般需要用對(duì)應(yīng)的私鑰進(jìn)行簽名;若收款方地址是以3開頭的多重簽名地址,則腳本中會(huì)包含某個(gè)特定腳本的hash值(hash160),動(dòng)用款項(xiàng)時(shí),一般需要依照特定的腳本,用多個(gè)私鑰來簽名。
用戶錢包中的比特幣實(shí)際上是用戶擁有支配權(quán)的、且尚未花費(fèi)的Tx_out中記錄的金額總和,即用戶可支配的所有UTXO金額之和。
完整的錢包中應(yīng)存有若干個(gè)UTXO和支配每個(gè)UTXO時(shí)所對(duì)應(yīng)的私鑰。當(dāng)然,有時(shí)從安全角度出發(fā),可能會(huì)把錢包劃分為兩個(gè)部分,在線錢包中只有UTXO,而離線錢包只存私鑰。
但是,用戶怎么才能把自己的所有UTXO都放到錢包中呢?
?
三、用戶如何收錄自己的UTXO
(一)去中心化方式:
實(shí)現(xiàn)方法:
1. 在本地建立一個(gè)用于存儲(chǔ)UTXO的數(shù)據(jù)庫;
2. 設(shè)置區(qū)塊掃描起始點(diǎn)(區(qū)塊鏈上的掃描起始高度),從該點(diǎn)開始,依次下載該點(diǎn)之后所有區(qū)塊(block)的完整數(shù)據(jù)。
3. 解析每個(gè)block的所有TX數(shù)據(jù),依次讀取每個(gè)Tx_in的prev_Tx_out([tx hash] + [tx_out的序號(hào)]),檢索UTXO數(shù)據(jù)庫中是否存在這個(gè)Tx_out,如果有,則從UTXO數(shù)據(jù)庫中刪除(或標(biāo)記刪除)。
4. 依次解析每個(gè)Tx_out的腳本,若與用戶相關(guān),則將[tx hash] + [Tx_out的序號(hào)]以及整個(gè)tx_out的內(nèi)容記錄到UTXO數(shù)據(jù)庫;
備注:如果錢包中只有新創(chuàng)建的私鑰,可以從最新的區(qū)塊開始掃描(由于私鑰發(fā)生碰撞的可能性可以視為0,在你告知他人比特幣地址之前,該私鑰對(duì)應(yīng)的地址上不會(huì)有任何收入)
優(yōu)點(diǎn):不依賴于信任;數(shù)據(jù)準(zhǔn)確。
缺點(diǎn):速度慢,需要從比特幣網(wǎng)絡(luò)下載大量數(shù)據(jù),對(duì)網(wǎng)絡(luò)造成的壓力大。
(二)中心化方式:
1. 某個(gè)中心化機(jī)構(gòu)(或個(gè)人)運(yùn)行完整的比特幣節(jié)點(diǎn),建立一個(gè)收錄所有UTXO的數(shù)據(jù)庫。
2. 用戶用中心化機(jī)構(gòu)提供的api來請(qǐng)求與自己有關(guān)的UTXO數(shù)據(jù)。
優(yōu)點(diǎn):速度快,不拖累比特幣網(wǎng)絡(luò);
缺點(diǎn):依賴于信任;數(shù)據(jù)不一定準(zhǔn)確(有可能中心化服務(wù)器出現(xiàn)故障,或是與中心服務(wù)器的會(huì)話被劫持,數(shù)據(jù)遭篡改)
?
四、瘦客戶端、SPV輕錢包和SPV節(jié)點(diǎn)是什么?
瘦客戶端:參考了SPV的機(jī)制,在監(jiān)聽收款地址時(shí),客戶端在本地只需保存與用戶可支配交易相關(guān)的數(shù)據(jù)。因?yàn)楸镜貨]有完整的區(qū)塊鏈,缺少發(fā)送方的相關(guān)數(shù)據(jù),客戶端無法親自驗(yàn)證交易是否合法,只能判斷交易是否是被收錄,并且得到了幾個(gè)確認(rèn)。這與SPV有很多相似之處,因而很多場(chǎng)合下這種瘦客戶端也常被成為是“SPV客戶端”,不過,與SPV的區(qū)別是,在去中心化方式下,這些客戶端仍需下載每個(gè)新區(qū)塊的全部數(shù)據(jù)并進(jìn)行解析,只是無需在本地保存全部數(shù)據(jù)而已。
“輕錢包”是用瘦客戶端模式實(shí)現(xiàn)的錢包,因?yàn)椴淮鎯?chǔ)完整區(qū)塊鏈,就涉及到如何獲取UTXO的問題。不同的開發(fā)者可能有各自的實(shí)現(xiàn)方法,但從效率上考慮,往往多用中心化的方式來實(shí)現(xiàn)。
SPV節(jié)點(diǎn):支持使用布隆過濾器(Bloom filter)在快速檢索并返回相關(guān)數(shù)據(jù)的節(jié)點(diǎn)。
SPV在實(shí)現(xiàn)上涉及到一個(gè)問題,如何才能通過交易特征值(比如tx_hash)來定位到該支付交易所在的區(qū)塊?用中心化方式來實(shí)現(xiàn)很好解決,但用去中心化就不那么簡(jiǎn)單了,因?yàn)橐酝谋忍貛畔到y(tǒng)協(xié)議中缺少對(duì)SPV的支持。去中心方式下獲取數(shù)據(jù)必須做到以下兩點(diǎn):1. 客戶端和節(jié)點(diǎn)間采用公認(rèn)的協(xié)議通信;2. 數(shù)據(jù)真實(shí)性的自驗(yàn)證——客戶端無需信任節(jié)點(diǎn)是否是誠(chéng)實(shí)節(jié)點(diǎn),返回的數(shù)據(jù)本身可以證明 該數(shù)據(jù)的真實(shí)性。
原有協(xié)議中,可以通過getheaders命令來獲取block headers,可以通過getdata命令支持獲取指定的block, 但不支持通過tx_hash反向查找所在的block。為了定位block,客戶端往往不得不下載整個(gè)區(qū)塊鏈。
新的比特幣協(xié)議中增加了Bloom filter的功能,Bloom filter解決了客戶端檢索的問題,原理是Bloom filter可以快速判斷出某檢索值一定不存在于某個(gè)指定的集合,從而可以過濾掉大量無關(guān)數(shù)據(jù),減少客戶端不必要的下載量。這樣的節(jié)點(diǎn)可以為去中心化方式SPV查詢提供必要的支持。
前文提到,SPV的用途是驗(yàn)證某個(gè)支付是否確實(shí)存在,并得到多少個(gè)確認(rèn)。而錢包的用途則是用于管理自己的資產(chǎn)以及進(jìn)行支付。簡(jiǎn)言之,SPV的應(yīng)用場(chǎng)合往往是為發(fā)貨做準(zhǔn)備(知道錢到帳了),“輕錢包”的應(yīng)用場(chǎng)合往往是數(shù)錢或花錢。雖然“輕錢包”中部分借鑒了SPV的機(jī)制,但和SPV是完全不用的應(yīng)用方向,直接把這兩個(gè)詞連起略顯牽強(qiáng)。這種錢包要么采用中心化的方式——提高了效率,但引入了信任的風(fēng)險(xiǎn);要么采用去中心化方式——無需信任,但效率低,且增加網(wǎng)絡(luò)的負(fù)擔(dān)。
SPV節(jié)點(diǎn)的出現(xiàn)使以去中心化方式來實(shí)現(xiàn)高效、低負(fù)荷的“輕錢包”成為了可能。筆者認(rèn)為將基于SPV節(jié)點(diǎn)來實(shí)現(xiàn)的”輕錢包”簡(jiǎn)稱為“SPV輕錢包”可能會(huì)更為合適些。
文/chehw
2015.3.23
http://www.8btc.com/spv_spv_node_and_spv_wallet
總結(jié)
以上是生活随笔為你收集整理的SPV、SPV节点和SPV钱包的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 简单支付验证(SPV)与创新
- 下一篇: 以太坊Sharding FAQ