以太坊(2)——共识机制与挖矿算法

共识机制

ETH采用的是基于GHOST协议的共识机制

"GHOST"(Greedy Heaviest-Observed Sub-Tree)共识机制,它是以太坊使用的一种改进的区块链共识算法。GHOST共识机制旨在提高链的安全性和效率,通过考虑非主链区块的贡献,减少网络中的分支和拜占庭错误,从而增加整体网络的可靠性。

新的共识机制

原因

ETH的区块产生时间短,更容易出现分支

  1. 新的共识机制着力于解决挖出分支链该怎么办的问题

  2. 新的共识机制解决了 挖矿奖励与算力不成线性正比使分支回到最长合法链 的两个问题

解决方法

对于挖出区块属于的非最长合法链的矿工予以补偿

为什么?

在ETH体系中,依旧有矿池的存在。假设按照BTC的处理方法

一个矿池挖出了一个区块,那么他肯定会沿着这个区块继续挖下去,而其他矿工的算力是分散的,而且更倾向于沿着矿池挖掘的最长合法链挖矿。这就导致了散户矿工拿到的收益与矿池拿到的收益和他们付出的算力不成正比,出现mining centralization的现象,矿池占到更大的便宜。

共识机制的演化

第一版

协议

  1. 每个区块可以包含uncle block,

  2. 被包含的uncle block获得出块奖励的7/8

  3. 包含uncle block的新区块额外获得出块奖励的1/32

  4. 对于uncle block,只判断它的哈希值是否合法,不管它的内容

优点

  1. 补偿了挖出分支区块的矿工

  2. 使得区块链分叉后的更快合并

存在问题

  1. 有的矿工去到很早的节点(几千几万个之前)挖分支区块,由于那时候挖矿难度低,他能获得大量区块,这时候他在主链上把这些区块当成uncle block包含进去,获得大量的以太币。

  2. 某些矿池为了压倒对手,故意不承认uncle block。损己一分,伤敌28倍

第二版

协议改进

  1. 规定uncle block获得的奖励为1-n/8。七代以内有共同祖先的区块才能算是uncle block

  2. 每个区块最多可以包含两个uncle block

改进意义

  1. 鼓励矿工尽早解决分支问题

  2. 小矿工可以尽早转入最长合法链,将自己的区块认作uncle block

区块实例

e0719ec2acb148189034cc3e8e2c9756.png

共识机制补充

局限

共识机制无法改变之前讲到的state fork(软/硬分叉)

BTC和ETH的收入

BTC

静态收入:挖矿奖励

动态收入:交易手续费

静态收入逐渐降低,是为了营造比特币“数字黄金”的稀缺性

ETH

静态收入:挖出最长合法链区块奖励 挖出分支区块的补偿 认叔奖励

动态收入:gas

静态收入基本不会降低,保证了gas费不会成为主要收入,进而保证了对于矿工的补偿机制,可以理解为,以太币是汽油(不会消失的消耗品)

另类uncle block

对于一个长分支链,每个区块都不会获得分支奖励

因为如果奖励的话会降低分叉攻击的成本。

挖矿算法

BTC挖矿的问题

挖矿设备的专业化,降低了去中心化的程度

one CPU,one Vote

因此,此后的加密货币要实现的是ASIC resistance

ASIC resistance可以先看一下BTC部分的挖矿

解决方案

  1. 内存,使得挖矿设备更接近通用计算机

  2. 权益证明,盘外招?

  3. 预挖矿,使得开发者拥有大量资产

方案一

设计需要大量内存的mining puzzle

这种mining puzzle的设计参考了莱特币

