每天进步一点点:使用Python获取指定区块在block_log中的位置信息。

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@oflyhigh·
0.000 HBD
每天进步一点点:使用Python获取指定区块在block_log中的位置信息。
在之前的文章中,我曾经提到过,可以通过`block_log.index`计算出指定的区块在`block_log`中的位置。那么具体如何操作呢?这篇文章我们就来探究一下。


![image.png](https://images.hive.blog/DQmYB84ifTTMNX4PACzTz9cLYb4M7EBaMEGJsP2nYUTQ2tB/image.png)
(图源 :[pixabay](https://pixabay.com/illustrations/battery-energy-green-technology-1162477/))

为了进行测试,我先停到我本地的节点,并复制出来一份`block_log.index`文件:(当然也可以不停,我怕搞砸了):
>![image.png](https://images.hive.blog/DQmVeKMZ15L63VSZ1ZUs8PKbwmhML5sRZ9yTugs8tmZ2VUs/image.png)

注意到上图中我画红圈的信息:
>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,就可以计算出最新不可逆块号:
>![image.png](https://images.hive.blog/DQmbqagtr68uBkCXSjfkakfsTYFRgwhnue8fhhS6EY88jeU/image.png)

是不是有点神奇?之所以这样是因为`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`

上述指令输出如下内容:
![image.png](https://images.hive.blog/DQmdduhXTuh74dXUan31BaZ8JCWLhnozcne6CUWMzsjDUG9/image.png)

可见我们读取的每什么问题,那么如何读取任意区块呢?只需修改如下成代码即可:
>`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中的位置信息哦。


![image.png](https://images.hive.blog/DQmbcxzunFVtBndBApPwRv25TrjrJ3Ab34P24iHw22yb4fV/image.png)
(图源 :[pixabay](https://pixabay.com/illustrations/lightbulb-bulb-light-idea-energy-1875247/))

好了,今天我们就学习到这里,不管你有没有学废,反正我是学废啦。
👍 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,