BTC协议
-
挖矿实际在做的, 找到一个noise, 使得$Hash(block\ header, noise) \leq threshold$.
-
哈希指针 (Hash Pointer):除了指明存储位置,还对存储内容进行加密,保证内容没有被篡改.
- 「例」区块链是使用哈希指针链接的. 对于单个节点而言, 我们可以只保留最近的若干个区块和tail哈希指针; 这样当我们问其他节点要前面的区块, 可以防止其他人篡改.
- Merkle Tree: 和二叉树(binary tree)的区别是用哈希指针代替的普通指针.
- Merkle Proof(也称为proof of membership/inclusion): merkle tree的一个运用就是merkle proof. 比特币中的节点分为两类, 一列是全结点, 一个是轻结点. 全结点包括交易内容(block body)和哈希指针(block header); 一个是轻结点, 只保存merkle root, 比如比特币钱包.
- 「例」对于轻结点, 利用merkle tree的性质可以以O(logn)的实际快速确认一笔交易是否已经写入区块链.
- Proof of Non-membership: 如果对叶结点的排列顺序没有要求, 复杂度是O(n); 如果对叶结点排列顺序有要求(sorted merkle tree), 比如哈希值排序, 可以先找到查询交易的前后两个交易, 然后看这两个交易是否是相邻的即可.
「安全性分析」
- 「共识」最长合法链 ← 防止分叉攻击(forking attack)
- 有可能会存在临时分支, 但是最早被拓展的才会被当作最长合法链
- 「共识」靠算力获得记账权 ← 防止女巫攻击(sybil attack, 防止如果按照账户投票的话, 某台计算机产生大量虚假账号从而控制整个区块链)
- 如何防止double spending? → 记录交易本身, 通过指向前面的交易来说明币的来源, 通过交易记录来计算每个账户的余额.
- 转账人如何说明这笔转账就是自己(即私钥)发出的? → 转账人用私钥对交易进行数字签名, 并公布公钥.
- 如何防止替身攻击, 比如A向B转账, 但是有个人直接用了用A的名义(A的公钥可能公布不及时), 但是用了自己的公钥和私钥进行数字签名制造虚假交易? → 每笔转账都要给出收款人的地址或者公钥, 这样新的交易指向前面的交易可以可以验证没有人在顶替A.
- 收款人为什么需要给地址(公钥的哈希)而不用公钥, 甚至可以每次转账都用一个新的地址? → 地址不会暴露公钥, 安全性更高, 而且反复用同一个地址会降低安全性和隐私.
- 如何避免临时分叉等导致的篡改风险?
- 解决方法是多等几个区块才确定不可篡改, BTC是默认6个区块后.
- 根据距离当前最新块的距离, 交易可以分为0-conformation, 1-conformation, 6-conformation. BTC是默认6-conformation后是不可篡改的.
- 「selfish mining」有没有可能一个矿工隐藏多个挖到的区块, 来制造最长链?
- 这种情况是基本不可能出现的, 原因是1. 在诚实结点占多数的情况下, 成功概率很低 2. 就铸币奖励而言, 这样做是没有好处的.
BTC实现
- UTXO(Unspent Transaction Output)
- 记录每笔交易的收款者还没有花出去的BTC
- 一笔交易可以有多个输出
- 每一笔新的交易都需要说明支付者的BTC来源, 包括来源交易的哈希和是该交易的第几个输出
<aside>
🤔 基于通过遍历交易来获得余额的方式称为transaction-based ledger, 如BTC; 与之相对的是account-based ledger, 如ETH.
</aside>
- 交易费: 除此以外,每笔交易都需要支付一定的交易费给矿工