LiteCoin(莱特币)

  1. LiteCoin使用的是 scrypt mining puzzle

  2. scrypt mining puzzle是一种需要大量内存的哈希算法

  3. 设计原理:

    1. 创建一个数组,使用一个seed,计算出的值填在第一个位置

    2. 之后,第一个位置的数取哈希,放在第二个的位置,以此类推往后放,直到将整个数组填充满

    3. 在求解mining_puzzle的时候,先取出一个指定位置的存储结果,将这个结果进行一定的运算得到下一个位置;取出”下一个位置“的值,按上述的方法以此类推,最终得到结果

  4. 这样做的好处:使得求解过程变成memory_hord,如果你不用这个数组,计算难度就会大幅度上升(不存储,只能一次一次算到该位置的哈希);如果你使用的话,对内存要求就会很高,实现了ASIC_resistance

  5. ASIC_resistance设计的核心思想是:增加计算过程对于内存的访问次数,使得这个过程跟贴近于普通计算机对于计算资源的配备

  6. 方案劣势:对于轻节点而言,也是memory_hard,因此在实际LiteCoin的使用中,最大的数组为128K。这也使得它对于ASIC的抵制性不高

ETH的挖矿设计

ETH挖矿使用了两个数据集小的是16M的 cache,大的是1G的dataset(DAG)

轻节点只用保存cache,矿工需要保存DAG

数据集

两个数据集的内存大小都在随时间上涨,适应计算机与日俱增的内存容量

cache

生成方式与莱特币数组生成的方式类似(seed在cache中)

DAG

  1. 根据cache,取出某个位置的数据,按照莱特币的方法,迭代256次,放入DAG数组的第一个位置,之后以同样的方法放在DAG的第二个位置,以此类推形成完整的DAG数据集

  2. 求解mining_puzzle的方法是,依照nonce和BlockHeader的数据,映射到DAG的某一个位置;取出这个位置和相邻下一个位置的数据,计算哈希映射到之后的位置,以此类推循环64次计算出区块哈希

  3. 验证区块哈希是否符合target要求

实现代码

ETHASH伪代码

生成cache

def mkcache(cache_size, seed):
    o = [hash(seed)]
    for i in range(1, cache_size):
        o.append(hash(o[-1]))
    return o
  1. 这个函数是通过seed计算出来cache的伪代码(cache中每个元素都是64字节的hash值)。

  2. 伪代码略去了原来代码中对cache元素进一步的处理,只展示原理,即cache中元素按序生成,每个元素产生时与上一个元素相关。

  3. 每隔30000个块会重新生成seed(对原来的seed求哈希值),并且利用新的seed生成新的cache。

  4. cache的初始大小为16M,每隔30000个块重新生成时增大初始大小的1/128(128K)。

生成DAG

//生成DAG中的一个元素
def calc_dataset_item(cache, i):
    cache_size = cache.size
    mix = hash(cache[i % cache_size] ^ i)
    for j in range(256):
    cache_index = get_int_from_item(mix)
    mix = make_item(mix, cache[cache_index % cache_size])
return hash(mix)
//多次调用生成整个DAG
def calc_dataset(full_size, cache):
    return [calc_dataset_item(cache, i)for i in range(full_size)]
  1. 这是通过cache来生成dataset中第 i 个元素的伪代码。

  2. 这个dataset叫作DAG,初始大小为1G,每30000个块更新,同时增大初始大小的1/128(8M)

  3. 先通过cache中的第i%cache_size个元素生成初始的mix,因为两个不同的dataset元素可能对应同一个cache中的元素,为了保证每个初始的mix都不同,(i也参与哈希计算)

  4. 随后循环256次,每次通过get_int_from_item来根据当前的mix值求得一个要访问的cache元素的下标,用这个cache元素和mix通过make_ item求得新的mix值。(由于初始的mix值都不同,所以访问cache的序列也都是不同的)

  5. 迭代256次最终返回mix的哈希值,得到第 i 个dataset中的元素。

  6. 多次调用这个函数,就可以得到完整的dataset。

挖矿与验证

//全节点挖矿
挖出一次hash(取名为最终哈希)
def hashimoto_full(header, nonce, full_size, dataset):
    mix = hash(header, nonce)
    for i in range(64):
        dataset_index= get_int_from_item(mix) % full_size
        mix = make_item(mix,dataset[dataset index])
        mix = make_item(mix,dataset[dataset index + 1])
    return hash(mix)
挖出hash的主循环函数
def mine(full size, dataset, header,target):
    nonce =random.randint(0,2**64)
    while hashimoto_full(header, nonce, full_size, dataset)target:
        nonce =(nonce +1)%2**64
    return nonce
