SPV、SPV节点和SPV钱包


一、什么是SPV




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兆,即便用户运用的是最低端的设备,正常状况下也彻底能够负载。

问题:怎样才干经过tx_hash定位到该买卖地点的区块? 以往的比特币协议中短少对此的支撑。


二、比特币钱包

在进一步讨论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都放到钱包中呢?


三、用户怎样录入自己的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轻钱包”可能会更为合适些。

chehw2015.3.19

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注