在blk文件中找寻目标块及交易示例
bitcoin所有得交易信息都以block的形式存放在文件中,存访文件名为blkxxxxx.dat,文件存放在blocks目录下。如测试网的block文件存放在testnet3\blocks目录下。
首先,设置当前数据主目录,
gArgs.SoftSetArg("-datadir",PATH);
其中PATH为主目录,可使用函数
GetDataDir()
来查看当前数据路径。
使用结构体CDiskBlockPos来存访block文件所在位置,其定义如下:
struct CDiskBlockPos
{
int nFile; // blk文件编号,如129,表示blk000129.dat
unsigned int nPos; // 文件指针偏移值
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(VARINT(nFile));
READWRITE(VARINT(nPos));
}
CDiskBlockPos() {
SetNull();
}
CDiskBlockPos(int nFileIn, unsigned int nPosIn) {
nFile = nFileIn;
nPos = nPosIn;
}
friend bool operator==(const CDiskBlockPos &a, const CDiskBlockPos &b) {
return (a.nFile == b.nFile && a.nPos == b.nPos);
}
friend bool operator!=(const CDiskBlockPos &a, const CDiskBlockPos &b) {
return !(a == b);
}
void SetNull() { nFile = -1; nPos = 0; }
bool IsNull() const { return (nFile == -1); }
std::string ToString() const
{
return strprintf("CBlockDiskPos(nFile=%i, nPos=%i)", nFile, nPos);
}
};
使用函数OpenBlockFile打开区块文件,定义如下:
/** Open a block file (blk?????.dat) */
FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false);
打开成功后,返回一个文件指针。
使用类CBufferedFile来读取文件内容,定义如下:
/** Non-refcounted RAII wrapper around a FILE* that implements a ring buffer to
* deserialize from. It guarantees the ability to rewind a given number of bytes.
*
* Will automatically close the file when it goes out of scope if not null.
* If you need to close the file early, use file.fclose() instead of fclose(file).
*/
class CBufferedFile
{
private:
const int nType;
const int nVersion;
FILE *src; // source file
uint64_t nSrcPos; // how many bytes have been read from source
uint64_t nReadPos; // how many bytes have been read from this
uint64_t nReadLimit; // up to which position we're allowed to read
uint64_t nRewind; // how many bytes we guarantee to rewind
std::vector<char> vchBuf; // the buffer
protected:
// read data from the source to fill the buffer
bool Fill() {
unsigned int pos = nSrcPos % vchBuf.size();
unsigned int readNow = vchBuf.size() - pos;
unsigned int nAvail = vchBuf.size() - (nSrcPos - nReadPos) - nRewind;
if (nAvail < readNow)
readNow = nAvail;
if (readNow == 0)
return false;
size_t nBytes = fread((void*)&vchBuf[pos], 1, readNow, src);
if (nBytes == 0) {
throw std::ios_base::failure(feof(src) ? "CBufferedFile::Fill: end of file" : "CBufferedFile::Fill: fread failed");
} else {
nSrcPos += nBytes;
return true;
}
}
public:
CBuffere