//轻节点验证
def hashimoto_light(header, nonce, full_size, cache):
    mix = hash(header.nonce)
    for i in range(64):
        dataset_index = get_int_from_item(mix) % full_size
        mix = make_item(mix, calc_dataset_item(cache, dataset index))
        mix = make_item(mix, calc_dataset_item(cache, dataset index + 1))
    return hash(mix)

挖矿一次函数

  1. 使用块头,使得轻节点存储占据内存小,方便验证。full_size是数据集的全部元素个数

  2. 首先根据块头的信息和nonce算出初始的哈希值。经过64次循环,每次循环读取大数据集中两个相邻的数(读取的位置由当前哈希值计算出),最后返回一个哈希值

挖出hash主循环函数

将调用一次上面挖矿函数返回的“最终哈希”与target进行比较,如果不满足,再调用挖矿函数

验证函数

  1. 这里的nonce是发布的区块块头里的nonce;使用cache验证,但是这里的full_size指的还是DAG里面的元素个数。

  2. 由于轻节点没有存储DAG,因此需要从cache中重新生成,其他操作的和上述生成一次最终hash类似

  3. 验证的操作分成两步,我们和BTC类比

    1. 验证哈希来源是否合法:BTC验证nonce值是不是生成hash的值,只需要结合块头进行一次哈希计算;而ETH的验证就是走一遍上面生成“最终哈希”的过程,看看生成的hash是不是公布的hash。

    2. 验证哈希是否符合要求(区块是否合法):二者都验证了公布的hash是不是满足target要求

效果

对于轻节点而言,验证的时候只用进行一次“最终哈希的计算”,因此可以逐次计算1G的DAG,但是对于矿工而言。如果存储DAG,每次试“最终哈希”的时候都可以使用,如果不存储,每次都要算,计算量大大提升。

实际上,ETH使用的挖矿算法ethash,到目前为止有效的将挖矿手段限制在了GPU的水平,取得了很好的ASIC_resistance的效果

方案二

使用权益证明(PoS)替代工作量证明(Pow)

权益证明

在权益证明中,区块的产生不再依赖于计算复杂的数学题,而是通过持有和抵押一定数量的以太币(ETH)来获得网络的投票权。持有更多以太币的节点将有更高的几率被选为下一个出块节点,并且会因此获得相应的奖励。

吓唬大家的手段?

之后会讲

方案三

预挖矿(Pre-mining):发行的一部分货币留给以太坊的开发者

预售(Pre-sale):将一部分Pre-mining货币换成资产(现实),用于以太坊的开发工作。如果投资者看好这种货币,可以在Pre-sale阶段购买,等到货币成熟(升值)之后获得收益。

4a136fb924eb46d5a61b20430d96f52c.png

挖矿挖的再努力,赢在起跑线上最重要!(dog)

关于安全性的另一种想法

使用ASIC挖矿有利于安全性提高

  1. 增加了攻击的代价ASIC芯片具有专一性,研发周期长,研发投入高的特点。因此,购买大量矿机的矿池,拥有大量的该货币资产。他们会尽量维持区块链的安全性,因为如果安全性降低(被攻击),该货币就会贬值。

    1. 挖矿收入和现有资产缩水

    2. 购入的矿机由于只能挖这一条链,所以现有的矿机化为废品

  2. 如果通用计算机可以挖矿,那么一些不法分子可能通过租借云计算资源的方式进行攻击,攻击的硬件成本大大降低,区块链安全性下降

至于哪种说法对?具体情况具体分析

挖矿难度的调整

调整算法

基础调整

492704647fc54246be93ca2ec936eb5c.png

  1. 难度炸弹是为了向权益证明过渡

  2. 红色部分设置的是挖矿的难度下限

36cbdd8da8974da79b398b76edd3d984.png

ea75fef64dd14345a1d8a6cd827d6908.png

难度炸弹

c272722298334d29a59b6fe2dc74ab24.png

由于权益证明会导致现有的ETH挖矿体系的硬件设备报废,为了防止出现节点因为不同的意见(造成社区的分裂)而出现分叉的情况,设计了难度炸弹。

