Skip to content

Commit bc385cb

Browse files
committed
Reload trimmed header from index instead of block, block may have been pruned
1 parent 2f74306 commit bc385cb

File tree

8 files changed

+72
-38
lines changed

8 files changed

+72
-38
lines changed

src/chain.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
#include <chain.h>
77

8+
#include <validation.h> // pblocktree
9+
810
/**
911
* CChain implementation
1012
*/
@@ -48,6 +50,11 @@ CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
4850
return CBlockLocator(vHave);
4951
}
5052

53+
const CBlockIndex *CBlockIndex::untrim_to(CBlockIndex *pindexNew) const
54+
{
55+
return pblocktree->RegenerateFullIndex(this, pindexNew);
56+
}
57+
5158
const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
5259
if (pindex == nullptr) {
5360
return nullptr;

src/chain.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ class CBlockIndex
224224
}
225225

226226
void untrim();
227+
const CBlockIndex *untrim_to(CBlockIndex *pindexNew) const;
228+
227229
inline bool trimmed() const {
228230
return m_trimmed;
229231
}

src/node/blockstorage.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -408,17 +408,6 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus
408408
return true;
409409
}
410410

411-
bool ReadBlockHeaderFromDisk(CBlockHeader& header, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
412-
{
413-
// Not very efficient: read a block and throw away all but the header.
414-
CBlock tmp;
415-
if (!ReadBlockFromDisk(tmp, pindex, consensusParams)) {
416-
return false;
417-
}
418-
header = tmp.GetBlockHeader();
419-
return true;
420-
}
421-
422411
bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start)
423412
{
424413
FlatFilePos hpos = pos;

src/node/blockstorage.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus
7979
bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start);
8080
bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CBlockIndex* pindex, const CMessageHeader::MessageStartChars& message_start);
8181
// ELEMENTS:
82-
bool ReadBlockHeaderFromDisk(class CBlockHeader& header, const CBlockIndex* pindex, const Consensus::Params& consensusParams);
8382

8483
bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex);
8584
bool WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex* pindex, const CChainParams& chainparams);

src/rest.cpp

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -221,13 +221,9 @@ static bool rest_headers(const std::any& context,
221221
case RetFormat::BINARY: {
222222
CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION);
223223
for (const CBlockIndex *pindex : headers) {
224-
if (pindex->trimmed()) {
225-
CBlockHeader tmp;
226-
ReadBlockHeaderFromDisk(tmp, pindex, Params().GetConsensus());
227-
ssHeader << tmp;
228-
} else {
229-
ssHeader << pindex->GetBlockHeader();
230-
}
224+
CBlockIndex tmpBlockIndexFull;
225+
const CBlockIndex* pindexfull = pindex->untrim_to(&tmpBlockIndexFull);
226+
ssHeader << pindexfull->GetBlockHeader();
231227
}
232228

233229
std::string binaryHeader = ssHeader.str();
@@ -239,14 +235,9 @@ static bool rest_headers(const std::any& context,
239235
case RetFormat::HEX: {
240236
CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION);
241237
for (const CBlockIndex *pindex : headers) {
242-
if (pindex->trimmed()) {
243-
CBlockHeader tmp;
244-
ReadBlockHeaderFromDisk(tmp, pindex, Params().GetConsensus());
245-
ssHeader << tmp;
246-
247-
} else {
248-
ssHeader << pindex->GetBlockHeader();
249-
}
238+
CBlockIndex tmpBlockIndexFull;
239+
const CBlockIndex* pindexfull = pindex->untrim_to(&tmpBlockIndexFull);
240+
ssHeader << pindexfull->GetBlockHeader();
250241
}
251242

252243
std::string strHex = HexStr(ssHeader) + "\n";

src/rpc/blockchain.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -226,15 +226,18 @@ CBlockIndex* ParseHashOrHeight(const UniValue& param, ChainstateManager& chainma
226226
}
227227
}
228228

229-
UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex)
229+
UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex_)
230230
{
231231
// Serialize passed information without accessing chain state of the active chain!
232232
AssertLockNotHeld(cs_main); // For performance reasons
233233

234+
CBlockIndex tmpBlockIndexFull;
235+
const CBlockIndex* blockindex = blockindex_->untrim_to(&tmpBlockIndexFull);
236+
234237
UniValue result(UniValue::VOBJ);
235238
result.pushKV("hash", blockindex->GetBlockHash().GetHex());
236239
const CBlockIndex* pnext;
237-
int confirmations = ComputeNextBlockAndDepth(tip, blockindex, pnext);
240+
int confirmations = ComputeNextBlockAndDepth(tip, blockindex_, pnext);
238241
result.pushKV("confirmations", confirmations);
239242
result.pushKV("height", blockindex->nHeight);
240243
result.pushKV("version", blockindex->nVersion);
@@ -271,7 +274,7 @@ UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex
271274
}
272275
}
273276
result.pushKV("nTx", (uint64_t)blockindex->nTx);
274-
if (blockindex->pprev)
277+
if (blockindex_->pprev)
275278
result.pushKV("previousblockhash", blockindex->pprev->GetBlockHash().GetHex());
276279
if (pnext)
277280
result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex());
@@ -966,7 +969,7 @@ static RPCHelpMan getblockheader()
966969
if (!request.params[1].isNull())
967970
fVerbose = request.params[1].get_bool();
968971

