区块链技术和比特币
区块链特点
区块链中的区块,是记录有特定信息的节点,这些节点收尾相连,构成了区块链。
区块链技术有以下特点:
-
去中心化
不再需要一个中央处理机构负责区块的记录,接入区块链网络的任何节点,都保存有完整的链,都可以接受和处理请求
-
数据防篡改
由于数据全量存储并公开给所有人,必须保证数据是不可更改的
区块链的应用,基本都是围绕上述特点落地,同时也是整个区块链设计中最难的点。
比特币的区块链技术
要实现去中心化和防篡改,比特币采用了两种技术:区块链技术和工作量证明共识机制。
区块链技术blockchain
每个区块保存有特定的信息、本区块ID和上一个区块的ID,其中本区块ID是根据本区块的内容通过hash算法生成的,对内容的改动会导致本区块ID发生变化,导致整个链条断裂,除非修改后面的节点。于是越老的区块,越难修改,可以一定程度上实现数据防篡改。
![assets/Untitled 39.png|Untitled 39.png](https://s3.665210.xyz/pictures/Notion/programmer/assets/Untitled 39.png|Untitled%2039.png)
工作量证明(proof-of-work)共识机制
区块链是分布式的,所有节点都可以参与区块的记录,那么大家都进行记录,以谁为准?那个人的记录可靠么?这个就涉及到分布式一致性的问题,可以参考 分布式系统之一:分布式事务和一致性
既然没有一个权威的机构,那么谁可信只能采取少数服从多数的原则,大多数人认为是对的记录,就认为是对的。
比特币采用的做法是,每个区块都有个唯一hash ID,这个ID的生成会有一个要求,需要通过大量的CPU计算,才能得到满足要求的ID。当一个区块的原始数据发布后,全网开始计算,第一个得到这个ID的,将ID公布给其他人,其他人使用原始数据验证没有问题后,就会记录这个结果,并放弃计算。
由于ID的生成很难,同一时间基本只有1个合法ID被计算出来,如果同时出现多个,比特币就会出现分叉,大家可以任意选择一个分叉进行记录(因为计算ID是很费力的,所以大家只能赌其中一个分叉),最终比较短的分叉,会被废弃(即实现了少数服从多数)。
而且,如果篡改原始数据,使得篡改数据可以得到和原始数据一样的满足要求的hash ID,需要特别久的时间(这时候已经有别的人计算出正确的ID了),所以篡改的可能性几乎不存在。如果执意篡改生成错误的ID,否则产生的ID不被认可,也不会被其他节点接受,除非控制全网50%以上的计算节点,这也是很难实现的。
好了,说了这么多,下面看看比特币区块的设计和PoW里面的hash ID如何要求的。
比特币的设计
下面是比特币的区块格式
![assets/Untitled 1 19.png|Untitled 1 19.png](https://s3.665210.xyz/pictures/Notion/programmer/assets/Untitled 1 19.png|Untitled 1%2019.png)
其中Version,Previous Block Hash,Merkle Root,Timestamp,Difficulty Target 和Nonce这六个数据字段是区块链的区块数据协议头。后⾯的数据是交易数据,分别是:本块中的交易笔数H和交易列表(最多不能超过1MB,为什么是1MB,后⾯会说)。
区块头中的六个字段的含义。
- Version:当前区块链协议的版本号,4个字节。如果升级了,这个版本号会变。
- Previous Block Hash:前⾯那个区块的hash地址。32个字节。
- Merkle Root:这个字段可以简单理解为是后⾯交易信息的hash值(后⾯具体说明⼀下)。32个字节。
- Timestamp:区块⽣成的时间。这个时间不能早于前⾯11个区块的中位时间,不能晚于"⽹络协调时间"——你所连接的所有结点时间的中位数。4个字节。
- Bits:也就是上图中的Difficulty Tagrget,表明了当前的hash⽣成的难度,4个字节。
- Nonce:⼀个随机值,⽤于找到满⾜某个条件的hash值。4字节。
对这六字段进⾏hash计算,就可以得到本区块的hash值,也就是其ID或是地址。其hash⽅式如下(对区块头做两次SHA-256的hash求值):
SHA-256(SHA-256 (Block Header))
当然,事情并没有这么简单。⽐特币对这个hash值是有要求的,其要求是那个Bits字段控制的,然后你可以**调整Nonce这个32位整型的值来找到符合条件的hash值。我们把这个事情叫做“挖矿”**。
关于 Merkle Root
前⾯说到过,可以简单地将Merkle Root理解为交易的hash值。这⾥,我们具体说⼀下,⽐特币的Merkle Root是怎么计算出来的。
⾸先,我们知道,⽐特币的每⼀笔交易会有三个字段,⼀个是转出⽅,⼀个是转⼊⽅,还有⼀个是⾦额。那么,我们会对每个交易的这三个字段求hash,然后把交易的hash做两两合并,再求其hash,直到算出最后⼀个hash值,这就是我们的Merkle Root。示意图如下:
![assets/Untitled 2 16.png|Untitled 2 16.png](https://s3.665210.xyz/pictures/Notion/programmer/assets/Untitled 2 16.png|Untitled 2%2016.png)
为什么要这样设计,而不是直接所有的数据做一次hash呢?有三个好处
- 可以快速的校验,大量的数据被分成二叉树的结构
- 提高篡改一笔交易的难度
- 大量的数据可以分片传输,在P2P的网络上,分片尤为重要
难度系数Difficulty Tagrget
参考Difficulty - Bitcoin Wiki,其决定了我们计算出来的hash值的字符串最前⾯有⼏个零,通过调整nonce和在允许的范围内修改timestamp,得到指定要求的hash作为ID。如果实在算出来没有符合要求的,还可以调整该笔记账包含的交易数量,即MerkleRoot。
这个难度系数,会在每出2016个区块后就调整⼀次。现在这个难度是要在前⾯找到有18个零。难度是根据全网的算力调整的,保证在10分钟左右可以完成一次记账
挖坑的流程如下
![assets/Untitled 3 12.png|Untitled 3 12.png](https://s3.665210.xyz/pictures/Notion/programmer/assets/Untitled 3 12.png|Untitled 3%2012.png)
比特币的交易模型
比特币中,没有“余额“的概念,比特币区块中的交易数据,也是一个链。
在比特币中,交易分为支出方input和收入方output。一个交易可以有多个output,所以一笔钱可以转给多个人。
由于只存储了交易数据,所以“余额“的概念被UTXO(Unspent Transaction Output)代替,即没有花出去的交易。例如A给C转了2个比特币,B给C转了3个比特币,对C来说,只有两个没有花出去的交易。此时,如果C给D转4个比特币,由于没有一笔交易是4个比特币,所以需要把2和3作为input,把自己和D作为output。
![assets/Untitled 4 10.png|Untitled 4 10.png](https://s3.665210.xyz/pictures/Notion/programmer/assets/Untitled 4 10.png|Untitled 4%2010.png)
TXO因为没有账户和余额的概念,所以可以并⾏进⾏多笔交易,不需要并行锁。通过设置多个交易目标可以隐藏交易的真实目的。
计算一个用户的余额,就要查看所有的其相关的交易,也是有点麻烦,所以ETH以太坊采用了有余额的方式。
比特币的交易是匿名的,每个用户创建比特币账户时,会产生一对公钥和私钥,公钥发布到比特币网络中,私钥是用户比特币钱包的唯一凭证。
比特币的每一笔交易,from和to都是账户的公钥,支付方发起交易,创建交易数据并使用自己的私钥加密作为签名,然后发布到网络。网络上其他人,会使用交易发起方的公钥校验交易数据。
交易过程如下:
![assets/Untitled 5 7.png|Untitled 5 7.png](https://s3.665210.xyz/pictures/Notion/programmer/assets/Untitled 5 7.png|Untitled 5%207.png)
信息传输的安全和加密,参考 加密、数字签名(摘要)和HTTPS 。比特币的网络上去中心化的,自然不能有证书机构,但是也不怕中间人攻击,任何对交易的篡改,都会导致签名不符,除非替换掉半数以上节点该用户的公钥。
比特币如何控制总数?
新的比特币是通过挖矿产生的,也即成功记录一笔交易后对矿工的奖励。比特币系统每出现2016个区块后,根据全网算力调整难度系数,保证每10分钟产生一个区块;同时,在比特币发行之初,每个区块中生成的比特币数量是50个,并规定每4年,每个区块产生的比特币数量减半。
在Controlled supply - Bitcoin Wiki中详细计算了每个区块的比特币数量,可以算出比特币会经历32次减半,到第33次减半的时候,比特币区块中包含的比特币数量就等于零(比特币的精度问题,实际上不是0,但是在比特币的精度下,就等于0了),根据计算,最终会产生略小于2100万枚比特币,大概在2140年所有比特币会被挖完。
那时候矿工咋办?没有挖矿的产出,大概会降低比特币的产生难度,矿工大量退场,回归小矿工模式,靠交易小费?
智能合约
区块链的不可篡改和去中心化的特点,除了像比特币一样作为货币之外,还有其他很多应用的场景,智能合约就是其中之一。
一个生活中的案例:两个人掰手腕打赌,输了的给赢了的100块钱,但是输了的赖账怎么办?这时候,需要找一个第三人来公正。这时候就牵扯到第三方公正人的可信度了。大额的资金面前,这个公证人通常是银行,小一点的么,在淘宝买卖东西时,支付宝就是充当了交易的公证人的角色。
涉及到银行么,流程就复杂了,既然区块链不能篡改,我们把合同写在区块链上不就好了?
ETH以太坊
对于以太坊来说,智能合约其实就是⼀段可执⾏的程序⽚段,由发布⼈使⽤⼀种类似于JavaScript或是Python的编程语⾔来编写。
我们把合约代码在本地编译成功后发布到区块链上,可以理解为⼀个特殊的交易(包括可执⾏代码),然后会被矿⼯打包记录在某⼀个区块中。当需要调⽤这个智能合约的⽅法时,只需要向这个智能合约的地址发送⼀笔交易即可。
但是,也有几个问题:
- 真正交易的过程很复杂,不能交易的涉及方,都去中心化放在区块链上吧?
- 既然是代码,就有bug,还不能修bug
共识算法
前面大概介绍了一下Pow,更多分布式系统一致性的共识算法,可以参考 分布式系统之一:分布式事务和一致性
比特币采用的Pow,而以太坊采用的是PoS。