Web3.0-比特币

2022/11/03 web3.0

Web3.0 - 比特币

比特币是区块链技术的一个典型应用。央行发行的数字货币,由银行提供验证、背书。

比特币是一个去中心化的数字货币。

去中心化的数字货币,需要解决的问题是:

  • 谁发行货币
  • 怎么验证

1. 谁发行BTC

比特币的发行是由挖矿决定的。

挖矿本质是争夺记账权,提交下一个区块。提交下一个区块的时候,会获得block reward(出块奖励),出块奖励的比特币是新产生的,等同于发行新的币。

比特币争夺记账权的过程叫作挖矿(mining),比特币被称为数字黄金(digital gold),争夺记账权的节点被称为矿工(miner),一旦找到就能赚钱。

最初的出块奖励是50个比特币,比特币协议规定,每21万个区块后,奖励减半。所以比特币一直运行下去,最终会产生2100万个比特币。

21万  * 50 * (1+ 0.5 + 0.25 + 0.125 + ... ) = 2100万

按照比特币系统平均每10分钟出一个区块的速度计算,差不多4年,出块奖励就减半。

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

2. BTC的验证

比特币依赖区块链,由链上的所有节点共同维护。

比特币在交易的过程中,需要有相应的签名,转出方还需要提供自己币的来源。

上图就是一个简单的比特币区块链,记录了btc交易的流转。

每个小区块有2种hash指针:

  1. 连接在块之间,记录前一个区块头的hash值,因此形成区块链

  2. 指向前面的某个交易,指明比特币的来源。

    指明币的来源的目的:证明币不是凭空捏造的,同时也能防范双花交易(double spending attack)

区块链里的内容是如何写到区块链里面的呢?

每个节点,每个账户都可以发布交易,交易是广播给所有节点的。有些交易是合法的,有些是非法的。

谁来决定哪些交易应该被写入下一个区块中呢? 按照什么顺序写呢? 如果每个节点自己决定可以吗? 区块链是什么?是个去中心化的账本,账本里的内容得有个统一的说法。如果每个人在本地维护一个区块链,那区块链的统一性得不到保证,而账本的内容是要取得分布式的共识(distributed consensus)。

借这里的图,提个有意思的事情。

如图中所示,A有10个BTC,图中转给B和C各5个,那么能转给B和C各4个吗?

可以,但是剩下的10-4*2=2个BTC 就成了交易手续费 赏给矿工了。

如果不想给矿工,可以给BC各4个,再转给自己另外一个账户2个。

3. 比特币中的共识协议

比特币中共识 (consensus in BitCoin) 要解决的一个问题是,有些节点可能是有恶意的。我们假设系统中大多数节点是好的,那么该如何取得共识协议?

投票

既然大多数节点是好的,那就直接投票,首先应该确定哪些区块有投票权,有些membership是有严格要求的,不是谁都可以加入的,(比如说联盟链hyperledger,只有某些符合条件的大公司才能加入 hyperledger fabric)这种情况下基于投票的方案是可行的。

但是比特币系统不是这样的。 但是比特币系统创建账户是很容易的,就在本地产生一个公钥私钥对就是一个账户,不需要任何人批准,甚至一个人产生了公私钥对别人都无法得知,只有转账时别人才知道。

所以有些恶意节点可以不停的创建账户,当超过账户总数的一半时就有了控制权,这种称为女巫攻击(sybil attack)。因此投票方法不可取。

比特币不是按照账户数目投票,而是按照计算力来投票。

每个节点都可以在本地组装出一个候选区块,把它认为合法的交易放在里面,然后开始尝试各种nonce值(占4 byte),看哪一个能满足不等式H(block header)≤target的要求。

block head里面有一个域叫做nonce。如果某个节点找到了符合要求的nonce,它就获得了记账权。

所谓的记账权,就是往比特币账本里写入下一个区块的权利。只有找到这个nonce,获得记账权的节点才有权利发布下一个区块。其他节点收到这个区块之后,要验证这个区块的合法性。

最长合法链(longest valid chain)

有时候会出现2个矿工都计算出nonce,都对外广播自己挖到下一个区块。其他节点验证之后,选择正确合法的区块,在其后继续挖。最终这个分叉的区块链会分出长短,长的取胜,不在最长合法链上的区块(orphan block)就被丢弃了。

这两条都是最长合法链,那该接受那条呢?

这里的接受 意味着 认可这个区块,并基于这个区块往下继续扩展。

比特币协议当中,在缺省(默认的意思)情况下,每个节点是接受它最早收到的那个。所以不同节点根据在网络上的位置不同,有的节点先听到新生成的其中一个区块,那就接受这个区块;有些节点先听到另一个区块,那就接受另一个区块。

这两个新区块有可能会各自拉拢,两个区块链看谁的算力强,有时候也是看谁的运气好,就会胜出。

比特币系统中共识机制要取得什么共识?

