以太坊暂未修复的一个bug-数组越界

2024-01-25 09:30

本文主要是介绍以太坊暂未修复的一个bug-数组越界,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前些天朋友遇到一个关于以太坊使用的leveldb导致的数组越界问题,一起讨论了很久。如果大家持续使用以太坊节点,迟早也会遇到此问题,在本篇文章中给大家分析一下,做好提前准备。

异常信息

我们先看一下具体的异常信息,对于普通的异常重启geth节点即可解决,但如果遇到下面这个异常信息,重启或升级版本都是无法解决的。

INFO [04-28|10:03:35] Starting peer-to-peer node               instance=Geth/v1.7.3-stable/linux-amd64/go1.9
INFO [04-28|10:03:35] Allocated cache and file handles         database=/mnt/data/eth/geth/chaindata cache=128 handles=1024
panic: runtime error: index out of rangegoroutine 1 [running]:
github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb.shortenb(0x10040ff1126, 0x4, 0xc4204bf9f8)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb/util.go:30 +0x14d
github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb.(*version).computeCompaction(0xc4416120f0)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb/version.go:395 +0x4b3
github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb.(*versionStaging).finish(0xc4204bfd18, 0xc4201e8000)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb/version.go:510 +0x935
github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb.(*version).spawn(0xc420182230, 0xc4201e8000, 0xc420182230)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb/version.go:279 +0x7a
github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb.(*session).commit(0xc4201d0240, 0xc4201e8000, 0x0, 0x0)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb/session.go:195 +0x88
github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb.(*DB).recoverJournal(0xc4200ee600, 0xc4200ee600, 0xc420068660)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb/db.go:538 +0xdb8
github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb.openDB(0xc4201d0240, 0x0, 0x0, 0xc4201d0240)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb/db.go:122 +0x6ba
github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb.Open(0x185e540, 0xc4202047e0, 0xc4204c02f0, 0x0, 0x0, 0x0)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb/db.go:194 +0x100
github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb.OpenFile(0xc4201f7ba0, 0x1c, 0xc4204c02f0, 0xc4201c5bb0, 0x4, 0x4)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb/db.go:216 +0x97
github.com/ethereum/go-ethereum/ethdb.NewLDBDatabase(0xc4201f7ba0, 0x1c, 0x80, 0x400, 0x1c, 0x0, 0x0)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/ethdb/database.go:72 +0x363
github.com/ethereum/go-ethereum/node.(*ServiceContext).OpenDatabase(0xc4202a2da0, 0xf4ad6c, 0x9, 0x80, 0x400, 0x0, 0x0, 0x0, 0x0)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/node/service.go:46 +0x133
github.com/ethereum/go-ethereum/eth.CreateDB(0xc4202a2da0, 0xc4203f4800, 0xf4ad6c, 0x9, 0x0, 0x0, 0x0, 0x0)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/eth/backend.go:201 +0x5d
github.com/ethereum/go-ethereum/eth.New(0xc4202a2da0, 0xc4203f4800, 0x181d560, 0xc4204c5808, 0x417268)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/eth/backend.go:111 +0x93
github.com/ethereum/go-ethereum/cmd/utils.RegisterEthService.func2(0xc4202a2da0, 0xc4204b4420, 0xc4204c5b18, 0x0, 0xc4204b4450)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/cmd/utils/flags.go:1065 +0x3d
github.com/ethereum/go-ethereum/node.(*Node).Start(0xc4201f4480, 0x0, 0x0)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/node/node.go:175 +0x433
github.com/ethereum/go-ethereum/cmd/utils.StartNode(0xc4201f4480)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/cmd/utils/cmd.go:62 +0x2f
main.startNode(0xc420230840, 0xc4201f4480)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/cmd/geth/main.go:225 +0x43
main.geth(0xc420230840, 0xffbbe0, 0xb2d05e00)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/cmd/geth/main.go:215 +0x43
github.com/ethereum/go-ethereum/vendor/gopkg.in/urfave/cli%2ev1.HandleAction(0xdd0280, 0xffd068, 0xc420230840, 0xc420230840, 0xc4204c5f40)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/vendor/gopkg.in/urfave/cli.v1/app.go:490 +0xd2
github.com/ethereum/go-ethereum/vendor/gopkg.in/urfave/cli%2ev1.(*App).Run(0xc420250000, 0xc4200100e0, 0xe, 0xe, 0x0, 0x0)/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/vendor/gopkg.in/urfave/cli.v1/app.go:264

异常分析

先查看一下异常信息的第一段代码位置:

/mnt/go/src/github.com/ethereum/go-ethereum-1.7.3/build/_workspace/src/github.com/ethereum/go-ethereum/vendor/github.com/syndtr/goleveldb/leveldb/util.go:30

