APP
精品帖
3190 0 0
  • RMB 0.44

    大雨
    • 34
      帖子
    • 11
      评论
    • 4870
      源点
    比特币挖矿,以太坊挖矿,区块链挖矿 区块链挖矿是什么意思? 区块链挖矿原理 区块链挖矿app十大排名
    发表于7个月前 只看楼主 帖子标签: 比特币挖矿  以太坊挖矿 
    • 区块链挖矿
    • 区块链挖矿是什么意思?
    • 区块链挖矿原理
    • 区块链挖矿app十大排名
    • 区块链挖矿平台合法吗
    • 区块链挖矿合法吗
    • 区块链挖矿是不是骗局
    • 区块链挖矿项目
    • 区块链挖矿怎么挣钱
    • 区块链挖矿成本包括

    作者:Hashkey哈小奇

    链接:https://www.zhihu.com/question/308037541/answer/11...
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


    在银行存钱,利息由存款金额和时间决定,权益证明机制(PoS)也是这样。PoS根据持币时间和持币数量来决定挖矿成功的打包概率。

    相比较于PoW挖矿,PoS挖矿的优势是降低了投资者的进入门槛,矿工和持币者利益一致,延迟低和确认速度快。


    但在隐私保护、投票治理机制的设计等方面存在一定的缺陷。这也导致了个人玩家在PoS挖矿时面临很多短期行为的风险,引进第三方机构来规避风险就成了一个不错的选择。

    一、什么是PoS挖矿?

    PoS(Proof-of-Stake),中文称权益证明机制,也称股权证明机制,顾名思义,是根据用户持币的币龄大小来决定挖矿成功的打包概率的共识机制。

    币龄=矿工质押代币的总额代币持有的时长

    币龄在一定程度上保护了持币份额低但持币期间较长的矿工(也可以是投资者)的利益,增加了恶意矿工激增持币份额的方式操纵(Manipulate)打包概率的作恶成本。

    通俗地讲,一个PoS代币经济生态就好比一家同股不同权(1股并不代表1份表决权)的上市公司,PoS挖矿就好比上市公司的股利支付决策,每个矿工(持币者)就是该上市公司的股东,矿工争夺的记账权就好比表决权,矿工获得记账权的概率就好比股东的表决权份额(即该矿工的表决权占总体表决权的比例),矿工质押代币的数量就是股东的持股金额。

    根据质押代币份额的大小不同,有的矿工是“鲸鱼”(大股东),有的矿工是“小股东”或“少数股东”。

    PoS挖矿也好比将质押的代币存储在银行,银行根据存放的时长和存放的金额支付利息。

    目前,以EOS、Tezos、Cosmos等为代表的数字货币都采用PoS作为共识机制,而ETH有从PoW(Proof-of-Work,工作量证明机制)转变为PoS的趋势。

    二 PoS挖矿 VS. PoW挖矿

    PoS挖矿的优势

    相比较于采用工作量证明机制(Proof-of-Work, PoW)挖矿,PoS挖矿具有以下4个优势:

    1. PoS不用造成大量的电力和资源耗费,比PoW更加环保,且用户参与门槛较低;
    2. 矿工和持币者动机一致,不存在委托代理问题,因为PoS中矿工就是持币者;
    3. 延迟可以设计的非常低,比如EOS的数据吞吐量已经达到了每秒3000笔;
    4. PoS确认速度快,其速度仅取决于网络和网络协议,只要满足2/3以上的节点诚实即可;

    PoS挖矿的缺陷

    但是,PoS的一些优点往往是一把双刃剑,导致PoS挖矿机制仍有待于进一步完善。主要包括以下四点:

    1. PoS的公链一般是许可型公链,而且不具有匿名性,投票账户和总票数已知且有限,鲸鱼(质押代币份额高的矿工)容易作恶;
    2. 投票行为成本低,容易遭受无利害攻击(Nothing-at-Stake Attack)。即“作恶无成本,好事无限多”,作恶矿工同时在多个分叉上挖矿,并且同时获得所有挖矿收益的行为;
    无利害攻击——同时获得多个分叉的出块奖励
    1. 投票权可复用可转账(PoS存在弱主观性),容易遭受长程攻击(Long Range Attack)。即攻击者创造一个长区块链取代最长合法链,从而骗取挖矿收益。
    长程攻击——取代最长合法链
    1. 投票权的决定和行使是分离的,二者没有绑定,从而导致容易产生贿赂选举的行为。

    三、如何规避PoS挖矿存在的风险?

    PoS挖矿仍有待于完善和改进 ,导致PoS挖矿存在的风险较高,有效控制在PoS挖矿中的作恶行为必须满足2/3以上的节点是诚实的大前提。一旦选举被操纵,或者是被选举出来的节点被“黑化”,都会导致PoS挖矿的收益大打折扣,存在较大的风险和不确定性。

    2009年中本聪发明比特币,并且设定了比特币只有2100万个,加入到比特币网络中,通过参与到区块的生产中,提供工作量证明(PoW),即可获得比特币网络的奖励。这个过程即是挖矿。

    ”挖矿”的概念取自于我们现实经济生活中已有的概念,黄金挖矿、白银挖矿等,因为矿物是有价值的,所以才驱使人们去付出劳动力来挖。

    比特币挖矿还有一个重要的点是因为参与挖矿的矿工认可比特币的价值,他们挖矿挖到的比特币市场上有人愿意花钱。所以,比特币的挖矿是有意义的。

    挖矿是一个极富场景感的词,听到挖矿的时候,是一群人淘金的样子。我们讲“搬砖”,就是自己在写字楼,付出自己的劳动,获得相应的奖励,这和挖矿一样的。搬砖是一个价值生产的过程,挖矿也是



    作者:「已注销」
    链接:https://www.zhihu.com/question/308037541/answer/11...
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    作者:浅谈比特币-罗森
    链接:https://www.zhihu.com/question/308037541/answer/11...
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


    挖矿,相信很多朋友可能应该已经听说过挖矿,其实就是比特币开采的过程。所谓的挖矿,不是说拿铁锹挖,而是用机器进行复杂的数学计算,这里用到的机器,就是我们常说的矿机,这个矿机是一个硬件设备,买回来插上电就可以挖矿。矿机的计算能力叫做算力,拥有矿机的人就叫做矿工,矿机存放的地方就叫做矿场

    上面面这张图,其实就是一个矿场的实际场景,货架上面放着的,其实就是一台台的矿机。这个每台矿机,挺沉的,搬起来得有二十来斤,这个搬起来跟砖头一样,而且不同型号的矿机,一台几千到上万块钱,价格不等。有的朋友可能会想,那我自己买几台回家挖矿行不行?要是五年前还可以,现在不行了。因为随着市场竞争的加剧,挖矿这个行业,已经进入到了一个巨头博弈的时代,都是大矿场大矿工,甚至是矿霸级别的人物才能玩得起。如果投资一家矿场,至少是一万台起步。一万台,按照刚才我说的价格,那你至少得投入一个亿,而且,我们说80%的矿场,其实都是建在深山老林水电站附近啊。下面这张图啊,就是矿场的外景。

    目前,基本上全球80%的算力,都集中在中国的云贵川,因为这里水电资源丰富,尤其是四川,号称这个世界的矿都。至于比特币具体的挖矿算法,大家不需要了解,只需要知道,比特币一共是2100万枚。目前,每天挖出1800个比特币,每四年产量减半,最后到2140年挖完,已经累计挖出来了1800多万个比特币,最近一次的减半,将会发生在今年的五月份

    一、挖矿原理

    最初的时候,我们用电脑CPU就可以挖到比特币,比特币的创始人中本聪就是用他的电脑CPU挖出了世界上第一个创世区块。然而,CPU挖矿的时代早已过去,现在的比特币挖矿是ASIC挖矿和大规模集群挖矿的时代。

    回顾挖矿历史,比特币挖矿总共经历了以下五个时代:

    CPU挖矿→GPU挖矿→FPGA挖矿→ASIC挖矿→大规模集群挖矿

    挖矿芯片更新换代的同时,带来的挖矿速度的变化是:

    CPU(20MHash/s)→GPU(400MHash/s)→FPGA(25GHash/s)→ASIC(3.5THash/s)→大规模集群挖矿(3.5THash/s*X)

    挖矿速度,专业的说法叫算力,就是计算机每秒产生hash碰撞的能力。也就是说,我们手里的矿机每秒能做多少次hash碰撞,就是算力。算力就是挖比特币的能力,算力越高,挖得比特币越多,回报越高。

    在比特币的世界里,大约每10分钟会记录一个数据块。所有的挖矿计算机都在尝试打包这个数据块提交,而最终成功生成这个数据块的人,就可以得到一笔比特币报酬。最初,大约每10分钟就可以产生50个比特币的比特币报酬。但是该报酬每4年减半,现在每10分钟比特币网络就可以产生25个比特币。

    而要成功生成数据块,就需要矿工需要找到那个有效的哈希值,而要得到正确的哈希值,没有捷径可以走,只能靠猜,猜的过程就是计算机随机hash碰撞的过程,猜中了,你就得到了比特币。

    二、挖矿方法

    挖矿芯片经历了CPU挖矿到GPU挖矿到FPGA挖矿,如今走入了ASIC挖矿时代。然而挖矿的方式也经历了从一两台矿机挖矿到小矿机作坊,再到如今走入了大规模矿场挖矿的时代。

    挖矿方式:从一台矿机到大规模矿场

    如果你开始尝试挖矿,你需要准备一台矿机、一台能联网的电脑、一个AUC、一个树莓派、电源及各种连接线等。各种设备的连接顺序为网线->树莓派->MicroUSB线->AUC->4PIN连接线->矿机和电源。

    上周,四川的一场洪水把许多矿场淹,矿机全部瘫痪,导致全球的比特币算力骤然下降。瞬间把比特币爱好者的目光都聚焦在了我大天朝的天府之国。随着比特币价格的暴涨,越来越多人投身于“挖矿”行业。

    区块链领域常提到的挖矿,其实是工作量证明(Proof Of Work,简称POW)。

    所谓的工作量证明,就是用来确认你做过一定量的工作。监测工作的整个过程通常是极为低效的,而通过对工作的结果进行认证来证明完成了相应的工作量,则是一种非常高效的方式。

    比如现实生活中的毕业证、驾驶证等等,也是通过检验结果的方式(通过相关的考试)所取得的证明。

    区块链挖矿是什么意思

    挖矿是通过消耗计算资源来处理交易,确保网络安全以及保持网络中每个人的信息同步的过程。这个过程因为同淘金类似而被称为“挖矿”,因为它也是一种新的临时机制。POW每年的确消耗了非常多的资源,这是事实,但直到目前为止POW仍然是经过实际证明的很好的方案。

    一、挖矿原理

    最初的时候,我们用电脑CPU就可以挖到比特币,比特币的创始人中本聪就是用他的电脑CPU挖出了世界上第一个创世区块。然而,CPU挖矿的时代早已过去,现在的比特币挖矿是ASIC挖矿和大规模集群挖矿的时代。

    回顾挖矿历史,比特币挖矿总共经历了以下五个时代:

    CPU挖矿→GPU挖矿→FPGA挖矿→ASIC挖矿→大规模集群挖矿

    挖矿芯片更新换代的同时,带来的挖矿速度的变化是:

    CPU(20MHash/s)→GPU(400MHash/s)→FPGA(25GHash/s)→ASIC(3.5THash/s)→大规模集群挖矿(3.5THash/s*X)

    挖矿速度,专业的说法叫算力,就是计算机每秒产生hash碰撞的能力。也就是说,我们手里的矿机每秒能做多少次hash碰撞,就是算力。算力就是挖比特币的能力,算力越高,挖得比特币越多,回报越高。

    在比特币的世界里,大约每10分钟会记录一个数据块。所有的挖矿计算机都在尝试打包这个数据块提交,而最终成功生成这个数据块的人,就可以得到一笔比特币报酬。最初,大约每10分钟就可以产生50个比特币的比特币报酬。但是该报酬每4年减半,现在每10分钟比特币网络就可以产生25个比特币。

    而要成功生成数据块,就需要矿工需要找到那个有效的哈希值,而要得到正确的哈希值,没有捷径可以走,只能靠猜,猜的过程就是计算机随机hash碰撞的过程,猜中了,你就得到了比特币。

    二、挖矿方法

    挖矿芯片经历了CPU挖矿到GPU挖矿到FPGA挖矿,如今走入了ASIC挖矿时代。然而挖矿的方式也经历了从一两台矿机挖矿到小矿机作坊,再到如今走入了大规模矿场挖矿的时代。

    挖矿方式:从一台矿机到大规模矿场

    如果你开始尝试挖矿,你需要准备一台矿机、一台能联网的电脑、一个AUC、一个树莓派、电源及各种连接线等。各种设备的连接顺序为网线->树莓派->MicroUSB线->AUC->4PIN连接线->矿机和电源。

    说起区块链挖矿,相信很多稍微了解的朋友都会想到比特币,毕竟比特币作为头号虚拟货币的地位一直未被动摇。即使现在比特币的价格已经不如往日,但是挖矿热情不减。

    那么区块链挖矿原理是什么?

    关于区块链挖矿原理

    在最新区块链的数据上,生成一个符合条件的区块,链入区块链的过程,就是挖矿。最简单的一种说法就是,在区块链上通过其特定计算公式,最快得到正确答案的人就会获得相应虚拟货币奖励,这一过程就是挖矿,就像做数学题一样。

    区块链挖矿算力

    既然是做数学题,那么就要涉及到算力也就是计算能力。算力又是怎么说的呢?

    算力单位:

    算力就是每隔千位划为一个单位,最小单位 H=1次,1000H= 1K,1000K= 1G,1000G= 1T,1000T= 1P, 1000P=1E。

    S9 13.5T 也等于 13500G / 0.0135P。

    现在比特币全网的算力在24.52EH/s ,就相当于是180万台的S9的算力。

    对于不同的币种而言,挖矿的算法是会不一样的。

    区块链挖矿风险

    了解区块链挖矿原理之后就可以肆无忌惮的挖矿了吗?当然不是,虽说目前我国对于挖矿行为并没有一个违法的规范,不会有什么政策风险。但是,虚拟货币市场价格的波动风险却是存在的,毕竟想要一个高的挖矿收益,那么你需要准备的挖矿设备投入可不是一个小数目。因此,在越来越高的设备投入与不稳定的未来收益之间,就需要你自己去衡量了。

    要想理解挖矿,就要先搞清楚区块链的结构。

    每个区块都包括两个部分:区块体和区块头。区块体有大小限制,不能被无限放大;区块最初的大小被限制在1M字节,这是因为在Segwit被激活之前,根据比特币网络建立之初达成的共识,比特币网络节点只能识别不大于1MB字节的区块。

    区块头主要用来记录说明信息,而区块体则用来记录“交易”。真正的数据记录在客户端的数据库列表中。区块链的结构中重要的是区块头。区块头共有六个字段,分别是:版本号、前一区块的哈希值、梅克尔根、预设的难度值、时间戳、要寻找的随机数。

    其中,版本号主要用于区分软件的升级换代,在一段时间内不变且相同;前一区块的哈希值就是前一区块头的哈希值,10分钟的挖矿过程,在所有矿机中,这个值都不变;梅克尔根也是一个哈希值,由列表中的各交易两两递归生成一个总哈希值;预设的难度值强调,10分钟内所有矿机中的这个值不变且相同;要寻找的随机数就是要获得挖矿奖励的核心要素。挖矿过程就是对上面这六个字段进行一系列转换、连接和哈希运算,不断地寻找随机数,最后成功找到一个随机数满足条件。

    当经过哈希运算后的值比预设难度值的哈希值小时,挖矿就成功了。当然,不管挖矿是否成功,每一节点都要预先把奖励的50个比特币、所有交易的手续费记录在交易列表的第一项,输出地址就是本节点的地址。如果挖矿不成功,这笔交易就作废,没有任何奖励。

    区块链矿业现在还赚钱吗?是或否。这取决于采矿的对象和方法,并且您的电费可能会因您的采矿机器或矿山而异。比特币(BTC)不再是最有利可图的矿业货币:矿业太难了,整个矿山需要大量的服务器来挖掘

    区块链矿业现在还赚钱吗?是或否。这取决于采矿的对象和方法,并且您的电费可能会因您的采矿机器或矿山而异。比特币(BTC)不再是最有利可图的矿业货币:矿业太难了,整个矿井需要用巨大的服务器来挖掘一个区块。幸运的是,我有很多代币,还有赚钱的空间。

    想加入加密矿业,并准备一个基于图形处理器或中央处理器的矿工?了解2020年最有利可图的GPU和CPU挖掘令牌。

    Grin是一种相对较新的基于MimbleWimble一致性算法的密码货币,它保证了网络中交易的隐私性。

    Grin的货币供应量是无限的,这对矿商非常有吸引力。挖掘的复杂性随着网络的散列而动态变化。令牌使用所谓的布谷鸟循环算法。我们正在讨论两种功率算法:CuckCarood-29和CuckAToo-31。第一种适合在GPU设备上进行挖掘,并抵抗ASIC挖掘,第二种是专门针对它们的。

    零现金于2016年10月发布。任何人都可以得到这个令牌。其算法允许使用挖掘图形卡。ZCash在交易中是完全匿名的,不能被追踪。许多人非常喜欢这个功能。

    ZCash交易的手续费很少,所以交易和销售都很方便。2017年,ZCash在一个良好且受欢迎的交易所推出。然而,这一标志被大大低估了,它的潜力很可能只会在2019/2020年显现出来。

    这种比特币分歧出现在2018年,而且流动性很高。今天,它是世界上第41种密码货币,市场价值超过1.55亿美元。2019年,开发人员将增加一套新的强大功能(消息传递、RVN投票、更好的兼容性、与助记符兼容的移动钱包),这将增加其价值。

    拉文硬币可以很容易地在许多不同的平台上交换。本质上,它是一个P2P区块链,用于高效快速地将资产从一个人转移到另一个人。它专注于基于以太网和比特币的资产转移。为什么向矿工推荐拉文科因?它使用X16R算法和工作量证明机制。

    自2014年推出以来,摩纳哥已被证明是一个可靠的象征。自2017年以来,XMR已进入上升趋势并继续增长。与Zcash不同,它的收费是Zcash的10倍,但用户仍然非常重视Monero的匿名性。

    Monero不断修改其算法,以防止ASIC挖掘的可能性,因此您可以使用GPU和CPU挖掘。Monero使用CryptoNightV8工作负载证明算法,每两分钟生成3.38个xmrs作为块奖励,因此挖掘非常有益。

    作为以太网的一个硬分支,以太网经典可以被多个处理器挖掘。它有更高的集体奖励(4 ETC),虽然ETC可能有更高的通货膨胀率和稀缺性,但它仍然是一种非常有利可图的加密货币。购买英伟达或AMD卡,享受被动收入。

    如果你能买到更多或更便宜的图形处理器,试着点击Litecoin ——。简而言之,这是最成功的比特币硬盘之一。为什么选择文学?

    这是另一种可以用于采矿的加密货币。比特币黄金是专为图形处理器开采而创造的。它是基于对等散列算法和功率协议之间的共识。它以2.6亿美元的市值在密码货币名单上排名第34位。

    比特币黄金的主要原因之一是其稳定性。尽管2019年没有增加,但它的波动性似乎比其他伪币要小。今年,人民币可以避免熊市趋势的影响,这是一个好迹象。

    作为ASIC的对立货币之一,电子货币于2017年推出,尽管此后价格没有上涨,但仍有增长潜力。区块链电子琴使用POW算法,并且基于最新的密码算法,所以你甚至可以在你的智能手机上进行挖掘。

    比利马库斯狗币只是为了好玩而发明的,但它突然变得流行起来。现在它是第29个世界密码货币,市值3.46亿美元!像Litecoin一样,它使用Scrypt协议,因此您不必使用非常昂贵的机器来将DOGE添加到您的投资组合中。

    然而,这并不意味着你应该使用你的笔记本电脑进行采矿。狗币很受欢迎,挖掘也不难。利用中央处理器/图形处理器享受稳定的性能和收入。

    2019年,Ethereum成功地获得了第二名,这种货币的价格预计将在3或2个ETH奖励减少后上涨。因此,增加需求和减少供应通常会增加价值。

    乔拉钦斯基,乔技术公司的创始人,声称到2019年底,ETH的价格将达到1200美元。奈杰尔格林认为ETH的售价为2500美元。对数字现金日益增长的需求、智能合同的流行以及云计算的分散化将有助于实现这一目标。

    概览

    本章节我们将会在我们的玩具版区块链的基础上加入工作量证明(POW)的支持。在第一章节的版本中, 任何人都都可以在没有任何工作量证明的情况下添加一个区块到区块链中。 当我们引入工作量证明机制之后,一个节点必须要解开一个有相当计算量的拼图(POW Puzzle)之后,才能往区块链上添加一个新的区块。而去解开该拼图,通常就被称为挖矿。

    引入工作量证明机制之后,我们还可以对一个新区块的产出时间作出大致的控制。大概的做法就是动态的改变拼图的难易程度来达到控制的效果:如果最近的区块产生的太快了,那么就将拼图的难度提升,反之,则将拼图的难度降低。

    需要点出来的时,本章节中我们还没有引入 交易(Transaction) 这个概念。这就意味着矿工挖出一个区块后,并不会获得相应的奖励。 一般来说,在加密货币中,如果矿工挖到了一个区块,是应该获得一定量的币作为激励的。

    工作量证明拼图和难易度

    在上一个章节的区块链的基础上,我们将会为区块结构加入两个新的属性:difficulty和nonce。要弄清楚这俩货是干嘛用的,我们必须先对工作量证明拼图作一些必要的阐述。

    工作量证明拼图是一个什么样的任务呢?其实就是去计算出一个满足条件的区块哈希。怎么才算满足条件呢?如果这个计算出来的哈希的前面的0的数目满足指定的个数,那么就算满足条件。那么这个个数又是谁指定的呢?对,就是上面的这个difficulty指定的。如果difficulty指定说哈希前面要有4个0,但你计算出来的哈希前面只有3个0,那么这个哈希就不是个有效的哈希。

    下图展示的就是不同难易程度的情况下,哈希是否有效:

    以下代码用来检查指定difficulty下哈希是否有效:

    <code>const hashMatchesDifficulty = (hash: string, difficulty: number): boolean => { const hashInBinary: string = hexToBinary(hash); const requiredPrefix: string = '0'.repeat(difficulty); return hashInBinary.startsWith(requiredPrefix); };</code>

    区块的哈希是通过对区块的内容算sha256来获得的,通过相同的区块内容做哈希,我们是无法算出符合指定difficulty的哈希, 因为内容一直没有变,哈希也就一直不变, 这就是为什么我们引入了nonce这个属性到区块中,我们可以控制nonce的改变来获得不同的哈希值。只要我们的内容有任何一点点的改变,算出来的哈希就肯定是不一样的。一旦相应的nonce修改后让我们获得到指定difficulty的哈希,我们挖矿也就成功了!

    既然加入了difficulty和nonce到区块,我们还是先看看区块结构现在长什么样吧:

    <code>class Block { public index: number; public hash: string; public previousHash: string; public timestamp: number; public data: string; public difficulty: number; public nonce: number; constructor(index: number, hash: string, previousHash: string, timestamp: number, data: string, difficulty: number, nonce: number) { this.index = index; this.previousHash = previousHash; this.timestamp = timestamp; this.data = data; this.hash = hash; this.difficulty = difficulty; this.nonce = nonce; } }</code>

    当然,我们的创世区块是硬编码的,记得把它也给更新成相应的结构哦。

    挖矿

    如上所述, 为了解开我们的工作量证明拼图这个任务,我们需要不停的修改区块中的nonce然后计算修改后的哈希,直到算出满足条件的哈希。这个满足条件的哈希什么时候才会跑出来则完全是个随机的事情。所以我们要做的就是给nonce一个初始值,然后不停的循环,修改,计算哈希,直到满足条件的心仪的它的出现。

    <code>const findBlock = (index: number, previousHash: string, timestamp: number, data: string, difficulty: number): Block => { let nonce = 0; while (true) { const hash: string = calculateHash(index, previousHash, timestamp, data, difficulty, nonce); if (hashMatchesDifficulty(hash, difficulty)) { return new Block(index, hash, previousHash, timestamp, data, difficulty, nonce); } nonce++; } };</code>

    一旦满足条件的区块的哈希给找到了,挖矿成功!然后我们就需要将该区块广播到网络上,让其他节点接受我们的区块,并更新最新的账本。这个和第一章节的情况并无二致。

    难易度共识

    我们现在已经拥有找出和验证满足指定难易度的区块的哈希的手段了,但是,这个难易程度是如何决定的呢?必须要有一个方法让全网各个节点一致认同这个决定。不然我的难易度是要挖半天才能出来,别人的是几毫秒就出来,那这个区块链网络就有问题。

    所以,这里必须要有一个方法来让所有的节点都一致认同当前挖矿的难易度。为了做到这一点,我们首先引入一些用于计算当前难易度的规则。

    先定义以下的一些常量:

    • BLOCK_GENERATION_INTERVAL: 定义 一个区块产出的 频率(比特币中该值是设置成10分钟的, 即每10分钟产出一个区块)
    • DIFFICULTY_ADJUSTMENT_INTERVAL: 定义 修改难易度以适应网络不断增加或者降低的网络算力(hashRate, 即每秒能计算的哈希的数量)的 频率(比特币中是设置成2016个区块, 即每2016个区块,然后根据这些区块生成的耗时,做一次难易度调整)

    这里我们将会把区块产出间隔设置成10秒,难易度调整间隔设置成10个区块。这些常量是不会随着时间而改变的,所以我们将其硬编码如下:

    <code>// in seconds const BLOCK_GENERATION_INTERVAL: number = 10; // in blocks const DIFFICULTY_ADJUSTMENT_INTERVAL: number = 10;</code>

    有了这些规则,我们就可以在我们的网络上达成难易度的一致性了。每产出10个区块之后,我们就去检查生成所有这10个区块所消耗的时间,然后和预期时间进行对比,然后对难易度进行动态的调整。

    这里的预期时间是这样指定的:BLOCK_GENERATION_INTERVAL * DIFFICULTY_ADJUSTMENT_INTERVAL。 该预期时间代表了当前网络的算力刚刚好和当前的难易度吻合。

    如果耗时超过或者不足预期时间的两倍,那么我们就会将difficulty进行对应的减1或者加1。该算法如下:

    <code>const getDifficulty = (aBlockchain: Block[]): number => { const latestBlock: Block = aBlockchain[blockchain.length - 1]; if (latestBlock.index % DIFFICULTY_ADJUSTMENT_INTERVAL === 0 && latestBlock.index !== 0) { return getAdjustedDifficulty(latestBlock, aBlockchain); } else { return latestBlock.difficulty; } }; const getAdjustedDifficulty = (latestBlock: Block, aBlockchain: Block[]) => { const prevAdjustmentBlock: Block = aBlockchain[blockchain.length - DIFFICULTY_ADJUSTMENT_INTERVAL]; const timeExpected: number = BLOCK_GENERATION_INTERVAL * DIFFICULTY_ADJUSTMENT_INTERVAL; const timeTaken: number = latestBlock.timestamp - prevAdjustmentBlock.timestamp; if (timeTaken < timeExpected / 2) { return prevAdjustmentBlock.difficulty + 1; } else if (timeTaken > timeExpected * 2) { return prevAdjustmentBlock.difficulty - 1; } else { return prevAdjustmentBlock.difficulty; } };</code>

    时间戳校验

    第一章节中的区块链版本中,区块结构中的时间戳属性是没有任何意义的,因为我们不会对其作任何校验的工作,也就是说,我们其实可以给该时间戳赋以任何内容。 但现在情况变了,因为我们这里引入了难易度的动态调整,而该调整是基于前10个区块产出的耗时总长度的。所以时间戳我们就不能像之前一样随意赋值了。

    既然时间戳的大小会影响区块产出难易度的调整,所以别有用心的人就会考虑去恶意设置一个错误的时间戳来尝试操纵我们的难易度,以实现对我们的区块链网络进行攻击。为了规避这种风险,我们需要引入以下的规则:

    • 新区块时间戳比当前时间最晚不晚过1分钟,那么我们认为该区块有效。
    • 新区块时间戳比前一区块的时间戳最早不早过1分钟,那么我们任务该区块在区块链中是有效的。
    <code>const isValidTimestamp = (newBlock: Block, previousBlock: Block): boolean => { return ( newBlock.timestamp - 60 < getCurrentTimestamp() ) && ( previousBlock.timestamp - 60 < newBlock.timestamp ); };</code>
    天地会珠海分舵注:这里为什么要有一分钟的缓冲呢?估计是为了既考虑一定程度的容错,也减缓了时间戳恶意修改的攻击。如果还有其他原因的,请不吝指教。

    累积难易度

    还记得第一章节的区块链的版本中,我们定的规则是:一旦发生冲突,我们总是选择最长的区块链作为有效的链进行更新,以示对更多区块生产者的努力的肯定。因为我们现在引入了挖矿的难易度,所以我们不应该再这样子做了,我们更应该对投入资源更多计算而出的那条链进行肯定。也就是说,现在正确的链,不是最长的那条链,而是累积难易度最大的那条链。什么意思呢?换个说法就是,正确的链,应该是那条消耗了最多计算资源(网络算力*耗时)而产生出来的链。

    那么怎么算出一条链的累积难易度呢?我们首先对区块链中每个区块的difficulty进行2^difficulty计算,然后将每个区块的计算结果加起来,最终就是这条链的累积难易度。

    这里为什么我们用2difficulty来计算呢?因为difficulty代表了哈希的二进制表示中前面的0的位数。试想下,一个difficulty是11的块和一个difficulty是5的块相比,总的来说,我们需要多计算2(11-5) = 2^6 次哈希才能获得想要的结果。因为每一位在二进制中都有0和1两种变化,他们之间相差6个位,固有2^6个变化。

    下图中,虽然链A比链B长,但因为链B的累积难易度比链A大,所以链B才是正确的链.

    同时我们还要注意的是,我们累积难易度只和区块的difficulty属性有关系,和区块的真实哈希即其前面的位数是没有任何关系的。 拿一个difficulty为4的区块来说,假如它的哈希是000000a34c…(该哈希同时也满足difficulty为5和6的情况),我们计算累积难易度是还是会以24来算,而不是25或者2^6, 即使它前面有6个0.

    这种根据难易度选择正确的链的策略也叫做中本聪共识(Nakamoto consensus), 这也是中本聪的比特币中最重要的一个发明之一。一旦账本出现分叉,矿工们就必须选择一条链来投入资源继续进行挖矿,因为这个关系到矿工挖矿后的激励,所以选择正确的链必须全网达成共识。

    验证测试

    • 安装运行
    <code>npm install npm run node1 npm run node2</code>
    • 挖矿

    我们可以尝试通过curl或者postman调用/mineBlock这个api接口来进行挖矿,并查看对应的输出.

    • 难易度调整

    在通过不同的时间间隔调用完10次/mineBlock这个接口之后,难易度就会相应的进行变化

    • 选择最大累积难易度的链

    这个真实情况不好模拟出来。 但是我们可以去验证对应的算法。我们可以先开一个节点,创建3个以上的区块之后,再开第二个节点。这时节点2就会去获取节点1的所有区块,然后运行对应的逻辑去选择最大累积难易度的链。

    小结

    工作量证明拼图的一个重要特点就是难以解开但易于验证。所以不断调整nonce以算出一个满足一定难度的SHA256哈希,然后简单的验证前面几位是否是0,往往就是这种问题最简单的解决方案。

    有了工作量证明机制后,节点现在就需要挖矿,也就是解决工作量证明拼图,才能往区块链中新增加一个区块了。在下一章节中,我们将会为我们的区块链引入交易(Transaction)功能。

    本章节代码请查看这里

    《第三章》

    本文由天地会珠海分舵翻译整理,喜欢的话请点个赞并关注我,吐槽请评论,如能给Github上的项目给个星,将不胜感激.


    比特币挖矿究竟在计算一个什么问题?手动验证区块链给出答案

    比特币基本的科普写起来更难,因为受众更广,而且市面的文章千篇一律,内容相差无几,做成漫画的形式又耗时耗力,我只在另外一篇文章中做了笔记,等待修改。技术文章则简单得多,基于许多共识,不需要解释太多的基础知识。
    比特币挖矿的算法,可以简单地总结为对区块头做两次sha256哈希运算,得到的结果如果小于区块头中规定的难度目标,即挖矿成功
    区块头的结构如下


    区块头的结构
    那么挖矿的算法可以表达为


    <code class="language-python" style="font-family: Menlo, Monaco, Consolas, "Andale Mono", "lucida console", "Courier New", monospace;"><span class="k" style="font-weight: 600;">for</span> <span class="n">nonce</span> <span class="ow" style="font-weight: 600;">in</span> <span class="nb" style="color: rgb(0, 132, 255);">range</span><span class="p">(</span><span class="mi" style="color: rgb(0, 132, 255);">0</span><span class="p">,</span> <span class="mi" style="color: rgb(0, 132, 255);">2</span><span class="o" style="font-weight: 600;">**</span><span class="mi" style="color: rgb(0, 132, 255);">32</span><span class="p">):</span>
        <span class="n">block_header</span> <span class="o" style="font-weight: 600;">=</span> <span class="n">version</span> <span class="o" style="font-weight: 600;">+</span> <span class="n">previous_block_hash</span> <span class="o" style="font-weight: 600;">+</span> <span class="n">merkle_root</span> <span class="o" style="font-weight: 600;">+</span> <span class="n">time</span> <span class="o" style="font-weight: 600;">+</span> <span class="n">target_bits</span> <span class="o" style="font-weight: 600;">+</span> <span class="n">nonce</span>
        <span class="k" style="font-weight: 600;">if</span> <span class="n">sha256</span><span class="p">(</span><span class="n">sha256</span><span class="p">(</span><span class="n">block_header</span><span class="p">))</span> <span class="o" style="font-weight: 600;"><</span> <span class="n">target_bits</span><span class="p">:</span>
            <span class="k" style="font-weight: 600;">break</span></code>


    简单回顾下挖矿的流程,我们可以定义为四个阶段。


    1. 验证和筛选交易
    2. 计算Merkle root
    3. 计算区块头
    4. 穷举nonce计算hash

    验证和筛选交易

    挖矿节点首先对交易做验证,剔除有问题的,然后通过一套自定义的标准来选择哪些交易希望打包进区块,比如通过交易费与交易占用的字节大小的比值超过某个门槛来判断,这样的交易才被认为有利可图。当然,节点也可以特意选择要加入某条交易,或者故意忽略某些交易,每个挖矿节点有很大的自由裁度权力。如果是通过矿池挖矿的话,矿池的服务器会去筛选交易,然后分配给每个参与的矿机一个独立的任务。这个任务的难度小于总的挖矿难度,通过完成较小难度的计算,来确认自己参与的份额。每台不同的矿机计算的问题不会重复,当其中一台矿机成功挖矿时,所有矿机依据确认的工作量来分配收益。


    计算Merkle root

    一旦筛选好交易数据,按照时间排序,两两哈希,层层约减,通过这些交易就可以计算出一棵Merkle树,可以确定一个唯一的摘要,这就是Merkl树的根。Merkle树中,任何节点的变化,都会导致merkle root发生变化,通过这个值,可以用来验证区块中的交易数据是否被改动过。


    <code class="language-python" style="font-family: Menlo, Monaco, Consolas, "Andale Mono", "lucida console", "Courier New", monospace;"><span class="n">ABCDEEEE</span> <span class="o" style="font-weight: 600;">.......</span><span class="n">Merkle</span> <span class="n">root</span>
          <span class="o" style="font-weight: 600;">/</span>        \
       <span class="n">ABCD</span>        <span class="n">EEEE</span>
      <span class="o" style="font-weight: 600;">/</span>    \      <span class="o" style="font-weight: 600;">/</span>
     <span class="n">AB</span>    <span class="n">CD</span>    <span class="n">EE</span> <span class="o" style="font-weight: 600;">.......</span><span class="n">E与自己配对</span><span class="p">,</span><span class="err" style="color: rgb(241, 64, 60);">奇数树叶时</span>
    <span class="o" style="font-weight: 600;">/</span>  \  <span class="o" style="font-weight: 600;">/</span>  \  <span class="o" style="font-weight: 600;">/</span>
    <span class="n">A</span>  <span class="n">B</span>  <span class="n">C</span>  <span class="n">D</span>  <span class="n">E</span> <span class="o" style="font-weight: 600;">.........</span><span class="err" style="color: rgb(241, 64, 60);">交易</span></code>

    计算区块头

    我们依次获取挖矿需要的每一项区块头信息。 区块头只有80个字节,挖矿只需要对区块头进行运算即可。区块头中的信息,在挖矿前大部分已经是固定的,或者是容易计算的。区块中的交易数据虽然很大,但是已经通过Merkle树固定了下来,不需要再包含进来。
    而所谓的区块链,其实也是通过区块头而链接在一起的。数据结构中的链表,每个节点保存了下个节点的内存地址,而区块链则保存了上个节点的地址。下面的示意图比较简单地解释了区块链和区块的构成。


    比特币区块链示意图
    我们接下来开始逐项准备需要的数字。


    版本号

    跟随比特币客户端而定,一段时间内不会改变。即使要改变,也会有比特币的核心开发人员来协调升级策略,这个可以理解为一个静态常数。


    前一区块摘要

    一次哈希即可。前一区块已经是打包好的。


    默克尔根

    刚才已经得到了结果,根据本次交易包含的交易列表得到。


    时间

    取打包时的时间。也不需要很精确,前后几秒,几十秒也都可以。


    难度目标

    参考上两周产生的区块的平均生成时间而定。两周内如果平均10分钟产生一个区块的话,两周会产生2016个区块,软件会计算最新的2016个区块生成的时间,然后做对比,随之调整难度,使得接下来产生的区块的预期时间保持在10分钟左右。因为最近的2016个区块已经确定,所以这个数字也是确定的。


    随机数nonce

    这个就是挖矿的目标了。这是一个32位的数字。
    随机数可以变化,而且要从0试到最大值2^32。直到最后出现的hash结果,其数字低于难度目标值。不过以现在的计算机算力,一台矿机用不了一秒就把全部的变化可能计算完了,所以还需要改变区块内部的创币交易中的附带消息,这样就让merkle root也发生了变化,从而有更多的可能去找到符合要求的nonce。
    挖矿中,第一笔交易是新发的比特币,接收方就是矿工指定的地址,这是挖矿中最大的奖励;另外一小部分来自交易手续费。这笔交易没有输入方,称为创币交易。创币交易可以附带一段文字消息,比如中本聪在挖出创世区块时植入的信息


    The Times 03/Jan/2009 Chancellor on brink of second bailout for banks
    就是这篇头条文章。


    The Times报纸2009-01-03期

    验证过程

    讲完了基本的原理,我们开始使用实际数据来验证这个算法。我们以区块277316为例,其信息来自网站blockchain.info
    Bitcoin Block #277316blockchain.info
    选择这个区块的原因是为了与《Mastering Bitcoin》一书中的介绍做参考。此书中文社区译本和英文原版在介绍这部分内容时有出入,而且作者Antonopoulos并没有做完整的演算,也没有提到其中关键的字节顺序问题,相信很多人可能会踩这个坑。这里还原的细节可以帮助读者对书中介绍工作量证明的部分彻底理解。


    比特币区块277316的信息
    比特币区块277316的hash值

    请注意下面的每个步骤,每一个变化,这是比特币最核心的算法。



    第一步,准备数据

    <code class="language-python" style="font-family: Menlo, Monaco, Consolas, "Andale Mono", "lucida console", "Courier New", monospace;"><span class="mi" style="color: rgb(0, 132, 255);">2</span> <span class="err" style="color: rgb(241, 64, 60);">(版本号的十进制)</span>
    <span class="mo" style="color: rgb(0, 132, 255);">0000000000000002</span><span class="n">a7bbd25a417c0374cc55261021e8a9ca74442b01284f0569</span> <span class="err" style="color: rgb(241, 64, 60);">(前一区块</span><span class="n">hash值的16进制</span><span class="err" style="color: rgb(241, 64, 60);">)</span>
    <span class="n">c91c008c26e50763e9f548bb8b2fc323735f73577effbc55502c51eb4cc7cf2e</span>  <span class="p">(</span><span class="n">merkle</span> <span class="n">root的16进制</span><span class="p">)</span>
    <span class="mi" style="color: rgb(0, 132, 255);">2013</span><span class="o" style="font-weight: 600;">-</span><span class="mi" style="color: rgb(0, 132, 255);">12</span><span class="o" style="font-weight: 600;">-</span><span class="mi" style="color: rgb(0, 132, 255);">27</span> <span class="mi" style="color: rgb(0, 132, 255);">23</span><span class="p">:</span><span class="mi" style="color: rgb(0, 132, 255);">11</span><span class="p">:</span><span class="mi" style="color: rgb(0, 132, 255);">54</span> <span class="err" style="color: rgb(241, 64, 60);">(</span><span class="n">utc时间</span><span class="err" style="color: rgb(241, 64, 60);">)</span>
    <span class="mi" style="color: rgb(0, 132, 255);">419668748</span>  <span class="err" style="color: rgb(241, 64, 60);">(难度目标的十进制)</span>
    <span class="mi" style="color: rgb(0, 132, 255);">924591752</span>  <span class="err" style="color: rgb(241, 64, 60);">(随机数的十进制)</span></code>
    转换时间,记住,一定要转为utc的时间戳,此处遇到过坑,小心。算法本身不难,困难的是你需要把其中所有的数据都准备正确。


    <code class="language-python" style="font-family: Menlo, Monaco, Consolas, "Andale Mono", "lucida console", "Courier New", monospace;"><span class="o" style="font-weight: 600;">>>></span> <span class="kn" style="font-weight: 600;">import</span> <span class="nn" style="color: rgb(100, 100, 100);">datetime</span>
    <span class="o" style="font-weight: 600;">>>></span> <span class="kn" style="font-weight: 600;">from</span> <span class="nn" style="color: rgb(100, 100, 100);">datetime</span> <span class="kn" style="font-weight: 600;">import</span> <span class="n">timezone</span>
    <span class="o" style="font-weight: 600;">>>></span> <span class="n">datetime</span><span class="o" style="font-weight: 600;">.</sp                                                    
    
    
                                                                                                
添加评论 (需要登录)