双花:就是双重支付,一笔资金被花费了两次。
在传统的交易中,因为有银行这样的中心化机构,所以是不会存在双花问题的:每一笔支付都将从你的银行账户中扣除相应的资金,所有的明细在银行都有记录。但是在比特币中,没有账户的概念,而是引入了UTXO,即未花费交易输出。因为没有银行这样的中心化机构的保证,当发生一笔交易时就可能存在着双花的危险:比方说A有一个比特币,然后他同时构造两笔交易T1和T2来花费这1个比特币,其中一个给了B,从B那里买件衣服,一个给了C,从C那里买双鞋。如果不引入某种机制来避免这种情况,那作为数字货币的比特币将没有任何存在的意义。
1.正常情况:
假设A构造了两笔交易T1和T2,将价值1 BTC的UTXO分别转给了B和C,妄图同时从B和C那里获得好处。然后A几乎同时将构造好的这两笔交易广播至网络。
假设网络中的矿工节点先收到了交易T1,发现这笔交易的资金来源确实没有被花费过,于是将T1加入到自己的内存交易池中等待打包进区块。
大部分情况下,这个矿工节点会在不久后又收到交易T2,此时因为T2所指向的交易输入与已经加入交易池的T1相同,于是矿工节点会拒绝处理该交易。网络中其他的矿工节点都类似,因此A发起的双花尝试将会失败。
2.分叉情况:
假设矿工节点M1和M2几乎同时挖出了区块,并且很不幸M1挖到的区块只收到了交易T1,而M2挖到的区块只收到了交易T2,这样交易T1和T2被分别打包进两个区块。因为这两个区块是同时被挖出的,于是造成了区块链的分叉。
网络中某些节点(可能是离M1近的)先收到了M1打包的区块BLK1,于是用该区块延长自己的区块链。而另外一些节点(邻近M2的)则先收到M2打包的区块BLK2,用该区块延长自己的区块链。于是整个区块链网络中呈现出了不一致的问题:
像这种不一致问题,一般只需要一个确认期就能得到解决:假设随后又收到新区块,而新区块以BLK1作为父区块,那么之前用BLK1延长自己区块链的节点,只需要将新区块链接到自己的区块链上,而之前以BLK2延长自己区块链的节点,则需要切换到新的最长链上,如下图:
因此在出现分叉的情况下,通常也只需要等待一个区块的确认时间,网络节点中的区块链就可以重新一致。在这个例子中,经过一个区块的确认期以后,B最终确认自己收到A的1 BTC,而因为包含有转账给C的交易T2的区块BLK2位于备用链上,因此无法通过支付验证。A的双花尝试也以失败告终。
3.经过6个区块的确认才安全
上面提到分叉情况,一般只要经过1个区块的确认时间基本上就能确保“相对的安全”。而在比特币中,对于很小额的支付,为了提高交易速度,一般也就是等1个区块的确认即可。但是注意这里说的是“相对安全”,对于数额特别大的交易,1个区块的确认远远不够。
我们考虑上面提到的分叉情况:假设经过1个区块的确认后,B知道了A给他的1 BTC确实已经位于链上,于是发货给A。此时A及其同伙掌握着很大的一部分算力,A通知其同伙开始使劲挖矿延长备用链(攻击链)。当A最终成功的使攻击链长度(累计工作量)超过当前主链长度时,会再一次导致网络中的节点切换主链,如下面的示意图:
于是包含了A转给C的交易T2的区块BLK2又位于了主链之上,此时A通知C钱已到账。C做支付验证也没问题,于是C给A发货,A的双花攻击成功。
因此对于额度稍大的交易,必须要等待6个区块的确认才能保证安全。因为攻击者要想构造攻击链追上已经经过6个区块确认的主链,需要花费的算力成本非常大,很有可能得不偿失。
参考链接:https://blog.csdn.net/ztemt_sw2/article/details/83543434