在比特币系统中,数字货币的发行是由挖矿决定的
比如说一个用户A获得了发行数字货币的权利,管这种权利叫做铸币权,假如A发行了10个比特币,A拿到这个钱,把它转给B,C各5个比特币,需要A的签名,同时还需说明花掉的10个比特币从何而来,是从前面的铸币交易来的【铸币交易(coinbase tx):能够凭空发行货币】。
比特币系统中,每个交易都包含了输入和输出,输入部分说明币的来源,输出部分要给出收款人公钥的哈希,比如说A转给B钱,就要说明B的公钥的哈希是什么,B又把钱转给C和D,C2个比特币,D3个比特币,也要说明B的钱的来源,这时C就有7个比特币,假如C把钱给E,E给7个比特币,这时候,C的来源有两部分
第一种哈希指针,用来把区块串起来构成一个链表。
第二种哈希指针,指向前面某个交易的,是为了说明币的来源,证明这个钱不是凭空捏造的,是有纪录的,同时也是为了防范double spending attack
仔细看一下A把钱转给B的交易,首先需要A的签名,同时还需要B的地址,
在比特币系统中,收款方的地址是通过公钥推算出来的,比如说B的地址,就是经过B的公钥取哈希,再经过一系列转换就得到B的地址,这个地址相当于银行账号,比如说某个电商网站接收比特币支付,可以在网站上公开他的地址,很多地址就是个二维码,扫一下就知道,另外B需要知道A的公钥,假如B收到一笔转账,但是不知道这钱是哪儿来的,A的公钥就是A的身份,B需要知道A的公钥,知道这钱是从哪儿来的,不光是B需要知道A的公钥,所有节点都需要知道A的公钥,为了验证A的签名,这个转账交易要是合法的,得是有A的签名,签名:私钥签名,公钥验证,区块链上每个节点都要独立验证,因为有的节点有可能是有恶意的,不能依靠别人,我得验证这个交易是不是合法的,这个钱不是转给我的,我是个旁观者,但是我也得验证,所以大家都需要知道A的公钥,那问题就来了,怎么才能知道A的公钥?接下行
A的公钥是这个交易中自己给出来的,就A给B转账这个交易,输入要说明币的来源,还要说明A的公钥是什么,这里面就有一个安全隐患,假如有人要冒名顶替呢,比如说B的同伙B1,他呢,伪造一个A到B的交易,他用他自己的公钥说是A的公钥,然后用它自己的私钥签个名,那别的节点收到之后,用假造的公钥去验证,那肯定是对的,就以为是合法的,那这样就麻烦了,这不就等于把A账上的钱偷走了,铸币交易的输出里面有A的公钥的哈希,所以A转给B的这个交易说明的A的公钥要跟币的来源里说明的A的公钥要对的上,前面讲到的B的同伙B1他伪造的公钥跟币的来源里说明的A的公钥对不上,就验证不通过
区块里由两部分,block header和block body
block header里存的是宏观信息
version:用的是比特币中哪个版本的协议
hash of previous block header:指向前一个区块的块头的指针
Merkle root hash:整颗Merkle tree的根哈希值
target:挖矿的难度目标域值,H(block header)<=target,块头存的是目标域值的编码nBits
nonce:随机数
block body:
transaction list
一个简单的例子:
distributed hash table(分布式哈希表)
系统里有很多台机器,共同维护全局的哈希表,这里需要取得共识的内容是什么?
答:哈希表中包含哪些key-value pairs,比如有的人在我这台机器插入了一个key-value pairs,拿别人在另一台机器上读的时候也要能够读出来,这叫全局的哈希表。
FLP是三个作者的姓的开头的字母
在一个异步的系统里(asynchronous),网络中,时延没有上限就叫做异步系统,即使只有一个成员有问题(faulty),也不能取得共识
CAP:分布式系统的三个性质,Consistency,Availability,Partition tolerance。
任何一个分布式系统,比如说分布式哈希表,这三个性质当中最多只能满足两个。
能保证一致性Consistency,但是某些情况下,有可能一直没有办法达成共识,可能性比较小,但是客观存在
解决问题:有些节点可能是有恶意的,假设系统中大多数的节点都是好的,有恶意的毕竟占少部分,那这种情况下,怎么去设计一个公式协议呢?
一种想法:投票,比如说某一个节点提出一个候选区块,根据这个收到的交易信息,选出合法的交易,按照某个顺序打包到一个区块里,候选区块发布到所有节点,每个节点收到这个区块之后检查一下交易是否合法,如何合法,投赞成票,如果其中有一个 是不合法的,投反对票,最后算一下,如果投票超过半数都是赞成的,这个区块就正式接受了,写道区块链里。
这里有个大问题:membership,任何基于投票的方案,首先要决定谁有投票权,如果这个区块链是有严格定义的,比如说这个不是谁都可以加入的,像我们有的叫联盟链(hyperledger),只有某些符合条件的大公司才能加入,fabric(联盟链协议),这种情况下,基于投票方案是可行的,因为我们假设大多数成员是好的,那么我们投一下票是可以的。
但是比特币系统中不是这样的,比特币e系统种,创建一个账户是很容易的,就在本地产生一个公私钥对儿就行,其实别人都不知道你产生了一个账户,你转账的时候别人会知道,只有跟外部发生一些交易的时候,别人才会知道,有恶意的节点都搞一台超级计算机,就只不停的产生账户,然后产生的账户超过总数的一半,就有控制权了,操纵投票结果,这种叫做sybil attack(女巫攻击),那怎么办呢?
投票不行,或者说简单的直接投票是不行的,比特币系统当中,用了一个非常简单的方式来解决这个问题,也是投票,但不是按照数目投票,而是按照计算力投票,每个节点都可以在本地组装出一个候选区块,把他认为合法的交易放到这个区块里,然后开始尝试各种nonce值,之前讲的H(block header)<=target,这个block header里面有一个域,是个随机数nonce,组装好区块之后,就开始试各种各样的随机数,4bytes,看哪一个能够满足不等式的要求,如果某个节点找到了nonce,就获得了记账权,记账权就是往比特币账本里写入下一个区块的权利,只有找到nonce,获得记账权的节点,才有权利发布下一个区块,其他节点收到这个区块之后,就验证合法性,比如先验证block header内容对不对,里面有一个域
nBits,实际上是目标域值得编码,检查nBits设置得是不是符合比特币协议中规定的难度要求,然后查一下nonce,是不是整个block header得哈希小于等于目标域值,比如说你发布一个区块,你是不是有权利发布,是不是真的获得了记账权,还要验证block body里面的交易列表都是合法的,一要有合法的签名,二以前没有被花过,如果任何一个不符合要求,那这个是不会被接收的,要放弃掉。
假如一个区块block header和block body都符合要求,必须接在最长的链的后面才是合法的区块,如果插在中间,就造成了forking attack(分叉攻击),通过往区块链中间插入一个区块来回滚已经发生的交易。
区块链在正常的情况下,也可能发生分叉,如果有两个节点同时获得记账权,那该接收哪一个呢?
比特币协议中,缺省情况下,每个节点是接收他最早收到的那一个,所以不同节点根据在网络中的位置不同,有些节点可能先听到上一个区块,会接收这个区块;有些节点先听到下一个区块,会接收这个区块。
那什么叫做接收一个区块?
比特币协议中,如果沿着这个区块继续往下扩展,就算是认可你发布的区块。
block reward(出块奖励)
比特币协议中规定,获得记账权的节点,在发布那个区块里,可以有一个特殊的交易,就是铸币交易,在这个交易里,可以发布一定数量的比特币
coinbase transaction是比特币系统中发行新的货币的唯一方法,其他的交易都是把已有的货币从一个账户转移到另外一个账户
那能造多少比特币呢。
一开始,每个账户可以造50BTC,BTC是比特币的符号
但是比特币协议中规定,21万个区块后,能造的比特币,出块奖励就要减半,就变成了25BTC,再过21个区块,又要减半,只能产生12.5BTC。
如果分叉上面最长的区块变成了主链,最长区块链,那下面的短的区块链里产生的出块奖励就没有了。
总结:
分布式哈希表取得的共识是哈希表的内容,包含哪些key-value pairs
比特币系统中取得的共识是去中心化账本里面的内容
那么谁能决定这个账本里的内容呢,只有获得记账权的节点才能往里面写东西。
那怎么获得记账权呢,就是解这个H(block header)<=target。
那为什么说比特币中的共识机制是靠算力投票,因为puzzle friendly这个性质,这个性质保证了求解H(block header)<=target的过程没有捷径,只能一个一个nonce去试,所以如果某一个节点的算力是另一个节点的十倍,那么获得记账权的概率也是那个节点的十倍,这就是比特币系统中的特殊性,他不是一人一票,也不是一台一票,而是看你每秒钟能够试多少个nonce的数目,这个管他叫做hash rate,如果hash rate越高,得到记账权,获得出块奖励的概率也越大
那么靠算力投票是怎么防范女巫攻击的问题,因为投票是靠算力投的,创建多少个账户其实是没有影响的,可以在服务器上创建一个账户,100个账户,10000个账户,并不会使你的hash rate怎么样,并不会使你每秒钟能够尝试的nonce数目怎么样。
争夺记账权的过程叫做挖矿mining,这个是比较形象的说法,是个比喻。有人把比特币叫做数字黄金,digital gold。争夺记账权的节点称作矿工miner,如果获得记账权,就说挖到矿了,或者说是挖到区块了。