进入此源代码之后,能够看到如下代码:

var bunits = [...]string{"", "Ki", "Mi", "Gi"}func shortenb(bytes int) string {i := 0for ; bytes > 1024 && i < 4; i++ {bytes /= 1024}return fmt.Sprintf("%d%sB", bytes, bunits[i])
}

其中异常就发生在return代码部分,也就是通过bunits[i]获取数据时,i的值超出了bunits数组的范围。

看这段代码,当shortenb传入的bytes<1024 * 1024 * 1024是没问题的,i <= 3。但是,当bytes>1024 * 1024 * 1024 * 1024时,也就是单位到TB的时候,i的值将等于4,此时将发生数组越界异常。

为什么刚才说大家迟早会遇到这个问题呢,就是当我们同步区块链数据一开始就使用full或者很早就采用full模式的话,数据量很快会到达TB级别,而leveldb的这段代码,当到达TB级别之后就会出现数组越界异常。

问题解决方案

上面已经分析了问题的原因,那么怎么解决这个问题呢?将数组bunits再扩展一个“Ti”项?这样修改不敢打包票会修复问题,因为只是在数组里面添加一个类型,不确定其他地方是否能够使用此类型。如果要这样修改,可能需要通读相关的代码,然后测试验证才可以。

另外一种比较轻量级的改动是将for循环中i<4的判断修改为i<3,修改后的代码为:

var bunits = [...]string{"", "Ki", "Mi", "Gi"}func shortenb(bytes int) string {i := 0for ; bytes > 1024 && i < 3; i++ {bytes /= 1024}return fmt.Sprintf("%d%sB", bytes, bunits[i])
}

这样再拿上面bytes>1024 * 1024 * 1024 * 1024计算一下,当单位编程TB的时候,会使用1024GB,符合原来数组的最大单位。

PS:当然,修改之后大家是需要进行相应级别数据量的测试验证的。

更多资讯

**获取更多资讯,请关注微信公众号:程序新视界。或加入QQ技术交流群:659809063。个人博客:www.choupangxia.com,区块链相关gitchat课程:http://gitbook.cn/gitchat/column/5ad98d9479e8c577efc7557d

QQ技术交流群:
这里写图片描述

获得一对一技术咨询请扫码加入知识星球(小密圈)
这里写图片描述

这篇关于以太坊暂未修复的一个bug-数组越界的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/642839

相关文章

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机

C语言:柔性数组

数组定义 柔性数组 err int arr[0] = {0}; // ERROR 柔性数组 // 常见struct Test{int len;char arr[1024];} // 柔性数组struct Test{int len;char arr[0];}struct Test *t;t = malloc(sizeof(Test) + 11);strcpy(t->arr,

C 语言基础之数组

文章目录 什么是数组数组变量的声明多维数组 什么是数组 数组,顾名思义,就是一组数。 假如班上有 30 个同学,让你编程统计每个人的分数,求最高分、最低分、平均分等。如果不知道数组,你只能这样写代码: int ZhangSan_score = 95;int LiSi_score = 90;......int LiuDong_score = 100;int Zhou

计算数组的斜率,偏移,R2

模拟Excel中的R2的计算。         public bool fnCheckRear_R2(List<double[]> lRear, int iMinRear, int iMaxRear, ref double dR2)         {             bool bResult = true;             int n = 0;             dou

C# double[] 和Matlab数组MWArray[]转换

C# double[] 转换成MWArray[], 直接赋值就行             MWNumericArray[] ma = new MWNumericArray[4];             double[] dT = new double[] { 0 };             double[] dT1 = new double[] { 0,2 };

【经验交流】修复系统事件查看器启动不能时出现的4201错误

方法1,取得『%SystemRoot%\LogFiles』文件夹和『%SystemRoot%\System32\wbem』文件夹的权限(包括这两个文件夹的所有子文件夹的权限),简单点说,就是使你当前的帐户拥有这两个文件夹以及它们的子文件夹的绝对控制权限。这是最简单的方法,不少老外说,这样一弄,倒是解决了问题。不过对我的系统,没用; 方法2,以不带网络的安全模式启动,运行命令行,输入“ne

PHP7扩展开发之数组处理

前言 这次,我们将演示如何在PHP扩展中如何对数组进行处理。要实现的PHP代码如下: <?phpfunction array_concat ($arr, $prefix) {foreach($arr as $key => $val) {if (isset($prefix[$key]) && is_string($val) && is_string($prefix[$key])) {$arr[

Go 数组赋值问题

package mainimport "fmt"type Student struct {Name stringAge int}func main() {data := make(map[string]*Student)list := []Student{{Name:"a",Age:1},{Name:"b",Age:2},{Name:"c",Age:3},}// 错误 都指向了最后一个v// a