主页 > 钱包imtoken > 【详解】2020年以太坊挖矿及难度调整过程

【详解】2020年以太坊挖矿及难度调整过程

钱包imtoken 2024-01-01 05:09:24

2020年以太坊挖矿及难度调整过程

在比特币的挖矿过程中,只需要进行比较简单的哈希运算,不需要额外的计算资源(内存等),所以比特币的挖矿过程逐渐变成了算力的竞争,所以出现了ASIC矿机,与个人电脑相比,这种矿机进行普通计算,其计算能力是个人电脑的数千倍,刚好适合比特币挖矿。 因此,普通人要想挖矿,就必须有更专业的设备,而挖矿行业出现了中心化的现象,这与比特币最初设计的去中心化理念背道而驰。

因此,在设计以太坊挖矿时,采用了一种新的挖矿流程来实现 ASIC Resistance。 ASIC只能进行计算,没有额外的存储空间,所以以太坊在挖矿过程中设计了两种数据结构,即Cache和dataset。 Cache大小为16M,dataset大小为1G。 对于矿工来说,每次选择一个nonce进行挖矿操作,都必须从dataset中读取数据,这就需要矿机具备存储能力。 引入读内存操作,大大降低了ASIC矿机的算力,使得挖矿优势不那么明显,普通个人电脑也可以进行挖矿。 具体挖矿流程如下:

根据当前区块信息生成一个Seed种子。

根据Seed种子生成一个16M的Cache。 Cache是​​一个List结构,它的数据是前后关联的。

基于Cache生成1G大小的Dataset(也叫Dag)。

矿工每次选择一个Nonce后,从Dataset中读取两个数字进行挖矿测试,直到找到合适的Nonce。

区块链每增加30000个区块,Cache和Dataset的大小都会增加11281128,也就是说Cache会增加128K,Dataset会增加8M。 生成Cache的算法如下:

def mkcache(cache_size, seed): cache = [hash(seed)] for i in range(1,cache_size): cache.append(hash[cache[-1]]) return cache12345

数据集的生成来自缓存。 具体来说,dataset[i]元素的生成需要cache和cache[i]的参与。 数据集中第i个元素的生成代码如下:

def cal_dataset_i(cahce, i):# 计算dataset[i] cache_size = cache.size mix = hash(cache[i%cache_size]^i)# cache远远小于dataset,让i也参与运算,从而使得mix不会重复 for j in range(256): cache_index = get_int(mix); mix = make_item(mix,cache[cache_index%cache_size]) return hash(mix)1234567

以上代码为伪代码,省略了大部分细节,重点在于展示原理。

首先通过缓存中的i%cache_size元素生成初始mix,因为两个不同的dataset元素可能对应同一个缓存中的元素,为了保证每次初始mix都是不同的,注意i也参与了hash计算。

然后循环256次,每次使用get_int根据当前mix值获取下一个要访问的缓存元素的下标,并使用这个缓存元素和mix通过make_item获取新的mix值。 注意,由于初始的mix值不同,所以访问缓存的顺序也不同。

最后返回mix的hash值,得到第i个数据集中的元素。

多次调用此函数以获得完整的数据集。

通过缓存生成数据集的元素时,根据当前使用的缓存元素的值计算下一次要使用的元素在缓存中的位置,这样具体的访问顺序是事先不可预知的,满足伪随机性。 原始数据集的代码如下:

def calc_dataset(full_size, cache): return [calc_dataset_item(cache,i) for i in range(full_size)]12

数据集生成后,矿工就可以开始挖矿,按照特定的流程计算哈希值。 代码如下。 64次循环没有额外的原因,就是增加了挖矿过程中的内存访问操作。 为了提高挖掘速度,矿工必须将数据集存储在内存中。

# 根据nonce计算出一个哈希值def get_hash_value(header, nonce, full_size, dataset): hash_value = hash(header, nonce); for i in range(64): dataset_index = get_int(hash_value )%full_size hash_value = make_item(hash_value , dataset[dataset_index) hash_value = make_item(hash_value , dataset[dataset_index+1]) return hash(hash_value )12345678

如果nonce不合适,则需要替换nonce,直到找到合适的nonce。 整个挖矿过程的伪代码如下:

def mine(full_size, dataset, header, target): max_nonce = 2**64 nonce = random.randint(0, max_nonce ) while get_hash_value(header, nonce, full_size, dataset) > target: nonce = (nonce+1)%max_nonce return nonce123456

为什么要在挖矿中设计缓存? 矿工挖矿的时候好像根本不用缓存,何必呢? 这是为了方便轻节点验证区块。 对于轻节点来说,不可能存储一个大的数据集,但是轻节点可以存储一个缓存,在验证区块头时,根据缓存在数据集中生成一个元素,然后验证区块的有效性。 轻节点验证区块合法性的伪代码如下:

