在之前的文章中,我曾经提到过,可以通过block_log.index
计算出指定的区块在block_log
中的位置。那么具体如何操作呢?这篇文章我们就来探究一下。
(图源 :pixabay)
为了进行测试,我先停到我本地的节点,并复制出来一份block_log.index
文件:(当然也可以不停,我怕搞砸了):
注意到上图中我画红圈的信息:
Database flushed at last irreversible block: 61482890
也就是说写入到数据库中(block_log.index
& block_log
& shared_memory.bin
)最新的不可逆块为61482890。先不去block_log
& shared_memory.bin
,其实我们可以通过block_log.index
算出最新的不可逆块号的。
做到这点很简单,只需使用ls -l
指令即可:
-rw-rw-r-- 1 test1234 test1234 491863120 Feb 3 02:20 block_log.index
其中的491863120
是文件的长度,而每个块的索引值占用8个字节,所以我们用这个数值除以8,就可以计算出最新不可逆块号:
是不是有点神奇?之所以这样是因为block_log.index
文件就是按块号堆积的索引值,格式如下:
+----------------+----------------+-----+-------------------+
| Pos of Block 1 | Pos of Block 2 | ... | Pos of Head Block |
+----------------+----------------+-----+-------------------+
(注意到这个格式文件中最后一个是Pos of Head Block
,而我们拿到的是最近不可逆块的位置,这是因为停掉节点时只会保留不可逆块的信息。)
好,有了这个格式信息之后,其实我们就可以读取任意区块在block_log
中的位置信息了。尽管许多编程语言都可以干这事,但是其它语言都忘得八九不离十了,那么还是用Python吧。
Python读取二进制文件,主要就四个操作:
- 使用
open
打开文件 - 使用
seek
定位位置 - 使用
read
读取内容 - 使用
close
关闭文件
所以,如果我们要读取上述block_log.index
最后8个字节的内容,那么示例代码如下:
f = open('block_log.index', 'rb')
f.seek(-8, 2)
data = f.read(8)
data_str = hexlify(data).decode()
pprint(data_str)
f.close()
上述代码输入如下内容:
'91a8b36a7c000000'
我们可以使用hexdump来对照一下:
tail -c 8 block_log.index |hexdump -C
上述指令输出如下内容:
可见我们读取的每什么问题,那么如何读取任意区块呢?只需修改如下成代码即可:
block_num = xxxx
f.seek((block_num-1)*8, 0)
我们代入61482890
这个块号,来计算一下,读出来的内容,与上述内容并无区别。也就是说我们可以用修改后的代码读取任意区块的索引信息。
接下来我们来看看怎么把上述输出内容,转变成我们可以阅读或者拿来使用的位置信息。在说这个问题之前,要说一下字节序(Byte Order)
的问题,字节序简单来讲就是:
大于一个字节类型的数据在内存中的存放或者传递时顺序。
拿我们读出来的结果91a8b36a7c000000
,内存中依次放置着0x91, 0xa8, 0xb3等几个数字,那么转换成一个数字,哪个数放前边,哪个数放后边呢?
在这里,我们使用的是little-endian
也就是说:低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
接下来的就好办了,使用如下代码获取位置信息:
pos = struct.unpack_from("<Q", data)[0]
print('0x%X' % pos)
结合之前的代码,上述代码输出:0x7C6AB3A891
,这个就是区块61482890
在block_log中的位置信息哦。
(图源 :pixabay)
好了,今天我们就学习到这里,不管你有没有学废,反正我是学废啦。