Created
December 15, 2017 16:35
-
-
Save jngbng/0b8b4861481b0df53746f734ea542c68 to your computer and use it in GitHub Desktop.
bitcoin core write block to disk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// validation.cpp | |
/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */ | |
static bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock) | |
{ | |
// ... | |
// Header is valid/has work, merkle tree and segwit merkle tree are good...RELAY NOW | |
// (but if it does not build on our best tip, let the SendMessages loop relay it) | |
if (!IsInitialBlockDownload() && chainActive.Tip() == pindex->pprev) | |
GetMainSignals().NewPoWValidBlock(pindex, pblock); | |
int nHeight = pindex->nHeight; | |
// Write block to history file | |
try { | |
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); | |
CDiskBlockPos blockPos; | |
if (dbp != nullptr) | |
blockPos = *dbp; | |
if (!FindBlockPos(state, blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != nullptr)) | |
return error("AcceptBlock(): FindBlockPos failed"); | |
if (dbp == nullptr) | |
if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) | |
AbortNode(state, "Failed to write block"); | |
if (!ReceivedBlockTransactions(block, state, pindex, blockPos, chainparams.GetConsensus())) | |
return error("AcceptBlock(): ReceivedBlockTransactions failed"); | |
} catch (const std::runtime_error& e) { | |
return AbortNode(state, std::string("System error: ") + e.what()); | |
} | |
if (fCheckForPruning) | |
FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE); // we just allocated more disk space for block files | |
return true; | |
} | |
static bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) | |
{ | |
// ... | |
unsigned int nFile = fKnown ? pos.nFile : nLastBlockFile; | |
if (vinfoBlockFile.size() <= nFile) { | |
vinfoBlockFile.resize(nFile + 1); | |
} | |
if (!fKnown) { | |
while (vinfoBlockFile[nFile].nSize + nAddSize >= MAX_BLOCKFILE_SIZE) { | |
nFile++; | |
if (vinfoBlockFile.size() <= nFile) { | |
vinfoBlockFile.resize(nFile + 1); | |
} | |
} | |
pos.nFile = nFile; | |
pos.nPos = vinfoBlockFile[nFile].nSize; | |
} | |
if ((int)nFile != nLastBlockFile) { | |
if (!fKnown) { | |
LogPrintf("Leaving block file %i: %s\n", nLastBlockFile, vinfoBlockFile[nLastBlockFile].ToString()); | |
} | |
FlushBlockFile(!fKnown); | |
nLastBlockFile = nFile; | |
} | |
vinfoBlockFile[nFile].AddBlock(nHeight, nTime); | |
if (fKnown) | |
vinfoBlockFile[nFile].nSize = std::max(pos.nPos + nAddSize, vinfoBlockFile[nFile].nSize); | |
else | |
vinfoBlockFile[nFile].nSize += nAddSize; | |
if (!fKnown) { | |
unsigned int nOldChunks = (pos.nPos + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE; | |
unsigned int nNewChunks = (vinfoBlockFile[nFile].nSize + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE; | |
if (nNewChunks > nOldChunks) { | |
if (fPruneMode) | |
fCheckForPruning = true; | |
if (CheckDiskSpace(nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos)) { | |
FILE *file = OpenBlockFile(pos); | |
if (file) { | |
LogPrintf("Pre-allocating up to position 0x%x in blk%05u.dat\n", nNewChunks * BLOCKFILE_CHUNK_SIZE, pos.nFile); | |
AllocateFileRange(file, pos.nPos, nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos); | |
fclose(file); | |
} | |
} | |
else | |
return state.Error("out of disk space"); | |
} | |
} | |
setDirtyFileInfo.insert(nFile); | |
return true; | |
} | |
static bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart) | |
{ | |
// Open history file to append | |
CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION); | |
if (fileout.IsNull()) | |
return error("WriteBlockToDisk: OpenBlockFile failed"); | |
// Write index header | |
unsigned int nSize = GetSerializeSize(fileout, block); | |
fileout << FLATDATA(messageStart) << nSize; | |
// Write block | |
long fileOutPos = ftell(fileout.Get()); | |
if (fileOutPos < 0) | |
return error("WriteBlockToDisk: ftell failed"); | |
pos.nPos = (unsigned int)fileOutPos; | |
fileout << block; | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment