UTXO Commitment有什么用?
全节点的同步问题,可以让新的全节点快速启动
目前,比特币的模式下要启动一个全结点,需要下载从创世区块到最新区块所有的区块。目前,所有区块的大小约为几百G。
我们来思考一下,这样的方式是否是必要的,其实用全结点去验证新交易,我们其实直接操作的是UTXO集合,看一下新的交易是否引用UTXO集合的某个UTXO。
UTXO集合其实就是比特币系统目前的状态,所以要启动一个全节点理论上只需要下载某个区块和该区块对应的UTXO集合即可,UTXO集合的大小约为几个G(<<几百G),其与历史数据不同,可以被消耗,所以它不会像历史数据那样线性增加。
当然,这样会丢失前面所有的历史交易的记录。
然而,怎么保证下载的UTXO集合和某个区块能够对上?这里就引入了UTXO Commitment(目前比特币没有这个东西)。就是把UTXO集合的摘要写到比特币的区块上。
UTXO Commitment的实现方式
朴素的方式
按某个键排列所有UTXO,然后把他们连接起来进行哈希
这样的问题在于:
随着新区块的加入,UTXO集合中会有UTXO被消费以及新的UTXO被消费。因此,需要重新把几G的UTXO集合重新排序,算哈希。这样真心大丈夫?
因此,下面引入了哈希求和算法
哈希求和算法
对集合中的每个UTXO进行哈希,然后把所有的哈希加起来作为这个UTXO集合的哈希结果。每接收一个新区块,就用UTXO集合的哈希减去花费的UTXO哈希&加上新增的UTXO哈希。
这里存在一个问题,这个算法没那么安全,假设当前UTXO集合哈希为S,我想伪造的交易为T,那么我只需要找到另外哈希值为S-T的交易即可。此处还有进一步弱化,UTXO集合的数量不确定,允许很多中排列组合,安全性进一步降低。
用hash-then-add方法去哈希集合存在的其他问题:
https://jameshfisher.com/2018/01/09/how-to-hash-multiple-values.html
ECMH哈希算法
思路
就是把哈希映射成椭圆曲线上的点,然后利用ECC的加法。
为什么比哈希求和算法要安全?
更安全的意思是要达到相同的安全性,ECMH算法需要的密钥长短远远小于哈希求和算法。
我个人觉得更安全与椭圆曲线类型的密钥有关,举个例子就是RSA在相同的安全性的条件下,需要的密钥长度远远长于ECC的。所以ECMH需要先映射到椭圆曲线,再继续进行同态加法。
UTXO Commitment的缺陷
同步时要把全部UTXO全同步完,才能获悉同步源是否为恶意结点。这样容易被攻击。
如何走得比UTXO Commitment更远
- ECMH commitment
ECMH可以把多个数据的 hash 合并到一个 hash 中,但还可以支持删除。这样节点维护一个 UTXO 的根 hash 的成本就很低了,每次只需做增量修改。然后只需要把 UTXO 根 hash 记录到区块上,其他节点同步 UTXO 集合之后,就可以验证该集合是否被篡改了。但这个方案的缺点是只能做全量验证,没办法验证单独一个 UTXO 是否存在。 - Bucketed ECMH commitment
这个方案与merkle tree思路类似,但用 ECMH作为哈希算法(为了方便删除)。要把每个 UTXO 的 hash 都保留着,维护一个分片的 Bucket 或者 Trie 结构,Bucket 或者 Trie 结构的每层都用 ECMH。 这样就有办法证明单个的 UTXO 了。 - Commitment enabled UTXO storage
改造 UTXO 的存储,将它存储在一种 Merkle binary tree 结构中,每次新区块产生,进行 merge 只需要计算变更的一部分。这种方案可以满足上面两个需求,但实现复杂度比较高,并且需要对 binary tree 的实现做优化。
更多灵感思考
- Storing UTXOs in a Balanced Merkle Tree设计了一种红黑树来保存 UTXO
- Dietcoin: shortcutting the Bitcoin verification process for your smartphone讨论了一种 UTXO 分片的办法来实现UTXO Commitment机制
- 三种Commitment方法的讨论