之前写过一篇文章《聊聊比特币》 ,其中聊了一些对比特币的看法,并提出了几点质疑。如今又想再写一篇对比特币网络进行解析的文章,这回主要谈比特币网络运行涉及到的基础技术,以及解释比特币网络这个大框架是如何运行的。
首先比特币的基础技术是加密技术,这里主要解释两个对于比特币而言最重要的基础技术。
密码哈希函数这类算法包括MD5,SHA-256,SHA-512,这些算法只是细节不同,大致原理是相同的,早期经典的MD5算法做出了关键的改进,有兴趣了解的可以参考RFC1321标准文档,或者看开源的代码实现。这里就不介绍了。
比特币采用的SHA-256算法,这个算法可以接收变长的字节流作为输入,然后输出的二进制长度则为固定的256位,这类函数的特点,输入到输出很容易计算,但是无法从输出推导出输入。比特币挖矿就是要找到某些输出对应的输入,为什么是某些呢,因为比特币挖矿有一个难度系数。因为哈希函数输出是256位,每位取值只能为0或者为1,那么总共就有2的256次方的组成,约等于10的77次方,难度系数就相当于定义了一个范围,难度越高,范围越小,难度越低,范围越大。
比特币网络对于挖矿难度有一个共识,这个难度是根据过去一周平均挖一个区块所需的时间的决定的,这个难度的计算方式是开源的,比特币网络中的节点都运行这个开源的代码,如果有少数节点擅自更改难度,挖出一个非共识难度系数对应的区块并将其传播到比特币网络中,则会被其它节点踢除,这个新挖出的区块也不会被承认从而被丢掉。
之前提到哈希函数无法通过输出来推导输入,因此挖矿的工作就是不断尝试不同的nonce值来找到符合条件的区块。下面通过python代码来演示挖矿的过程:
block = { 'previous_block': '52a6eb687cd22e80d3342eac6fcc7f2e19209e8f83eb9b82e81c6f3e6f30743b', 'trasactions': [ 'trans1', 'trans2', 'trans3' ], 'nouce': 0}def solve(data, difficulty): t_start = time.time() for i in range(2**256): data['nouce'] = i data_byte = pickle.dumps(data) sha256 = hashlib.sha256(data_byte).hexdigest() if int(sha256, 16) < 2**(256-difficulty): print('耗时为:%s' %(time.time() - t_start)) return datasolve(block, 10) #难度系数低,nouce为298时满足条件solve(block, 20) #难度系数高,nouce为241854时满足条件
这里为了说明简化了,区块中有交易数据,实际上一个区块中的所有交易是通过哈希树的形式生成一个root哈希,然后再把这个root哈希放入区块中去挖矿的,而且区块中还有其它一些附加信息。而且真正的验证过程比这个复杂,源代码比较长,这里为了解释说明简化了,不过原理都是一样的,通过不断穷举找到答案。
一个节点找到答案时向比特币网络中扩散,网络中其它节点接收到这个数据后首先验证难度系数是否正确,然后给的nouce值是否能生成满足难度条件的哈希,验证成功则将其插入自己维护的区块链中,然后再把这个区块往其它节点传播。每个区块都需要指明它的前一个区块是哪个,即上面代码中对应的previous_hash键对应的内容,通过这种方式把区块一个一个的连接了起来,所以称作区块链。
在我们简化的代码中,当设置难度为10时,nouce从0开始尝试,到298时找到答案,注意有不止一个nouce值可以满足验证条件的,找到一个即可停止;而难度设置为20时,则尝试到241854这个值时才停止。示例中的难度系数很低,实际挖矿难度要高得多,而且随着算力增强,难度也是不断提升的,目前每一周都会更新一次难度,如果过去一周平均挖出一个区块的时间低于10分钟,则按照指定公式调高难度,高于10分钟,则降低难度。
图1. 区块链示意图
非对称密码技术所谓非对称密码技术则是有一个公钥和一个私钥,通过私钥可以计算出公钥,而通过公钥是无法计算出私钥的。这样一来账户的拥有人只需要保存自己的私钥即可,而公钥可以提供给他人,作为转账地址。
在比特币中,有钱包地址的概念,钱包地址用的就是非对称密码技术中的公钥。区块中的交易有两类,一类是把比特币从某个账户转到另一个账户,另一类是把新生成区块的奖励转给某个账户,这个账户地址是有生成区块的节点写上去的。
公钥就对应账户地址,如果某个账户的公钥地址收到一笔钱,那么只有用这个公钥对应的私钥去解锁才能使用这笔钱。如果某人丢失了自己的私钥,那么该账户下的所有比特币就永久消失了。
在比特币网络中,交易也像区块一样是链接起来的,因此所有比特币是可以溯源的。比如现在某个账户有一笔未消费的钱,这笔钱在比特币网络以交易记录的形式存在,某一笔交易的输入金额来自某一条交易记录(其哈希被记录)的输出金额,某条交易记录的输出金额对应一个公钥地址,被使用的前提是具备对应的私钥。某一笔交易的输出金额被使用后,它对应的交易记录会向整个比特币网络中传输,之后这笔金额就无法再使用了。由于输入对应的交易记录是一直保存在比特币网络中,因此可以溯源每一笔钱的来龙去脉,直到源头是新区块生成的coinbase交易记录为止,coinbase交易记录中涉及的金额是奖励给挖矿人的。
比特币网络
接下来解释一下比特币网络,比特币网络大致分为两类节点,一类是钱包节点,该类节点不致力于生成区块,它的作用是使用钱包对应的私钥对属于这个账户的未消费交易记录进行签名,然后再生成新的交易记录(转到指定账户)并将其传播到比特币网络中,钱包会定期从从比特币网络中获取钱包对应公钥地址的所有未消费交易记录,这些未消费交易记录涉及的比特币总量就是该账户的余额。另一类是挖矿节点,该类节点会收集交易记录,然后去除重复的交易记录,然后验证交易记录的签名,验证成功则放入交易池中,在开始生成下一区块时把交易池中的记录都放入区块中。
比特币网络多个节点之间在进行竞赛,看谁先找到满足条件的值,一旦某个节点先找到,它就把新生成的区块传播出去,其它节点一收到则停止挖矿,并将该区块写入自己保存的区块链中,并以这个新区块的哈希值作为previous_hash开始挖下一个区块。
如果比特币网络两个节点几乎同时算出了满足条件的nouce值,并向网络中传播,这个时候整个网络如何解决冲突?
比特币网络的共识是只维持最长的链,但这个时候有两个高度相同的区块在网络中传输,解决方案是网络中的节点先收到哪个区块就以哪个区块的哈希值为基础上挖下一个区块,这样就会导致一部分节点致力于延长A链,一部分节点致力于延长B链,如图2所示。之后如果有哪个节点有挖出一个新的区块,则该新区块所对应的链则被整个比特币网络所承认。一句话总结就是只维持最长的链,各条链长度一样,则每个节点致力于延长自己最先接收到的链。
图2. 区块链分叉
如果有恶意势力,他们要操控区块链,则需要拥有51%以上的算力,通过生成更长的链(区块中放入什么交易由他们决定)来替代存有正常用户交易记录的区块链。需要注意的是他们生成的区块中存放的必须是有效的交易,不然交易验证不通过会被其它比特币网络节点认作是恶意节点而踢出去。因此他们只能破坏其它人进行的交易,因为他们故意不把这些交易写入生成的区块中,而其它正常节点想写入这些交易,但是他们生成的区块老被更长的替换掉。恶意势力是无法使用其它账户中的余额的,只要他们没有那些账户对应的密钥。
喜欢的朋友记得点赞、转发或者关注主播,谢谢!
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。