比特币&区块链与挖矿
前言
最近这段时间好好学习了下比特币,但也只是初步了解了个大概,也有好多疑问没有解决。
根据各个地方收集到的资料,加上自己的理解,写下了这篇博客。
比特币定义
比特币是一种由开源的P2P软件产生的数字货币,是通过计算产生的,由一串串复杂的计算机代码组成。与传统的法定货币不同的是,比特币不依赖于特定的中央发行机构,而是使用遍布整个P2P网络节点的分布式数据库来记录货币的交易,并使用密码学的加密设计来确保货币流通各个环节的安全性。
比特币总量
比特币的发行上限为2100万枚
比特币的产生速度
大约每10分钟可以产生出25枚比特币,产量每四年会缩减一半(2009-2012年的最初4年内,每10分钟产出50枚比特币),因此比特币的流通数目将在2140年达到它的发行上限。
分布式数据库
分布式数据库系统通常使用较小的计算机系统,每台计算机可单独放在一个地方,每台计算机中都可能有DBMS的一份完整拷贝副本,或者部分拷贝副本,并具有自己局部的数据库,位于不同地点的许多计算机通过网络互相连接,共同组成一个完整的、全局的逻辑上集中、物理上分布的大型数据库。
- 无发行机构(政府、个人、企业等)
- 任何人都可以挖掘、购买、出售、收取比特币
- 交易过程中外人无法识别用户身份信息
- 支付速度快1秒内完成交易,10分钟内全网节点记录、验证、确认,实现交易确认
- 点对点兑换和交易,成本为零。通过比特币交易所来兑换,支付千分之三或更少手续费
比特币系统中的数据库——区块和区块链
区块链是比特币的底层技术,但已经独立地发展为了一种革命性技术。比特币则是区块链最大最成功的的应用。
区块链是一个基于共识机制、防篡改、去中心化的公开数据库。
- 共识机制使之在分布式系统中保证数据一致性的算法;
- 防篡改特性是基于哈希算法实现的
- 去中心化是指参与区块链的所有节点都是权利对等的,没有高低之分,唯一的限制就是个人自己的选择。
- 公开数据库则意味着所有人都可以看到过往的区块和交易,这也保证了无法造价和改写。
Block Chain(区块链):比特币从开始到现在的每一笔产出或交易的记录文件。Bitcoin Block Explorer可以查看
Block(数据区块):一个区块是部分或所有最新(未被其他先前的区块记录)比特币交易的记录集。大约10min产生一个。
以下给出比特币系统中的区块结构,在之后会有说明
数据区块结构:
区块头结构:
矿工的世界
在p2p比特币网络中,一些节点被称为专业节点矿工。
矿工的工作:
- 接受、验证、中继新交易
- 挖矿——开发新的区块
- 监听、验证、传播新区块
矿工们在挖矿过程中会得到两种类型的奖励:
- 创建新区块的新币奖励
- 区块中所含交易的交易费
矿工的各种工作大都是同时进行的,挖矿的同时在处理交易,并一直监听是否有新的区块产生。
1.矿工在网络中收集被广播的比特币交易,把验证过的交易,加到自己的交易池中。根据块龄,矿工费和优先级排序交易,靠前的交易优先被记录。
2.当监听到新区块产生,就立刻停下工作,先去验证新的区块。验证通过,会尝试将新的区块连接到现存的区块链,将他们组装起来,并继续传播此区块,同时要将新区块中对应的交易从交易池中移除,确保任何留在内存池中的交易都是未确认的。
3.当自己挖到一个新区块,就立刻将新区块发送给相邻节点。
新区块象征着本轮区块竞争的结束,也是下一轮竞争的开始。
挖矿
通过开源的计算方法在比特币特定的数据链上运算正确的比特币数据区块的行为,产生比特币的唯一途径。
挖矿三个重要功能:
- 维系货币的支付功能(对于比特币系统的最主要功能)
通过算力保障系统安全(防止“双重支付”)
双重支付:2次或多次花费同一笔比特币
发行新的货币(总量达到之前)
挖矿算法
区块头参数:
- version:版本号
- prev_hash: 上一个Block(父区块)的hash值
- merkle_root:这个区块中全部交易构成的merkle树的根 (为了防止有交易出现在倒数第二层,如果当前交易数量是奇数的话,那么最后一个交易将会被计算两次哈希值)
- ntime:区块生成的时刻(以Unix纪元开始到当下的秒数,精确到秒)(每几秒更新)
- nbits: 当前运算难度,最终反应结果为TARGET的
- X:正确运算结果的唯一参数,范围是0~2^32
- TARGET: 比特币系统要求新的哈希值拥有特定的格式——必须以一串特定数量的0开头
挖矿算法:1
SHA256(SHA256(version + prev_hash + merkle_root + ntime + nbits + x)) < TARGET
对区块头进行哈希运算,将所得哈希值与目标哈希值进行比较,如果当前X值计算的哈希值小于目标哈希值,则挖矿成功。如果这个哈希值不小于目标值,矿工就会修改这个X(通常将之加1)然后再试。
Q1. 如何保证区块更新周期平均是10min?
nbits越大,TARGET越小,解出X的难度越大。target=2**(256-nbits)
难度值nbits是节点自动调整的。New nbits= Old nbits*(Actual time of last 2016 Blocks/ 20160 minutes)
(即最新2016个区块花费时长与20160分钟(2周)比较所得,期望10min产生一个)
区块成熟时间(Maturation Time)
区块成熟时间是指矿工产生一个新区块得到25BTC收益后,要等过了100个块后,才能使用这些币。这个100区块时间,即收到100个确认的时间,就是区块成熟时间。
为什么要设这个时间?
如果这个区块在分叉时变成了孤立区块,25个BTC的收益将消失,如果矿工挖到比特币后可以马上花掉,就会造成后续的一系列接收者损失比特币,因而设定了100个确认的限制,在这之后产生分叉的可能性非常小,即使产生分叉,也只会影响矿工收益,不会影响到其他人。
Q2. 是否有可能同时解出区块 ?
当两个区块产生的时间仅相差几秒时,可能会产生包含一个区块的分叉。
Q3. 同时解出来怎么办 ?
短暂产生两个分支,矿工节点会根据收到区块的时间,在先收到的区块基础上继续挖矿。哪个区块的后续区块先出现,这个区块就被包括进主链,因为这条块链更长,所有人都会选择这个更长的分支。没选中的区块的矿工,所得比特币无效,其区块中包含的交易也无效(虽然这种交易的无效是暂时的,这些交易会被重新广播投入到交易池中被新的区块重新记录,但是此处引起双重支付的可能)。
Q4. 如何实现双重支付 ?
在目前公认的数据链上完成交易确认,然后延续另一条数据链,使之成为新的被公认的数据链,则原来被公认的数据块的交易不被承认,在交易重新被认可之前,抢先完成同一笔钱的另一个交易确认,这笔交易就会因为账单中指定地方的钱已经被使用了而作废,但是对方的交易物品已经发送。
比如:挖到新的BLOCK不广播,比特币消费给A,继续挖,抢先到达2个区块,前后广播,所有人会以你这个更长的分支为当前的数据链。A收到的比特币不被承认,再消费一次比特币,关于A的账单因为比特币不足作废。
解决办法:收款人不要在交易确认后(及产生一个新的区块后)立刻发出货物(实现交易),而是应该在看一段时间,等待基于这个区块的新生成的区块达到6个,并且之前的账簿没有被取消,才确认钱已经到账(你的交易所在的区块链足够强壮)。
当整个网络算力足够高,攻击概率极低,或成本极大。
Q4. 难度是节点自己自动调控的,是否可以人为利用低难度去产生长分支区块?
客户端接受“最长”块链作为有效链,整条块链的“长度”是指具有最大难度的链,而不是指具有最多区块数量的块链,可防止某些人创建大量低难度区块,故意使块链分叉,并且让网络接受它成为“最长”的块链。
Q5. ???矿工节点会在先收到的区块上继续挖矿,还是根据区块头中的时间戳来替换???
这个问题不是很确定,个人觉得是在先收到的区块上挖矿。这样子对于矿工工作合理一些,但是如此区块头中的时间戳貌似用处也不大。
Q5. ???区块头中上一个区块的hash,是上一个区块全部的hash还是上一个区块头的hash???
也不是很确定,说两者的都有,个人觉得是上一个区块头的hash,因为区块头包括交易的merkle树的根,已经做到与交易绑定。
参考:
《比特币开发》——申屠青春
比特币:交易的数据结构-姜家志
深入理解比特币交易的脚本