之前是设置难度炸弹逼大家转,后来是PoS设计不出来,不得不延长“爆炸”的时间,将区块号回退3000000个。

c6163386061b42b2afba751d5ccd932b.png

前半部分,影响挖矿难度的主要是“基础调整”的公式;难度炸弹爆炸的时候,挖矿难度由它决定,剧增,使得人们转向PoS的证明共识。但是由于研究设计PoS遇到问题,不得不回调难度炸弹的区块数,又出现了此后的情况。

ETH的发展阶段

14d6c7d1443c43e79210d1858ad5c89d.png

BIP(BitCoin Improvement Proposal)

在下调挖矿难度(难度炸弹的回调)的同时要下调挖矿的收入,这是为了

  1. 让之前较难时候挖到区块的矿工承受的住一夜之间难度骤减的心理冲击,得到一些心理安慰。

  2. 同时也维持了挖出货币的总供应量

代码实现

拜占庭阶段计算挖矿难度的调整代码

// calcDifficultyByzantium is the difficulty adjustment algorithm.
// It returns the difficulty that a new block should have when created at the given time,
// given the parent block's time and difficulty. The calculation uses the Byzantium rules.
func calcDifficultyByzantium(time uint64, parent *types.Header) *big.Int {
    // https://github.com/ethereum/EIPs/issues/100
    // algorithm:
    // diff = (parent diff + (parent diff / 2048 * max((2 if len(parent.uncles) else 1) * ((timestamp - parent.timestamp) * 0.9), -99)) + 2^(periodcount-2)
    bigTime := new(big.Int).SetUint64(time)
    bigParentTime := new(big.Int).Set(parent.Time)
    x := new(big.Int)
    y := new(big.Int)
    // More code goes here...
}

基础部分计算

// calcDifficultyByzantium is the difficulty adjustment algorithm.
// It returns the difficulty that a new block should have when created at the given time,
// given the parent block's time and difficulty. The calculation uses the Byzantium rules.
func calcDifficultyByzantium(time uint64, parent *types.Header) *big.Int {
    // https://github.com/ethereum/EIPs/issues/100
    // algorithm:
    // diff = (parent diff + (parent diff / 2048 * max((2 if len(parent.uncles) else 1) * ((timestamp - parent.timestamp) * 0.9), -99)) + 2^(periodcount-2)
    bigTime := new(big.Int).SetUint64(time)
    bigParentTime := new(big.Int).Set(parent.Time)
    x := new(big.Int)
    y := new(big.Int)
    
    // Calculate x: (2 if len(parent.uncles) else 1) * ((timestamp - parent.timestamp) / 9)
    x.Sub(bigTime, bigParentTime)
    x.Div(x, big.NewInt(9))
    if parent.UncleHash == types.EmptyUncleHash {
        x.Sub(big.NewInt(1), x)
    } else {
        x.Sub(big.NewInt(2), x)
    }
    
    //与-99相比
    // Calculate max((2 if len(parent.uncles) else 1) * ((timestamp - parent.timestamp) / 9), -99) 
    if x.Cmp(big.NewInt(-99)) < 0 {
        x.Set(big.NewInt(-99))
    }
​
    // Calculate y: parent difficulty / 2048
    y.Div(parent.Difficulty, big.NewInt(2048))
​
    // Calculate diff: parent diff + (parent diff / 2048 * max((2 if len(parent.uncles) else 1) * ((timestamp - parent.timestamp) / 9), -99))
    x.Mul(y, x)
    x.Add(parent.Difficulty, x)
​
    // Set minimum difficulty
    if x.Cmp(big.NewInt(131072)) < 0 {
        x.Set(big.NewInt(131072))//难度下限
    }
​
    return x
}

难度炸弹计算