类似于分布式哈希表,有很多系统服务器要维护分布式哈希表,假如有人在自己电脑上插入一个键值对,那么别人在另一台读的时候也要能把这个读出来,这就叫一个全局的哈希表。这里维护的共识是这个哈希表中的内容,包含那些key-value值。

4. 分叉

比特币的分叉,分两种:状态分叉、协议分叉

4.1. state fork

由于对区块链当前状态有意见分歧而导致的分叉。

比如说:2个矿工同时挖到下一个正确的区块,就形成了一个分叉,只不过这个分叉随着时间的推移,会 根据【最长合法链】原则得到解决。

4.2. protocol fork

对比特币协议产生分歧,用不同版本的协议造成的分叉。根据协议修改的内容不同,可以分成 硬分叉 和 软分叉

  • hard fork

    什么情况会出现硬分叉? 对比特币协议增加新协议,扩展新功能,未升级软件的旧节点会不认可这些修改,会认为这些特性是非法的。

    这也就是对比特币协议内容产生分歧,从而导致分叉。

    硬分叉的一个典型例子,就是对比特币区块大小的修改。

    在BTC系统中,区块大小最大为1MB,可以包含的交易最大数量为4000笔左右。而一个区块产生大概需要10min左右,也就是说,整个比特币系统,平均每10分钟最多只能处理4000笔交易(平均每秒7笔交易)。这个速度严重影响了吞吐量和交易处理。

    所以,有人建议增大区块,使得一个区块可以包含更多笔交易。假设扩大到4M。

    未升级的节点只认可1M的小块,新的节点对1M和4M大小的都认可。

    就可能出现上图的效果:老节点认为包含1和3的块所在的链都是非法的,于是又在2后面分叉 并创建4。

    这种分叉是永久性的,只要旧节点不更新,下面的链就永远不会消失。

  • soft fork

    目前UTXO是全节点自己在本地为了方便查询自行维护的,但UTXO内容并未写入区块链。

    UTXO(Unspent Transaction Output)

    比特币采用了一种追踪比特币的流水账记录法。本质上,就是只记录交易本身,而不记录交易的结果。

    区块链系统只处理所有的交易,而需要清算、查看余额等信息,由区块链节点自行处理。

    在比特币中,采用transcation-base ledger,即基于交易的记账本。通常我们更容易理解account-base ledger基于账户的记账本。

    比特币系统中,全节点负责维护UTXO数据结构,保存没有花费的交易。

    如果账户要查询余额,可以查找账户在UTXO里输出一共收到多少个币,如果是全结点的话可以算出来,但是很多比特币钱包不可能在手机上维护一个完整的区块链,实际上是一个轻节点,如果查询某账户余额,轻节点便需要询问全节点,全节点根据UTXO中信息可以计算得到账户余额,但如何确保全节点给的数据可信? 有人提议把UTXO集合中的内容也组织成一棵Merkle tree,将其根哈希值写在coinbase域中,(如果改block header的话动静太大,coinbase域正好没人用),改这个域的内容,最后会改到block header中的根哈希值,这样就可以通过Merkle proof证明出来了。 可以看到,旧节点认可新节点的区块,因为旧节点不管你写的内容,但新节点对于旧节点CoinBase域检查时候,发行并没有这个UTXO的根哈希值,不会认可其发布的区块,所以这是软分叉。

小结一下:

soft fork:只要系统中拥有半数算力以上的结点更新了软件,系统就不会出现永久的分叉

hard fork:必须所有节点都更新了软件,系统才不会出现永久性的分叉,如果有小部分结点不愿意更新,系统就分成了两条链

5. 全节点和轻节点

比特币区块链中的节点,分为全节点和轻节点。

如果不需要进行挖矿,只需要进行转账 只需要运行一个轻节点就可以,没必要运行全节点。

两者区别如下:

5.1. 全节点

  • 一直在线
  • 在本地硬盘上维护完整的区块链信息
  • 在内存里维护UTXO集合,以便快速检验交易的正确性
  • 监听比特币网络上的交易信息,验证每个交易的合法性
  • 决定哪些交易会被打包在区块里
  • 监听别的矿工挖出来的区块,验证其合法性
  • 挖矿并且可以决定挖矿的方向:最长链方向,如果出现等长的分叉时,选择最先监听到的那一条分叉

5.2. 轻节点

  • 不是一直在线
  • 不用保存全部整个区块链,只要保存每个区块的块头
  • 不用保存全部交易,只保存与自己相关的交易
  • 无法检验大多数交易的合法性,只能检验与自己相关的那些交易的合法性
  • 无法检测网上发布的区块的正确性
  • 可以验证挖矿的难度(即检测你发布的区块是否符合难度要求)
  • 只能检测哪个是最长链,不知道哪个是最长合法链

6. 挖矿

前面说了,挖矿本质是争夺记账权,提交下一个区块。

挖矿的过程是无记忆性的memoryless,又称progress free。

就像 抛硬币,我想要抛一个正面向上的硬币,和已经抛过的过程无关系。

