ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

EIP-1588 硬分叉 Meta 解析:Ethereum ProgPoW 的规范、参数与安全边界

EIP-1588 硬分叉 Meta 解析:Ethereum ProgPoW 的规范、参数与安全边界 EIP-1588 硬分叉 Meta 解析Ethereum ProgPoW 的规范、参数与安全边界【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs本文以 EIPS/eip-1588.md 为骨架完整继承其硬分叉规范定义并深度融合其所引用的 EIPS/eip-1057.md 算法规范与 assets/eip-1057/test-vectors.md 测试向量带读者系统理解 ProgPoW 的动机、参数调优、核心代码流程与安全考量。读完后你将能准确描述该硬分叉的激活条件与包含范围理解 ProgPoW 相比 Ethash 的六大结构性改动掌握算法参数表、关键伪代码与验证测试向量的使用方法并了解其已公开的安全审计结论与未修复漏洞的边界。一、EIP-1588一次以 ProgPoW 为核心的备选硬分叉EIP-1588 是一份Meta 类型的 EIP其作用并非定义新的协议机制而是打包一组改动为它们赋予统一的代号、激活时机与范围。根据 EIPS/eip-1588.md 的 Abstract它规范了名为Ethereum ProgPoW的备选以太坊硬分叉所包含的全部变更。该文档的 Specification 非常简洁全部内容如下代号CodenameEthereum ProgPoW别名AliasesN/A无激活条件Activation以太坊主网Block 7280000包含的 EIPEIP-1057——ProgPoW一种程序化工作量证明算法Programmatic Proof-of-Work这是一份典型的薄壳型 meta-EIP所有实质性的技术内容都沉淀在被引用的 EIP-1057 中。EIP-1588 的意义在于为社区讨论与节点协调提供一个统一的指代——当开发者或研究者提到Ethereum ProgPoW 分叉时指的是在主网 7,280,000 区块高度激活 ProgPoW这一整套方案。值得注意的是该 EIP 当前状态为Stagnant停滞意味着它并未进入最终采纳流程历史背景是 ProgPoW 的争议与以太坊最终转向 PoS 共识但本文仍以仓库文档为准介绍其规范内容。从仓库检索可以看到ProgPoW 曾长期出现在以太坊核心开发者会议的候选清单中EIPS/eip-2378.md 的 EIP-1057 状态表将其标记为ELIGIBLE合格候选并注明讨论日期为 2019-11-01可见该提案曾是一条真实的、进入过治理流程的技术路线而非纸面空想。二、为什么需要 ProgPoWASIC 抗性之争ProgPoW 的设计动机源自以太坊黄皮书对 PoW 的两条根本诉求引自 EIPS/eip-1057.md 的 Motivation 部分尽可能让更多人参与尽量减少对专用、稀有硬件的需求或奖励使用电换以太的转换率对全球任何人都大致公平杜绝超线性收益不允许高资金壁垒的参与者攫取不成比例的算力与奖励从而威胁网络安全。Ethash 选择了顺序内存硬sequential memory-hard这条路线来对抗 ASIC——它要求确定 nonce 需要大量内存与带宽使得内存无法并行服务多个 nonce 求解。但 EIP-1057 作者指出以太坊区块链 5 年运行经验暴露了这条路线的新问题Ethash 专用 ASIC如 Antminer E3已能提供高于 GPU 的效率当时估计网络中可能多达40% 的算力由 ASIC 保障这直接违背了黄皮书的两条设计目标。ProgPoW 的应对思路是走黄皮书所说的第二条路径——让专用硬件的定义本身变成通用硬件使算法的资源需求与市售 GPU 的特性完全匹配从而让为算法定制的 ASIC 几乎没有效率优化空间。EIP-1057 给出的量化结论是即便实现 ProgPoW 的定制 ASIC其相对 GPU 的效率增益也仅有约1.1~1.2 倍远低于 Ethash 的约 2 倍、CryptoNight 的约 50 倍、以及 SHA256 / Scrypt / X11 等算法的约 1000 倍。2.1 ProgPoW 的六大核心元素EIP-1057 将算法改动归纳为以下六点元素说明替换 Keccak 变体从 keccak_f160064 位字改为 keccak_f80032 位字降低功耗占比增大 mix 状态增加算法中间混合状态的规模随机数学序列主循环中加入随机序列的数学运算小容量低延迟缓存读取新增对支持随机寻址的小型低延迟缓存的读取扩大 DRAM 读取单次 DAG 读取从 128 字节提升到 256 字节周期性程序更换随机序列每隔PROGPOW_PERIOD块更换一次约 2~12 分钟取决于配置其中周期性程序更换是 ProgPoW 的灵魂随机序列变化时挖矿软件在宿主机 CPU 上为这段序列生成源码并现场编译GPU 执行的是数学操作与 mix 状态均已解析完毕的编译产物。由于程序每PROGPOW_PERIOD默认 10 块约 2 分钟就更换一次矿工没有足够时间手工优化特定随机序列——这正是Programmatic程序化一词的由来。2.2 既有 PoW 算法的 ASIC 效率增益对比EIP-1057 对主流 PoW 算法做了系统性比较下表完整继承了原文档的估算数据潜在 ASIC 效率增益算法潜在 ASIC 效率增益原因SHA256~1000X纯简单算术/逻辑/旋转指令序列ASIC 上一颗哈希核只需少量晶体管与连线Scrypt / NeoScrypt~1000X运算与 SHA 类似且 scratchpad 仅 32~128KB可轻易放进 ASIC 芯片内X11 / X16R~1000X多个哈希核按固定流水线或简单状态机排序单核效率与 SHA 相当Equihash~100X~150MB 状态虽大但 ASIC 可实现分箱/排序/比较可超高速完成Cuckoo Cycle~100X专用图遍历核的增益与 SHA 计算核相当CryptoNight~50X需完整 2MB scratchpad片上 SRAM 主导实现限制哈希核数量Ethash~2XDAG 体积大需外部内存但只需最小计算ASIC 可退化为内存接口 小计算引擎ProgPoW~1.1~1.2XGPU 绝大部分资源被算法用满仅可移除图形管线与浮点单元等EIP-1057 还给出了一个犀利的概念辨析CPU 和 GPU 本身就是通用 ASIC任何能在其上运行的算法理论上都能被定制 ASIC 以略少的功能实现。因此ASIC 抗性的准确定义应是——专用硬件与广泛采用硬件之间的效率差距差距越小抗性越强算法越好。这一度量标准是本文后续理解所有设计取舍的钥匙。三、算法规范参数、原语与核心流程ProgPoW 的全部行为由一组可调参数决定下表完整继承 EIPS/eip-1057.md 的参数定义参数含义PROGPOW_PERIOD更换随机程序的块数间隔PROGPOW_LANES协同计算单个哈希实例的并行 lane 数PROGPOW_REGS寄存器文件使用规模PROGPOW_DAG_LOADS每个 lane 从 DAG 加载的 uint32 数量PROGPOW_CACHE_BYTES缓存大小字节PROGPOW_CNT_DAGDAG 访问次数即算法外层循环64 与 Ethash 相同PROGPOW_CNT_CACHE每轮循环的缓存访问次数PROGPOW_CNT_MATH每轮循环的数学运算次数EIP-1057 文档给出了 0.9.2 与 0.9.3 两版参数演进对照表此处完整保留参数0.9.20.9.3PROGPOW_PERIOD5010PROGPOW_LANES1616PROGPOW_REGS3232PROGPOW_DAG_LOADS44PROGPOW_CACHE_BYTES16x102416x1024PROGPOW_CNT_DAG6464PROGPOW_CNT_CACHE1211PROGPOW_CNT_MATH2018以及 DAG 参数DAG 参数0.9.20.9.3ETHASH_DATASET_PARENTS256256关键解读PROGPOW_PERIOD从 50 降到 10程序更换更频繁约 2 分钟一次进一步压缩手工优化随机序列的时间窗。原文档特别说明若程序仅随 DAG epoch 更换约 5 天一次部分矿工将有时间针对随机序列开发手工优化版本从而获得不当优势。数值约定规范代码为 C所有数值均按无符号 32 位整数计算溢出在下一次计算前截断。Python、JavaScript 等非定长数值语言以及 Java 等仅用有符号整数的语言实现时需特别注意位宽语义。这一设计与现代 GPU 的内部数据架构32 位保持一致。3.1 两个基础随机/合并原语FNV1a32 位变体——用于合并数据。Ethash 使用 FNV1而 ProgPoW 改用分布性质更优的 FNV1aconst uint32_t FNV_PRIME 0x1000193; const uint32_t FNV_OFFSET_BASIS 0x811c9dc5; uint32_t fnv1a(uint32_t h, uint32_t d) { return (h ^ d) * FNV_PRIME; }KISS99——用于随机数生成。它是指令数最少、且能通过 TestU01 统计测试套件的随机生成器之所以不用 Mersenne Twister 这类更复杂的生成器是因为它能在专用 ASIC 上被高效实现反而给 ASIC 留下效率优化的空间typedef struct { uint32_t z, w, jsr, jcong; } kiss99_t; uint32_t kiss99(kiss99_t st) { st.z 36969 * (st.z 65535) (st.z 16); st.w 18000 * (st.w 65535) (st.w 16); uint32_t MWC ((st.z 16) st.w); st.jsr ^ (st.jsr 17); st.jsr ^ (st.jsr 13); st.jsr ^ (st.jsr 5); st.jcong 69069 * st.jcong 1234567; return ((MWC^st.jcong) st.jsr); }3.2 mix 状态初始化fill_mixfill_mix用 FNV 将每 warp 的种子扩展为每 lane 的种子再用 KISS99 填充每个 lane 的mix数组规模为PROGPOW_REGSvoid fill_mix( uint64_t seed, uint32_t lane_id, uint32_t mix[PROGPOW_REGS] ) { uint32_t fnv_hash FNV_OFFSET_BASIS; kiss99_t st; st.z fnv1a(fnv_hash, seed); st.w fnv1a(fnv_hash, seed 32); st.jsr fnv1a(fnv_hash, lane_id); st.jcong fnv1a(fnv_hash, lane_id); for (int i 0; i PROGPOW_REGS; i) mix[i] kiss99(st); }3.3 哈希原语keccak_f800与 Ethash 一样Keccak 用于按 nonce 播种序列并产出最终结果。ProgPoW 采用keccak-f800变体因为其 32 位字宽与现代 GPU 原生字宽匹配。其实现是 SHAKE 的变体width800、bitrate576、capacity224、output256、无填充。Keccak 结果按 256 位大端数处理结果第 0 字节为 MSB。由于输入输出固定且较小只需单次 absorb 与 squeezehash32_t keccak_f800_progpow(uint32_t* state) { // 单次 absorb 的 keccak_f800 调用 for (int r 0; r 22; r) keccak_f800_round(st, r); // 固定 8 字输出的 squeeze 阶段 hash32_t ret; for (int i0; i8; i) ret.uint32s[i] st[i]; return ret; }3.4 程序种子初始化progPowInitprogPowInit从prog_seed生成两个序列mix_seq_dstmerge 的目标寄存器序列与mix_seq_src缓存读取的源寄存器序列。它保证每个目标恰好被 merge 一次、缓存读取无重复重复读取可能被优化掉并使用 Fisher-Yates 洗牌实现随机化kiss99_t progPowInit(uint64_t prog_seed, int mix_seq_dst[PROGPOW_REGS], int mix_seq_src[PROGPOW_REGS]) { kiss99_t prog_rnd; prog_rnd.z fnv1a(FNV_OFFSET_BASIS, prog_seed); prog_rnd.w fnv1a(prog_rnd.z, prog_seed 32); prog_rnd.jsr fnv1a(prog_rnd.w, prog_seed); prog_rnd.jcong fnv1a(prog_rnd.jsr, prog_seed 32); // 生成 merge() 的 mix 目标序列与缓存读取的 mix 源序列 for (int i 0; i PROGPOW_REGS; i) { mix_seq_dst[i] i; mix_seq_src[i] i; } for (int i PROGPOW_REGS - 1; i 0; i--) { int j; j kiss99(prog_rnd) % (i 1); swap(mix_seq_dst[i], mix_seq_dst[j]); j kiss99(prog_rnd) % (i 1); swap(mix_seq_src[i], mix_seq_src[j]); } return prog_rnd; }3.5 数据合并与随机数学merge 与 mathmerge将新数据 b 并入高熵值 a刻意只保留熵的操作不做a b这类会降低熵的运算uint32_t merge(uint32_t a, uint32_t b, uint32_t r) { switch (r % 4) { case 0: return (a * 33) b; case 1: return (a ^ b) * 33; // 避免旋转 0 位那是 NOP case 2: return ROTL32(a, ((r 16) % 31) 1) ^ b; case 3: return ROTR32(a, ((r 16) % 31) 1) ^ b; } }math的 11 种运算全部选取自 CUDA/OpenCL 的原生指令——mul_hi、min、clz、popcount、rotate等均与 OpenCL 内建函数一一对应ROTR32 等价于rotate(i, 32-v)。这正是算法要求匹配 GPU 硬件原则在指令层面的落地uint32_t math(uint32_t a, uint32_t b, uint32_t r) { switch (r % 11) { case 0: return a b; case 1: return a * b; case 2: return mul_hi(a, b); case 3: return min(a, b); case 4: return ROTL32(a, b); case 5: return ROTR32(a, b); case 6: return a b; case 7: return a | b; case 8: return a ^ b; case 9: return clz(a) clz(b); case 10: return popcount(a) popcount(b); } }3.6 内层循环progPowLoopprogPowLoop的流程每轮迭代选择loop % LANES号 lane 作为本轮的leader用 leader 的mix[0]值对 DAG 中 256 字节条目数取模决定从完整 DAG 何处读取每个 lane 以(lane ^ loop) % LANES作为条目内起始偏移顺序读取DAG_LOADS个字执行随机序列的数学运算与缓存访问在循环末尾合并本轮读到的 DAG 数据延迟到最后合并是为了充分隐藏内存延迟。dag参数指向以 32 位无符号整数小端分组的 Ethash DAG 字节在小端架构上它就是一个指向现有 DAG 的普通 int32 指针。DAG_BYTES为当前 DAG 的字节数其生成方式与既有 Ethash 完全一致。原文档还解释了(l ^ loop)混洗的深层意图防止多芯片 ASIC 各自只存储 DAG 的一部分。void progPowLoop( const uint64_t prog_seed, const uint32_t loop, uint32_t mix[PROGPOW_LANES][PROGPOW_REGS], const uint32_t *dag) { // dag_entry 保存从 DAG 加载的 256 字节数据 uint32_t dag_entry[PROGPOW_LANES][PROGPOW_DAG_LOADS]; // 每轮旋转哪个 lane 作为 DAG 地址来源保证上一轮 DAG 数据反馈到本轮地址 uint32_t dag_addr_base mix[loop%PROGPOW_LANES][0] % (DAG_BYTES / (PROGPOW_LANES*PROGPOW_DAG_LOADS*sizeof(uint32_t))); for (int l 0; l PROGPOW_LANES; l) { size_t dag_addr_lane dag_addr_base * PROGPOW_LANES (l ^ loop) % PROGPOW_LANES; for (int i 0; i PROGPOW_DAG_LOADS; i) dag_entry[l][i] dag[dag_addr_lane * PROGPOW_DAG_LOADS i]; } int mix_seq_dst[PROGPOW_REGS]; int mix_seq_src[PROGPOW_REGS]; int mix_seq_dst_cnt 0; int mix_seq_src_cnt 0; kiss99_t prog_rnd progPowInit(prog_seed, mix_seq_dst, mix_seq_src); int max_i max(PROGPOW_CNT_CACHE, PROGPOW_CNT_MATH); for (int i 0; i max_i; i) { if (i PROGPOW_CNT_CACHE) { // 缓存内存访问lane 访问 DAG 前部区域的随机 32 位位置 int src mix_seq_src[(mix_seq_src_cnt)%PROGPOW_REGS]; int dst mix_seq_dst[(mix_seq_dst_cnt)%PROGPOW_REGS]; int sel kiss99(prog_rnd); for (int l 0; l PROGPOW_LANES; l) { uint32_t offset mix[l][src] % (PROGPOW_CACHE_BYTES/sizeof(uint32_t)); mix[l][dst] merge(mix[l][dst], dag[offset], sel); } } if (i PROGPOW_CNT_MATH) { // 随机数学生成两个唯一源寄存器 int src_rnd kiss99(prog_rnd) % (PROGPOW_REGS * (PROGPOW_REGS-1)); int src1 src_rnd % PROGPOW_REGS; int src2 src_rnd / PROGPOW_REGS; if (src2 src1) src2; // src2 现在是不等于 src1 的任意寄存器 int sel1 kiss99(prog_rnd); int dst mix_seq_dst[(mix_seq_dst_cnt)%PROGPOW_REGS]; int sel2 kiss99(prog_rnd); for (int l 0; l PROGPOW_LANES; l) { uint32_t data math(mix[l][src1], mix[l][src2], sel1); mix[l][dst] merge(mix[l][dst], data, sel2); } } } // 在循环最末尾消费全局加载数据以充分隐藏延迟 // 始终合并进 mix[0] 以喂养下一次偏移计算 for (int i 0; i PROGPOW_DAG_LOADS; i) { int dst (i0) ? 0 : mix_seq_dst[(mix_seq_dst_cnt)%PROGPOW_REGS]; int sel kiss99(prog_rnd); for (int l 0; l PROGPOW_LANES; l) mix[l][dst] merge(mix[l][dst], dag_entry[l][i], sel); } }3.7 整体流程progPowHash算法整体分为六个阶段与 Ethash 保持headernonce 播种 → 循环混合 → 归约 → 最终哈希的宏观结构对 header nonce 做一次 keccak_f800 哈希得到 256 位摘要填充与 Ethash 的自定义填充一致用摘要前两个字作为种子生成初始 mix 数据多次循环将随机加载与随机数学反复混入 mix将所有 mix 数据归约为单个 256 位值用初始摘要 最终 mix 256 位值做第二次 keccak 哈希填充一致挖矿时将最终哈希与hash32_t目标值比较。hash32_t progPowHash( const uint64_t prog_seed, // 值为 (block_number/PROGPOW_PERIOD) const uint64_t nonce, const hash32_t header, const uint32_t *dag // 位于显存中的 GB 级 DAG——前部区域被缓存 ) { hash32_t hash_init; hash32_t hash_final; uint32_t mix[PROGPOW_LANES][PROGPOW_REGS]; // 初始 keccak 通道的 absorb 阶段 { uint32_t state[25] {0x0}; // 1st: 填充 header 数据8 字 for (int i 0; i 8; i) state[i] header.uint32s[i]; // 2nd: 填充 nonce2 字 state[8] nonce; state[9] nonce 32; // 3rd: 应用填充 state[10] 0x00000001; state[18] 0x80008081; hash_init keccak_f800_progpow(state); // 取种子以初始化 mix seed ((uint64_t)hash_init.uint32s[1] 32) | hash_init.uint32s[0]); } // 为所有 lane 初始化 mix for (int l 0; l PROGPOW_LANES; l) fill_mix(seed, l, mix[l]); // 执行随机生成的内层循环 for (int i 0; i PROGPOW_CNT_DAG; i) progPowLoop(prog_seed, i, mix, dag); // 将 mix 数据归约为每 lane 的 32 位摘要 uint32_t digest_lane[PROGPOW_LANES]; for (int l 0; l PROGPOW_LANES; l) { digest_lane[l] FNV_OFFSET_BASIS; for (int i 0; i PROGPOW_REGS; i) digest_lane[l] fnv1a(digest_lane[l], mix[l][i]); } // 将所有 lane 归约为单个 256 位摘要 for (int i 0; i 8; i) digest.uint32s[i] FNV_OFFSET_BASIS; for (int l 0; l PROGPOW_LANES; l) digest.uint32s[l%8] fnv1a(digest.uint32s[l%8], digest_lane[l]); // 最终 keccak 通道的 absorb 阶段 { uint32_t state[25] {0x0}; // 1st: 填充 hash_init8 字 for (int i 0; i 8; i) state[i] hash_init.uint32s[i]; // 2nd: 填充主循环摘要8 字 for (int i 8; i 16; i) state[i] digest.uint32s[i - 8]; // 3rd: 应用填充 state[17] 0x00000001; state[24] 0x80008081; hash_final keccak_f800_progpow(state); } // 将最终哈希与目标值比较 [...] }四、测试向量验证实现正确性的唯一标准ProgPoW 的工程可验证性极强——仓库在 assets/eip-1057/ 目录下提供了三份测试资产人类可读的 assets/eip-1057/test-vectors.md、机器可读的 assets/eip-1057/test-vectors-0.9.2.json 与 assets/eip-1057/test-vectors-0.9.3.json。任何语言/平台的实现都可以用这些向量逐函数校准。4.1 基础原语向量fnv1a如fnv1a(0X811C9DC5, 0XDDD0A47B) 0XD37EE61Akiss99以z362436069, w521288629, jsr123456789, jcong380116160为初态第 1 次调用得769445856第 100,000 次调用得941074834fill_mix以hash_seed0xEE304846DDD0A47B、lane_id0填充的 mix 数组首值为0x10C02F0D, 0x99891C9E, ...lane_id13 时则有另一组完全不同的 32 个值keccak_f800_progpow两个官方用例给定 header 8 字与 seed 后产出固定 digestmerge / math每个分支路径都有对应向量例如merge的mul/add、xor/mul、rotl/xor、rotr/xor四路径math的 add、mul、mul_hi32、min、rotl32、rotr32、and、or、xor、clz、popcount 共 11 种运算。4.2 progPowInit 与 progPowLoop 向量对于 ProgPow period 600即块 30,000progPowInit应产出长度为 32 的 src 序列0x1A, 0x1E, 0x01, ...、dst 序列0x00, 0x04, 0x1B, ...以及 KISS99 状态z0x6535921C, w0x29345B16, jsr0xC0DD7F78, jcong0x1165D7EB。progPowLoop向量则给出块 30,000、第 1 轮循环后mix[0]到mix[15]全部 16 条 lane 的完整 mix 数组快照——任何一行数值不匹配都意味着实现存在偏差这是逐 lane、逐寄存器级别的严格校验。4.3 progPowHash 端到端向量以块 30,000 为例EIP-1057 文档给出了完整链路Header : 0xffeeddccbbaa9988776655443322110000112233445566778899aabbccddeeff Nonce : 0x123456789abcdef0 Hash init : 0xee304846ddd0a47b98179e96b60ec5ceeae2727834367e593de780e3e6d1892f Mix seed : 0x7ba4d0dd464830ee Mix hash : 0x493c13e9807440571511b561132834bbd558dddaa3b70c09515080a6a1aff6d0 Hash final : 0x46b72b75f238bea3fcfd227e0027dc173dceaa1fb71744bd3d5e030ed2fed053test-vectors.md 的progPowHash一节还补充了 0.9.2 与 0.9.3 两个版本的序列化向量Block 0、49、50、99、29,950、29,999、30,000、30,049、30,050、30,099、59,950、59,999 直至 Block 100,000,000覆盖prog_seed从 0 到 2,000,000 的跨度并标注了prog_seed block_number / PROGPOW_PERIOD的计算关系。其中 0.9.2 与 0.9.3 的差异正对应上文参数表中PROGPOW_CNT_CACHE12→11与PROGPOW_CNT_MATH20→18的调整是理解参数如何影响输出结果的第一手资料。五、安全考量审计结论、已知漏洞与修复边界EIP-1057 是极少数同时接受过软件与硬件双重审计的 PoW 提案原文档记录了以下关键结论1. 软件审计Least Authority审计方建议修改 DAG 生成——将ETHASH_DATASET_PARENTS从 256 提升到 512以缓解Light Evaluation轻量求值攻击。副作用是 ProgPoW 的 DAG 内存文件将不再与 Ethash 兼容epoch 长度与体积增长比例不变。但 EIP 作者明确建议暂不实施此修复Ethash 数年之内不会可被利用也不清楚 ProgPoW 是否会被利用部署经过审计的代码是更优选择。2. 硬件审计Bob Rao作为配套的 ASIC 实现可行性评估结论同样支撑效率增益有限的核心论点。3. Kik 发现的绕过内存硬性漏洞该漏洞同样存在于 Ethash但近不可利用而在 ProgPoW 中实际不可利用——它假设攻击者能像比特币那样构造候选块 header 的变体而以太坊做不到这一点。攻击者需要修改块 header、需要接受修改后 header 的定制节点、并以非常规方式使用 extraNonce/extraData 作为熵且暴力搜索难以在一个出块时间内完成即便定制节点支持其产出的块也会因 header 哈希无效而被其他对等节点立即拒绝。4. 类似漏洞与建议修复作者后来发现了与 Kik 类似的另一漏洞但其开销过大反而对 ASIC 不友好。若要彻底防范此类利用可将最后一次 keccak 通道的输入状态从header256 位 mix 种子64 位 主循环 mix256 位 无填充改为初始 keccak 摘要256 位 主循环 mix256 位 填充从而把 keccak 暴力搜索的约束宽度从 64 位扩大到 256 位。该修复以 PR 形式存在于参考实现中但作者同样建议暂不实施。5. 影响边界原文档特别强调上述漏洞均无法用于拒绝服务、双花或破坏网络最坏情况只是给部署者带来对普通矿工的效率优势。六、实现参考与许可证说明EIP-1057 的参考挖矿实现位于 ifdefelse 的 ProgPOW 仓库文档链接指向 GitHub 外部仓库本文仅转述其事实它是 ethminer 的衍生品因此保留GPL 许可证——这对想基于参考实现二次开发的团队是一个重要的合规前提。七、总结EIP-1588 以一份极简的 meta-EIP 将 ProgPoWEIP-1057打包为Ethereum ProgPoW备选硬分叉激活区块门槛为主网 7,280,000。剥开这层薄壳其技术内核是一套为商品化 GPU量身定制的工作量证明用 keccak_f800、FNV1a、KISS99 与 Fisher-Yates 洗牌构建随机程序用PROGPOW_PERIOD10 块级的高频程序更换阻止手工优化用覆盖全部 11 种 GPU 原生指令的math运算填满通用硬件资源最终把定制 ASIC 的相对效率增益压到约 1.1~1.2 倍。该提案曾进入核心开发者会议候选流程见 EIPS/eip-2378.md最终状态为 Stagnant但其完整的参数表、伪代码与测试向量体系至今仍是研究程序化抗 ASIC PoW设计的范本。若要继续深挖可直接研读 EIPS/eip-1057.md 全文、assets/eip-1057/test-vectors.md 的逐函数向量以及两份 JSON 机器可读向量文件。【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表