969-
const CBlockIndex* pblockindex;
972+
CBlockIndex* pblockindex;
970973
const CBlockIndex* tip;
971974
{
972975
ChainstateManager& chainman = EnsureAnyChainman(request.context);
@@ -982,13 +985,9 @@ static RPCHelpMan getblockheader()
982985
if (!fVerbose)
983986
{
984987
CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
985-
if (pblockindex->trimmed()) {
986-
CBlockHeader tmp;
987-
ReadBlockHeaderFromDisk(tmp, pblockindex, Params().GetConsensus());
988-
ssBlock << tmp;
989-
} else {
990-
ssBlock << pblockindex->GetBlockHeader();
991-
}
988+
CBlockIndex tmpBlockIndexFull;
989+
const CBlockIndex* pblockindexfull = pblockindex->untrim_to(&tmpBlockIndexFull);
990+
ssBlock << pblockindexfull->GetBlockHeader();
992991
std::string strHex = HexStr(ssBlock);
993992
return strHex;
994993
}

src/txdb.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
// ELEMENTS
2020
#include <block_proof.h> // CheckProof
21+
#include <chainparams.h> // Params()
2122

2223
static constexpr uint8_t DB_COIN{'C'};
2324
static constexpr uint8_t DB_COINS{'c'};
@@ -342,6 +343,51 @@ bool CBlockTreeDB::WalkBlockIndexGutsForMaxHeight(int* nHeight) {
342343
return true;
343344
}
344345

346+
const CBlockIndex *CBlockTreeDB::RegenerateFullIndex(const CBlockIndex *pindexTrimmed, CBlockIndex *pindexNew) const
347+
{
348+
if(!pindexTrimmed->trimmed()) {
349+
return pindexTrimmed;
350+
}
351+
CBlockHeader tmp;
352+
bool BlockRead = false;
353+
{
354+
// At this point we can either be locked or unlocked depending on where we're being called
355+
// but cs_main is a RecursiveMutex, so it doesn't matter
356+
LOCK(cs_main);
357+
// In unpruned nodes, same data could be read from blocks using ReadBlockFromDisk, but that turned out to
358+
// be about 6x slower than reading from the index
359+
std::pair<uint8_t, uint256> key(DB_BLOCK_INDEX, pindexTrimmed->GetBlockHash());
360+
CDiskBlockIndex diskindex;
361+
BlockRead = this->Read(key, diskindex);
362+
tmp = diskindex.GetBlockHeader();
363+
}
364+
assert(BlockRead);
365+
// Clone the needed data from the original trimmed block
366+
pindexNew->pprev = pindexTrimmed->pprev;
367+
pindexNew->phashBlock = pindexTrimmed->phashBlock;
368+
// Construct block index object
369+
pindexNew->nHeight = pindexTrimmed->nHeight;
370+
pindexNew->nFile = pindexTrimmed->nFile;
371+
pindexNew->nDataPos = pindexTrimmed->nDataPos;
372+
pindexNew->nUndoPos = pindexTrimmed->nUndoPos;
373+
pindexNew->nVersion = pindexTrimmed->nVersion;
374+
pindexNew->hashMerkleRoot = pindexTrimmed->hashMerkleRoot;
375+
pindexNew->nTime = pindexTrimmed->nTime;
376+
pindexNew->nBits = pindexTrimmed->nBits;
377+
pindexNew->nNonce = pindexTrimmed->nNonce;
378+
pindexNew->nStatus = pindexTrimmed->nStatus;
379+
pindexNew->nTx = pindexTrimmed->nTx;
380+
381+
pindexNew->proof = tmp.proof;
382+
pindexNew->m_dynafed_params = tmp.m_dynafed_params;
383+
pindexNew->m_signblock_witness = tmp.m_signblock_witness;
384+
385+
if (pindexTrimmed->nHeight && pindexTrimmed->nHeight % 1000 == 0) {
386+
assert(CheckProof(pindexNew->GetBlockHeader(), Params().GetConsensus()));
387+
}
388+
return pindexNew;
389+
}
390+
345391
bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex, int trimBelowHeight)
346392
{
347393
std::unique_ptr<CDBIterator> pcursor(NewIterator());

src/txdb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class CBlockTreeDB : public CDBWrapper
8787
bool ReadFlag(const std::string &name, bool &fValue);
8888
bool LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex, int trimBelowHeight);
8989
// ELEMENTS:
90+
const CBlockIndex* RegenerateFullIndex(const CBlockIndex *pindexTrimmed, CBlockIndex *pindexNew) const;
9091
bool WalkBlockIndexGutsForMaxHeight(int* nHeight);
9192
bool ReadPAKList(std::vector<std::vector<unsigned char> >& offline_list, std::vector<std::vector<unsigned char> >& online_list, bool& reject);
9293
bool WritePAKList(const std::vector<std::vector<unsigned char> >& offline_list, const std::vector<std::vector<unsigned char> >& online_list, bool reject);

0 commit comments

Comments
 (0)