每尝试一个nonce,都是在一定概率下满足挖矿条件,和之前尝试了多少次nonce没关系。这种memoryless的特性,使得挖矿成功的概率等于节点占总算力的比例。

比特币中用的哈希函数叫作SHA-256,根据SHA256的特性:块头任意一位发生变化,得到的hash值会变得完全不一样,而且大小变化方向不确定。

挖矿的时候,miner用PoW算法(Proof-of-Work)计算整个块头的hash值,比较hash值是否小于某个值(实际上这个值是保存在块头中的nBit “解压后” 的current_target值)来判断是否满足要求;

如果小于,则广播这个区块;如果不小于,则按照当前挖矿节点的规则改变块头中可以改变的值,然后再次计算块头hash值,以此往复,直到结果小于目标值。

那么块头中,有哪些值可以改变,从而改变整个块头的hash的呢?

除了前面说到的nonce,其实还可以改变merkle root。

每次挖矿,矿工可以得到一定数额奖励。也就是常说的铸币交易,铸币交易(coinbase域)可以自由输入任意的一些内容,从而向上影响整个merkle tree root hash。

6.1 挖矿设备变迁

比特币的mining puzzle是哈希算法,流行的运算工具有CPU、GPU、ASIC等。

第一代,CPU挖矿,CPU擅长逻辑控制,串行的运算。普通电脑挖。

第二代,GPU挖矿,GPU擅长的是大规模并发计算。显卡挖。

第三代,ASIC专用设备挖矿,矿机。

ASIC,Application Specific Integrated Circuit,在集成电路界被认为是一种为专门目的而设计的集成电路。

矿机淘汰速度也很快,过段时间就有更好的矿机问世。

6.2 矿池

单兵作战的模式,已经比较难挖到矿了。

矿池可以将分散的算力集中起来,一个矿池可以管理很多个矿工,矿池负责打包区块,矿工负责接收矿池的任务进行hash运算。

矿池中的矿工按贡献率分配挖矿奖励,矿工的贡献也是采用工作量证明的方式。实际,矿池要求矿工提交一个较比特币puzzle难度的结果。

比如比特币puzzle要求包含70个0,而矿池要求puzzle是60个0。

矿工每提交一个这样的结果,被认为比较了一个share。这些share中可能包含了符合比特币要求的结果,矿池就可以获得收益。

而绝大部分的share是没有意义的,仅仅作为矿工的工作量证明。

从概率上分析,加入矿池的矿工的收入期望并没有增加,获得的收益任然是矿工占全部节点算力的比例。但是,通过加入矿池,矿工收入的稳定性提高了。一些矿池为了吸引矿工加入,会为矿工提供额外的奖励,这也导致了超大型矿池的出现。

如果有一个矿池 包含了百分之51的节点,也不一定是百分之51,相当大的算力就有可能,那么他可以发动分叉攻击以及Boycott

分叉攻击:比如A将一笔交易给了B,经过了6个区块确认生效后。A发动分岔攻击,再生成一个链比原来的更长(拥有足够高的算力是有可能达到的)然后A转给B这笔交易就无效了。这样B就造成了经济损失。

Boycott:即对任意用户进行“封杀”,比如对A进行封杀,A进行的所有的交易都不让上链,只要A进行一次交易 就进行一次分岔。和分岔攻击不同的是,boycott不需要等6个区块确认,只要A进行上链就发动分岔 越早越好。

6.3 挖矿难度

比特币需要维持约10分钟出一个块,那么就要根据实际情况 动态调整挖矿难度。

难度调整公式:
target = target * actual_time / expect_time

比特币规定每2016个区块调整一次难度,计算公式等价于
newdiff = diff * (2016*10*60) / R

newdiff:       新的难度调整值
diff:          上次难度调整结果
(2016*10*60):  每10分钟产生一个区块,两周时间产生区块数=2016
R:             本次难度调整的2016个出快实际用时

问题,如何让所有矿工同时调整目标阈值target的值呢?

计算target的方法是写在比特币系统的代码里的,每挖到2016个区块。难度就会自动调整。

7. BTC相关问题

  1. 假设某全节点收到某个转账交易,会不会有可能转账交易中收款人地址该全节点从未听过? 可能,因为比特币账户只需要本地产生即可。只有该账户第一次收到钱时,其他节点才能知道该节点的存在。
  2. 私钥泄露怎么办? 尽快将剩余BTC转到其他安全账户上,没有第三方中心机构重置密码或冻结账户,只能自己对自己负责。 BTC系统中账户便是公私钥对,密码就是私钥,无法更改。
  3. 转账写错地址怎么办? 没有办法,只能自认倒霉,无法取消已经发布的交易。如果转入不存在地址,则该部分比特币便成为了死钱。当然,比特币系统中UTXO会永久保存该交易,记录该并不存在的地址。因此,对全节点来说,这是不友好的。

参考资料:

https://blog.csdn.net/qq_41569591/article/details/107932841

Search

    欢迎关注我的微信公众号

    钢仔

    Table of Contents