04 BTC-实现

发布时间 2023-05-02 11:34:13作者: YangYi215

《区块链技术与应用》课程链接:https://www.bilibili.com/video/BV1Vt411X7JF/?spm_id_from=333.337.search-card.all.click


04 BTC-实现

比特币系统是 transaction-based ledger


UTXO:Upsent Transaction Output

UTXO中的元素需要给出它所在交易的哈希值,以及它是交易的第几个输出(因为一笔交易可能有多个输出)。

为什么要维护一个UTXO数据结构?

验证交易是否合法,要花的币必须在UTXO中才行,如果不在,要么是不存在的,要么是之前已经被花过了。

全节点要在内存中维护一个UTXO的数据结构,以便快速检测double spending。

每个交易会消耗掉一些UTXO输出,同时也会产生新的UTXO输出。

如果某个人收到一笔比特币转账,始终不花这笔钱(不想花或私钥丢失),那么这笔钱的信息将永久的保存在全节点的UTXO中。【虽然UTXO的大小不断增大,但是目前为止,装在一个服务器的内存中还是完全足够的】


total inputs = total outputs

奖励光有CoinBase Transaction是不是够的,发布区块的节点为什么要把你的交易打包在交易中呢?这样做对它有什么好处吗?

比如:有些自私的节点,只打包与自己相关的交易,其余交易都不管,打包其它交易对它没有任何好处,而且还有一定的代价,因为你要验证交易的合法性,而且区块中的交易多的话,占用的带宽也多,在网络中传播的速度就会慢。

所以,才有了transaction fee。


(21万 * 10 分钟)/ (60分钟 * 24小时 * 365天)≈ 4年

大概每4年交易减半,2140年不发币。


以太坊是account-based ledger。【系统显示的记录每个账户的余额】


每隔2016个区块,需要调整难度Difficulty,保持出块时间在10分钟左右。


区块数据信息:

Block header的数据结构:

需要注意:nNonce是32位的无符号整型,最多有 $2^{32}$ 的取值,按照比特币目前的挖矿难度,就算把可能的取值都遍历,很可能仍然找不到符合要求的数,因为搜索空间不够大。

比特币系统并不要求非常精确的时间,所以可以进行一定范围的调整,只要别太离谱。

nBits是(目标阈值target,编码之后的结果),不能进行调整。

可以通过修改Merkle root hash值,更进一步,修改的是CoinBase Tranctions的输入。(因为该交易的输入为空)

其中CoinBase Tranctions的输入可以写任何想要值的hash内容。(比如股票预测,生活琐事)

块头中的nNonce不够用,可以使用coinbase中的前8个字节,这样搜索空间增大到了 $2^{96}$ 。

挖矿的时候执行两层循环。外层循环调整Coinbase中的值之后,算出block header中的根hash值之后,内层循环再计算nonce中的值。


下述为比特币中普通交易结构的示意图:


挖矿过程中每次尝试nonce,可以看作是一个Bernoulli trial:a random experiment with binary outcome.【每次两种可能性,如:扔硬币,因为硬币可能不均匀,所以正面朝上的概率为p,反面朝上的概率为 1-p 】

挖矿中所有的 Bernoulli trial 构成了一个 Bernoulli process:a sequence of independent Bernoulli trial.

Bernoulli process的一个性质是无记忆性(memoryless)。做大量的实验,前面的实验结果,对后面的实验是没有影响的。【比如:掷硬币,10次反面朝上,是不是下一次正面朝上的概率大一些呢?不是的】

对挖矿来说,每次尝试nonce,成功的可能性很小,需要尝试大量的nonce,才有可能找到符合要求的,这种情况下,Bernoulli process 可以用 Poisson process 来近似。

出块时间服从指数分布(exponential distribution)。

将来还要挖多长时间,和过去挖了多长时间,是没有关系的,仍然是服从指数分布的,平均还是要10分钟。

如果不是progress free,过去的计算对未来的计算有影响,那么算力强的矿工会有不成比例的优势,因为算力强的矿工做的工作肯定是多的。

有两个矿工 A 和 B,A的算力是B的10倍,理想情况下,A获得记账权的概率也应该是B的10倍,这才算是公平。现在A尝试了那么多的nonce,之后找到正确nonce的概率就会增大,这就叫做不成比例的优势。

所以,progress free的性质不是无情,恰恰是挖矿公平性的保证。


geometric series

21万 * 50 + 21万 * 25 + 21万 * 12.5 ...... = 2100万


虽然,挖矿计算的东西是没有什么意义的,但是,挖矿的过程,对于维护比特币系统的安全性是至关重要的。

BitCoin is secured by mining.

对于一个去中心化的,没有membership控制的系统来说,挖矿提供了一种凭借算力投票的有效手段,只要大部分算力是掌握在诚实节点的手中(算力大的投票节点,投票权大),系统的安全性就能够得到保证。


虽然出块奖励少,但是比特币价值反而变高。


假如系统中一半以上的节点都是诚实节点,那么我们能不能保证写入区块链的交易都是合法的?

恶意节点也有可能获得记账权,然后强行写了一笔错误的交易,但是诚实节点不认可该区块中的交易,会继续沿着之前的块往后挖。

定义一个有恶意的攻击是否成功的标准,是要看它能不能让诚实节点接受这个交易,如果仅仅是有恶意的节点之间认可,诚实节点之间不认可,那是没有用的。

比特币讲究的是拓展最长合法链,如果区块不合法,不管不合法区块多长都没有用,是作废的。【这样攻击者既投不了币,也白白损失了出块奖励】


区块往哪个位置挖,是从一开始决定的,因为需要设置前一个区块的hash。


使用fork attack达到double spending attack的效果。


为了防止上述攻击,简单的方法,多等几个确认(confirmation)。

six confirmation之后,才能真正确认一笔交易。


区块链是不可篡改的账本,那是不是说,凡是写入区块链中的内容(irrevocable ledger),那是不是说,凡是写入区块链中的内容,就永远都改不了了。

这种不可篡改性,只是一种概率上的保证。


其实还有一种说法,叫做zero confimation。交易发出之后,还没有写入到区块链中。


比特币全节点在缺省条件下,是按照监听到的交易的顺序进行打包的。


获得记账权的全节点,能不能故意不把某些合法的交易包含到区块中?

问题也不大,因为合法交易还可以写到下一个区块中,总有诚实的节点愿意发布这些交易。


比特币协议规定,每个区块的大小不能超过 1M 个字节,交易太多,有些交易只能等到下一个区块中。


selfish mining 的好处和风险:

好处:可能浪费了别人的算力,减少了竞争。

坏处:可能在自己挖下一个区块的时候,别人挖出了上一个区块,这样自己只能赶紧把自己挖出的区块发布出去,形成分叉,说不能还能获得奖励。