// Calculate a fake block number for the ice-age delay:
// https://github.com/ethereum/EIPs/pull/669
// Fake block number = min(0, block.number - 3,000,000)
fakeBlockNumber := new(big.Int)
if parent.Number.Cmp(big.NewInt(2999999)) >= 0 {//判断的是负区块的序号
    fakeBlockNumber.Sub(parent.Number, big.NewInt(2999999))
}
​
// For the exponential factor:
periodcount := new(big.Int).Set(fakeBlockNumber)
periodcount.Div(periodcount, expDiffPeriod)
​
// The exponential factor, commonly referred to as "the bomb":
// diff = diff + 2^(periodcount - 2)
if periodcount.Cmp(big.NewInt(1)) > 0 {
    expDiffPeriod := big.NewInt(100000)
    y := new(big.Int).Sub(periodcount, big.NewInt(2))
    y.Exp(big.NewInt(2), y, nil)
    x.Add(x, y)//x 基础部分难度  y  难度炸弹的附加难度
}

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/633201.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

kubectl详解

文章目录 kubectl详解一、陈述式管理1、陈述式资源管理方法2、k8s相关信息查看2.1 查看版本信息2.1.1 查看资源对象简写2.1.2 查看集群信息2.1.3 配置kubectl自动补全2.1.4 查看日志 2.2 基本信息查看2.2.1 查看集群状态2.2.2 查看命名空间 2.3 命名空间操作2.3.1 查看default命…

CDN用户平台安装说明

CDN用户平台安装说明 登录管理员系统 在”系统设置” – “高级设置” – “用户节点”中点击”添加节点” 如果所示&#xff1a; 节点名称 - 可以任意填写 进程监听端口 - 启动用户节点后&#xff0c;进程所监听的端口&#xff0c;通常是HTTP 80或者HTTPS 443&#xff0c;…

html 段落与排版标记 Web前端开发技术、详细文章(例如)

段落与排版标记 网页的外观是否美观&#xff0c;很大程度上取决于其排版。在页面中出现大段的文字&#xff0c;通常采用分段进行规划&#xff0c;对换行也有极其严格的划分。本节从段落的细节设置入手&#xff0c;利用段落与排版标记自如地处理大段的文字。 段落p标记 在HTM…

Spring Cloud Gateway 网关

一. 什么是网关&#xff08;Gateway&#xff09; 网关就是一个网络连接到另一个网络的关口。 在同一个项目或某一层级中&#xff0c;存在相似或重复的东西&#xff0c;我们就可以将这些相似重复的内容统一提取出来&#xff0c;向前或向后抽象成单独的一层。这个抽象的过程就是…

Linux磁盘高级操作

RAID RAID存储系统是一种数据存储虚拟化技术&#xff0c;它将多个物理磁盘驱动器组合成一个或多个逻辑单元&#xff0c;以提供数据冗余和/或提高性能。 1. RAID 0 无奇偶校验与冗余&#xff08;磁盘容错&#xff09;的条带存储&#xff08;带区卷/条带卷&#xff09; 由两块…

Linux-文件或目录权限

在使用 ll 时&#xff0c;可以查看文件夹内容的详细信息&#xff0c;信息的第1位表示类型&#xff0c;具体信息如下&#xff1a; 类型说明-普通文件d文件夹b块设备文件c字符设备文件p管道文件s套接口文件 第2-10位表示权限&#xff0c; 举例&#xff1a;rwxr-xr-x 类型说明r…

简单快捷的图片格式转换工具:认识webp2jpg-online

经常写博客或记笔记的朋友们可能会碰到图床不支持的图片格式或图片太大需要压缩的情况。通常&#xff0c;我们会在浏览器中搜索在线图片格式转换器&#xff0c;但这些转换器往往伴有烦人的广告或要求登录&#xff0c;并且支持的转换格式有限。最近&#xff0c;我在浏览 GitHub …

java8总结

java8总结 java8新特性总结1. 行为参数化2. lambda表达式2.1 函数式接口2.2 函数描述符 3. Stream API3.1 付诸实践 java8新特性总结 行为参数化lambda表达式Stream Api 1. 行为参数化 定义&#xff1a;行为参数化&#xff0c;就是一个方法接受多个不同的行为作为参数&#x…

HiWoo Box边缘计算网关

​在数字化浪潮汹涌的今天&#xff0c;边缘计算网关成为了连接物理世界与数字世界的桥梁&#xff0c;其重要性日益凸显。HiWoo Box&#xff0c;作为一款功能强大的边缘计算网关&#xff0c;不仅具备了传统网关的基本功能&#xff0c;更在数据采集、处理、传输等方面展现出了卓越…

