区块链(block chain):一种分布式数据库技术。以区块为单位存储数据,区块们以哈希链的形式串联,因此防伪。
- 区块链起源于比特币(BTC),用于记录交易信息,每笔交易相当于 SQL 数据库的一个事务。
- 本文主要分析比特币协议中的区块链原理(协议更新之后,一些细节可能变化)。
- 参考资料:
区块结构
挖矿难度
- 矿工打包新区块时,需要尝试指定 nonce 值,比如穷举。如果使得当前 header 的哈希值小于等于 target threshold ,则有权打包该区块,被其他矿工承认。
- SHA256 哈希值的长度为 32 bytes ,而 target threshold 以有损压缩形式存储为 nBits ,长度为 4 bytes 。
- 例:根据 nBits 计算出 target threshold
>>> nBits = int('0x170cfecf', 16)
>>> target = 256**(int('0x17', 16) - 3) * int('0x0cfecf', 16)
>>> '0x' + "{:064x}".format(target)
'0x0000000000000000000cfecf0000000000000000000000000000000000000000'
- 可见 nBits 第一个字节的值越大,会使 taget 越大,开头连续的 0 越少,因此挖矿难度越小。
- difficulty 表示挖矿难度。
- 计算公式如下:
diffculty = difficulty_1_target / target
- 可见 difficulty 与 target 成反比,取值越小则挖矿难度越小,最小为 1 。
- difficulty_1_target 表示区块链的初始难度,是一个常数:
>>> difficulty_1_target = 2**(256-32)-1
>>> '0x' + "{:064x}".format(difficulty_1_target)
'0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
>>> difficulty_1_target / target
21659675333681.926
- 当 difficulty 为 1 时,target 达到允许的最大值 ‘0x1d00FFFF’ 。因为有损压缩丢失了右侧的所有 ‘0xF’ ,所以有的程序会将 difficulty_1_target 计算成偏小的值:
>>> _target = 256**(int('0x1d', 16) - 3) * int('0x00FFFF', 16)
>>> '0x' + "{:064x}".format(_target)
'0x00000000ffff0000000000000000000000000000000000000000000000000000'
>>> _target / target
21659344833264.848
- 丢失右侧 ‘0xF’ 的 difficulty_1_target 常用于快速估算难度,称为 bdiff(Bitcoin difficulty)。
- 标准的 difficulty_1_target 常用于正式挖矿,称为 pdiff(Pool difficulty)。
- 例:根据 nBits 估算出 difficulty
>>> nBits = int('0x170cfecf', 16)
>>> difficulty = 256**(29 - (nBits >> 24))*(65535.0 / ((float)(nBits & 0xFFFFFF)))
>>> difficulty
21659344833264.848
- BTC 预计每隔 10 分钟生成一个新区块。为了维持这一速率,会每隔 2016 个区块调整一次挖矿难度,重新计算 nBits :
expected_time = 2016*10
actual_time = ...
new_difficulty = old_difficulty * ( actual_time / expected_time )
new_nBits = ...
- 理论上,SHA256 哈希值有 2^256 种可能性,而 nonce 只有 2^32 种可能性,因此可能穷举 nonce 的所有值之后依然不满足 target threshold 。
账户
交易
sigScript
:签名脚本(Signature Script,sigScript)。
- sigScript 包含以下内容:
- pubKey :账户公钥
- sig :使用账户私钥,生成交易数据的数字签名。
- 交易延展性(Transaction Malleability)攻击
- :一种攻击方式,指改变未打包交易中的签名,使得交易的哈希值改变,导致引用该交易 txid 的其它交易失效。
- 由于椭圆曲线的对称性,可以计算出两个有效的签名,还可以根据任意一个签名推算出另一个签名。
- 常见的解决办法:
- 等待一个交易被打包,再引用它的 txid 。但这就不能实现闪电交易。
- 规定只采用取值较小的那个签名。
- 使用 SegWit 。
pkScript
:公钥脚本(Pubkey Script,pkScript),采用一种基于堆栈的脚本语言,包含一些指令。
隔离见证
:隔离见证,一种 BTC 的扩容方案,属于软分叉升级。
合约交易
多重签名
:多重签名(multi-signature,multisig),一种基于 P2SH 的交易方式。
- 原理:将 BTC 转账到一个 P2SH 地址,通过 pkScript 指定 n 个公钥,要求 sigscript 至少用 m 个对应的私钥签名才有效。
- 其中 1≤m≤n≤15 ,又称为 m-of-n 交易。
- 1of2 是允许两个账户中的任意一个都有权花费 UTXO 。
- 2of3 适合三方交易。例如 A 想花费 BTC 从 B 处购买商品,先将 BTC 转账到 2of3 多签地址。
- 如果仲裁方判断交易成功,则与 B 一起签名,将 BTC 转账给 B 。
- 如果仲裁方判断交易失败,则与 A 一起签名,将 BTC 转账给 A 。
- 没有 A 或 B 的同意,仲裁方不能私自转走 BTC 。
闪电交易
:闪电交易(Lightning Network,LN),一种 layer2 技术,基于链下交易(Off-Chain)。
-
官方文档 -
原理:在区块链下进行任意数量的交易,然后将这些交易的结果保存到区块链。主要步骤如下:
- 开启通道:两个账号将一笔 BTC 转账到一个多签地址,暂时锁定,称为开启一个闪电交易通道(channel)。
- 使用通道:双方建立对等连接(Peer connection),私下进行一些交易。
- 关闭通道:双方根据交易结果,将多签地址的 BTC 分配给双方。
-
在通道中,双方私下进行的交易只需要互相知道,不必公布到区块链上,称为承诺交易(commitment transaction)。
- 每个承诺交易,表示此时的通道状态,即双方应该分别拥有通道的多少 UTXO 。
- 每创建一个新的承诺交易,就撤销旧的承诺交易。
- 为此双方要交换一个承诺撤销密钥,证明它已撤销。
- 如果一方将已撤销的承诺交易广播到链上,企图双花攻击。则另一方可以根据撤销密钥,广播一个更新的惩罚交易(Penalty transaction),将通道的全部资产转给自己。
- 每个承诺交易设置了 locktime ,如果某方离线,则另一方等待 locktime 时间之后就可以将承诺交易公布到链上,从而关闭通道。
- 每个承诺交易的 locktime 依次递减,因此越新的承诺交易能越早公布到链上。
- 准备关闭通道时,双方签署最后一笔承诺交易,立即公布到链上。
-
闪电交易通道只能连通两个账户,但大量相互开启通道的账户可以组成闪电交易网络。
- 假设 A 与 B 之间存在通道,B 与 C 之间存在通道,则 A 可以通过 B 间接转账给 C 。此时 B 称为路由节点,像计算机网络的路由转发。
- 哈希时间锁定合约(Hash Time Locked Contracts,HTLC):一种智能合约,用于保证路由节点的可信任。工作流程如下:
- A 创建一个密钥 secret ,私下发送给 C 。
- A 在 A、B 之间的通道,使用 secret 的哈希值签署一个 HTLC 合约,将 BTC 转入合约。合约大意为:如果 B 能在 locktime 时间内发现 secret ,则有权获得合约的 UTXO ,否则资金将返回给 A 。
- B 在 B、C 之间的通道,也创建一个使用同样 secret 哈希值的 HTLC 合约,请求 C 提供 secret 。但是合约锁定的 UTXO 微少一点,因为 B 收取了手续费。locktime 也更短一点。
- C 提供 secret ,完成 B 的 HTLC 合约,得到 UTXO 。然后 B 再提供 secret ,完成 A 的 HTLC 合约。
- 即使 B 下线,C 依然可以完成 B 的 HTLC 合约,只有 B 会受到损失。
- 一些大型的路由节点可连接大量用户,像中心化网络。
- 一些路由节点会担任瞭望塔(watchtower),监控网络,广播惩罚交易。
-
优点:
- TPS 很高
- 手续费很低:支付给路由节点的费用很低,适合以 satoshis 为单位的小额交易。
- 耗时短:每个交易不超过一分钟,不需要等待区块链打包、确认。
- 隐私:只有开启通道、关闭通道的两次交易需要公布到链上,期间的交易不会上链,路由节点也不会知道整个交易的源头、终点。
- 耗费区块空间小:通道中的交易不必保存到区块链。
-
相关历史:
- 2017 年 5 月,LTC 区块链进行了第一次闪电交易。
- 2019 年 1 月,twitter 用户发起了一场称为闪电火炬(Lightning Torch)的行动,用于推广闪电交易。
- 规则:通过闪电交易发送一笔小额 BTC ,收到转账的账户添加 10w satoshis 之后再发送给下一个账户,以此类推。
- 这笔 BTC 传递了将近 300 次,最终被捐赠。
CoinJoin
:一种混币方案。
|