主页 > imtoken钱包下载2.0 > 用VC学习BTC:(1)了解区块的保存文件blk*.dat

用VC学习BTC:(1)了解区块的保存文件blk*.dat

imtoken钱包下载2.0 2023-09-19 05:10:17

用VC学习BTC:(1)了解区块的保存文件blk*.dat

虽然先用win10的linux层在Windows上编译并成功运行了bitcoin core,但是对于比较习惯VS开发工具的人来说,在VS下跟踪调试总是比较容易的,所以我准备建一个VS工程编译比特币,逐步学习理解其实现比特币存储文件blkxxxx.dat格式

为了方便在VS上编译运行,先从保存的数据文件开始。 这部分涉及的代码在VS上应该是比较容易跑起来的。

创建项目的步骤如下:

808比特币创始人颜万卫 炮制比特币风险大_比特币dat文件下载_okex比特币莱特币下载

 

#define MESSAGE_START_SIZE 4

unsigned char pchMessageStart[MESSAGE_START_SIZE] = { 0xf9, 0xbe, 0xb4, 0xd9 };

bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)

{

int nLoaded = 0;

尝试 {

// 这会接管 fileIn 并在 CBufferedFile 析构函数中对其调用 fclose()

CBufferedFile blkdat(fileIn, 2 * MAX_BLOCK_SERIALIZED_SIZE, MAX_BLOCK_SERIALIZED_SIZE + 8, SER_DISK, CLIENT_VERSION);

uint64_t nRewind = blkdat。 获取位置();

while (!blkdat.eof()) {

块数据。 设置位置(nRewind);

nRewind++; // 下次再开始一个字节,以防失败

blkdat.SetLimit(); // 移除之前的限制

无符号整数 nSize = 0;

尝试 {

//定位一个header

无符号字符缓冲区[MESSAGE_START_SIZE];

blkdat.FindByte(pchMessageStart[0]);

nRewind = blkdat. 获取位置() + 1;

blkdat >> FLATDATA(buf);

如果 (memcmp(buf, pchMessageStart, MESSAGE_START_SIZE))

继续;

//读取大小

blkdat >> nSize;

如果(nSize < 80 || nSize > MAX_BLOCK_SERIALIZED_SIZE)

继续;

}

赶上(常量 std::exception&){

// 没有找到有效的区块头; 不要抱怨

休息;

}

尝试 {

// 读取块

uint64_t nBlockPos = blkdat。 获取位置();

如果(dbp)

dbp->nPos = nBlockPos;

块数据。 设置限制(nBlockPos + nSize);

块数据。 SetPos(nBlockPos);

std::shared_ptr pblock = std::make_shared();

CBlock&块 = *pblock;

blkdat >> 块;

nRewind = blkdat. 获取位置();

printf("%s\n\n", block.ToString().c_str());

}

赶上(常量 std::exception& e){

printf("%s: 反序列化或 I/O 错误 - %s\n", __func__, e.what());

}

n加载++;

}

}

捕捉(常量 std::runtime_error& e){

printf("系统错误: %s\n", e.what());

}

如果(nLoaded > 0)

printf("从外部文件加载 %i 个块\n", nLoaded);

返回 nLoaded > 0;

}

该函数的主要内容是从比特币的验证码部分复制过来的。 之所以复制比特币dat文件下载,是因为一旦引入验证码,整个工程就会复杂很多。

 

int 主要(无效)

{

// Todo: 更改为存储比特币块文件的真实路径

char path[] = "G:\\blockchain\\bitcoin\\bin\\Bitcoin\\blocks\\blk00000.dat";

FILE *file = fsbridge::fopen(path, "rb");

LoadExternalBlockFile(文件,NULL);

返回 0;

}

这里我偷懒了,直接写了一个保存的block文件的路径,反正就是学习用。

至此,项目文件都已经有了,但是编译还是有问题,因为比特币的源码有依赖。 得益于VS自带的nuget包管理工具比特币dat文件下载,不用自己去下载依赖源码编译了(也是个累人的活,VS下开源代码的编译很烦人)。

右键单击解决方案,然后在弹出菜单中选择“管理解决方案的 NuGet 包”

808比特币创始人颜万卫 炮制比特币风险大_比特币dat文件下载_okex比特币莱特币下载

搜索boost_filesystem-vc141和boost_system-vc141,选择

okex比特币莱特币下载_比特币dat文件下载_808比特币创始人颜万卫 炮制比特币风险大

808比特币创始人颜万卫 炮制比特币风险大_okex比特币莱特币下载_比特币dat文件下载

在撰写本文时已提交此错误的修复程序,但尚未被接受,之后将不加修改地下载源代码。

比特币dat文件下载_808比特币创始人颜万卫 炮制比特币风险大_okex比特币莱特币下载

比特币dat文件下载_okex比特币莱特币下载_808比特币创始人颜万卫 炮制比特币风险大

此时可以跟踪调试查看整个文件的格式!

内容字节数说明

4字节

0xF9 0xBE 0xB4 0xD9

所谓Magic,用于确认区块的开始

4字节

块长度 Little-Endian

小端 unsigned int

区块长度

CBlock 类序列化的数据

CBlock 类在 block.h 文件中定义

内容字节数说明

4字节

版本号

小端 int32_t

32字节

前一个区块的哈希值

小端 uint256

32字节

默克尔根

小端 uint256

4字节

时间戳

区块生成的网络时间

4字节

目标价值

当前区块生成所达到的目标值的特征

4字节

随机数

用于挖矿时生成符合要求的区块哈希

对于紧凑格式整数的读取,在serialize.h的ReadCompactSize模板中,规则是如果第一个字节是255,则读取后面的8个字节为uint64; 如果第一个字节是 254,则读取后续 4 个字节为 uint32; 如果第一个字节是 253,则读取接下来的 2 个字节作为 uint16; 否则,使用第一个字节作为 uint8。

因此,这是一个变长数据,最少占用1个字节,最多占用9个字节。

如果你不想从头开始构建项目,你可以从 csdn 下载它。

【原文首发地址://blog.csdn.net/lazypiggy/article/details/79414709,转载请保留此链接】