岛屿问题刷题

200. 岛屿数量 - 力扣&#xff08;LeetCode&#xff09; class Solution {public int numIslands(char[][] grid) {int n grid.length;//grid行数int m grid[0].length;//grid列数int res 0;for(int r 0;r<n;r){for(int c0;c<m;c){if(grid[r][c]1){dfs(grid,r,c);res…

Web Server项目实战3-Web服务器简介及HTTP协议

Web Server&#xff08;网页服务器&#xff09; 一个 Web Server 就是一个服务器软件&#xff08;程序&#xff09;&#xff0c;或者是运行这个服务器软件的硬件&#xff08;计算机&#xff09;。其主要功能是通过 HTTP 协议与客户端&#xff08;通常是浏览器&#xff08;Brow…

面试八股之MySQL篇5——主从同步原理篇

&#x1f308;hello&#xff0c;你好鸭&#xff0c;我是Ethan&#xff0c;一名不断学习的码农&#xff0c;很高兴你能来阅读。 ✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。 &#x1f3c3;人生之义&#xff0c;在于追求&#xff0c;不在成败&#xff0c;勤通…

绿色智能:AI机器学习在环境保护中的深度应用与实践案例

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

CSS transform 三大属性 rotate、scale、translate

transform 浏览器支持定义和用法translate位移函数rotate旋转函数scale缩放函数 浏览器支持 表格中的数字表示支持该属性的第一个浏览器版本号。 紧跟在 -webkit-, -ms- 或 -moz- 前的数字为支持该前缀属性的第一个浏览器版本号。 定义和用法 transform 属性向元素应用 2D…

音视频安卓主板记录仪手持终端定制开发_基于MT6762平台解决方案

音视频安卓主板采用了基于MT6762高性能处理器芯片的设计&#xff0c;其中包括4个主频高达2.0GHz的Cortex-A53核心和4个主频1.5GHz的Cortex-A53高效聚焦核心&#xff0c;可提供无比流畅的体验。搭载Android 12操作系统&#xff0c;系统版本进行了全新的优化&#xff0c;进一步确…

新火种AI|净利润上升628%,英伟达财报说明AI热潮还将持续

作者&#xff1a;一号 编辑&#xff1a;美美 AI大潮仍未放缓&#xff0c;英伟达再次超越预期。 今天凌晨&#xff0c;全球AI算力芯片龙头&#xff0c;被称为“AI时代卖铲人”的英伟达&#xff0c;正式公布了截至2024年4月28日的2025财年第一财季财报&#xff0c;其中第一财季…

Linux:top命令的每一列的具体含义

Linux&#xff1a;top命令的每一列的具体含义 文章目录 Linux&#xff1a;top命令的每一列的具体含义图片显示top命令的概念语法显示字段的含义顶部字段第二行第三行第四行第五行每列字段的含义 图片显示 top命令的概念 top命令上一个常用的Linux命令行工具&#xff0c;用于实…

医院是自建档案室还是档案寄存好呢

医院可以选择自建档案室或档案寄存&#xff0c;具体选择取决于医院的需求和资源。 自建档案室意味着医院会拥有自己的档案空间和设施&#xff0c;可以更方便地管理和保管档案。这种方式可以确保医院对档案的访问和控制有更多的自主权&#xff0c;同时也能够根据医院的需求进行档…

是做软件开发,还是软件测试,哪个职业更好,全方位对比

文章目录 前言一、市场需求二、技能需求三、工作强度四、行业趋势总结 前言 在IT行业中&#xff0c;软件开发和软件测试这两个职业长期共存&#xff0c;相爱相杀。很多人都纠结过是做软件开发还是做软件测试&#xff0c;本篇文章将进行全方位对比分析&#xff0c;供各位读者参…

小程序-收货地址管理模块实现

页面结构代码&#xff1a; address-form.vue --->新建地址和修改地址页面 <template><view class"content"><form><!-- 表单内容 --><view class"form-item"><text class"label">收货人</text>…