def varify(header, nonce, full_size, cache): hash_value = hash(header, nonce) for i in range(64): index = get_int(hash_value)%full_size hash_value = hash(hash_value, cal_dataset_i(cache,index))# 计算生成dataset中的数据 hash_value = hash(hash_value,cal_dataset_i(cache,index+1)) return hash(hash_value)1234567

矿工需要验证大量的随机数。 如果每次都从16M的缓存中重新生成,挖矿效率会大大降低,而且会出现大量的重复计算:随机选择的数据集的很多元素都是重复的。 它可能在之前尝试其他随机数时使用过。 因此,矿工采用以空间换时间的策略来保存整个数据集。 由于轻节点只验证一个nonce,所以直接生成数据集中的元素来验证时使用即可。

以太坊挖矿难度调整

以太坊中的区块难度调整公式如下图所示。

挖矿莱特币好还是比特币好_比特币调整挖矿难度_比特币挖矿机真能挖到比特币吗

参数说明

在区块链难度调整中比特币调整挖矿难度,创始区块的难度设置为D0=131072D0=131072,此后每个区块的难度都与其父区块的难度相关。 D(H)为该区块的难度,由P(H)Hd+x×ζ2P(H)Hd+x×ζ2和难度炸弹εε组成。

P(H)HdP(H)Hd是父块的难度,每个块的难度都是根据父块的难度来调整的。

x×ζ2x×ζ2用于自适应调整出块难度,保持稳定的出块速度。

εε 代表难度炸弹。

难度有最小下限,即不能低于D0=131072D0=131072

xx和ε2ε2的计算方法如下图所示。

挖矿莱特币好还是比特币好_比特币调整挖矿难度_比特币挖矿机真能挖到比特币吗

xx是父块难度的1204812048四舍五入,是调整的单位。

εε是调整因子,它的最小值只能是-99。

y的值取决于父块是否包含叔块,如果是,则y=2,否则y=1。

HSHS是本块的时间戳,P(H)HsP(H)Hs是父块的时间戳,单位秒,HS>P(H)HsHS>P(H)Hs。

难度降低的上限设置为-99,主要是为了应对被黑客攻击或者其他当前突发的黑天鹅事件。

假设当父块没有叔块时(y=1),调整过程如下:

出块时间在[1,8]之间,如果出块时间太短,增加一个单位的难度。

出块时间在[9,17]之间,出块时间可以接受,难度不变。

出块时间在[18,26]之间,如果出块时间过长,难度应该降低一个单位。

……

这里发现,当出块时间变长时,出块的整体难度会降低。 如果一些矿工故意在后面更改区块的时间戳,他们可以先释放区块吗? 例如,如果时间戳延迟 15 秒会怎样? 这样,矿工计算出的难度比其他矿工计算出的难度要低。 其他矿工在 15 秒内发布区块,而矿工可以在 10 秒内发布区块并获得区块奖励。 但问题是,如果另一个区块刚好在 10 秒内发布了一个区块,根据 POW 规则,另一个矿工发布的区块难度更大,所以其他矿工会根据最大工作量标准选择 15 秒。 挖出区块所在的链为主链,矿工释放的区块成为叔块。

难度炸弹计算公式如下图所示。

挖矿莱特币好还是比特币好_比特币调整挖矿难度_比特币挖矿机真能挖到比特币吗

εε 是 2 的指数函数,每 100,000 个区块翻一番,后期增长非常快,这就是难度“炸弹”的由来。

H'iHi'称为假块号,是将真实块号HiHi减去三百万得到的。 之所以减少 300 万,是因为目前的 proof of stake of work 方法还存在一些问题。 pos协议并不完美,但是难度炸弹导致挖矿时间变成了30秒左右。 为了降低难度,将减去三百万。

之所以设置难度炸弹,是为了降低迁移到 PoS 协议时分叉的风险。 如果矿工联合起来抵制POS的工作量证明模式,将导致以太坊出现硬分叉; 越大,矿工越愿意迁移到 PoS 协议。 从下图可以看出难度炸弹的威力。

比特币挖矿机真能挖到比特币吗_比特币调整挖矿难度_挖矿莱特币好还是比特币好

区块数达到370万后,挖矿难度骤增。 到了430万的时候,难度就已经很高了。 此时挖矿时间已经改为30秒比特币调整挖矿难度,但POS协议还没有完善,所以以太坊将挖矿难度公式调整为每次计算当前区块数减去300万,降低了挖矿难度,在此期间,以太坊区块奖励由原来的5ETH调整为3ETH。

以太坊中的难度计算公式如下图所示。 由于目前以太坊发展处于Metropolis拜占庭阶段,难度计算公式的函数名称为calcDifficultyByzantium

以太坊挖矿原理以太坊挖矿软件以太坊挖矿难度以太坊挖矿指南以太坊挖矿算法以太坊挖矿难度与收益以太坊挖矿教程以太坊挖矿收益计算以太坊挖矿2020以太坊挖矿收益